diff --git a/docs/pages/performance/slider-base-default-props.js b/docs/pages/performance/slider-base-default-props.js new file mode 100644 index 00000000000000..320872588f18b8 --- /dev/null +++ b/docs/pages/performance/slider-base-default-props.js @@ -0,0 +1,82 @@ +import React from 'react'; +import { SliderBase as Slider } from '@material-ui/core/Slider'; + +const PerfExample = () => { + function valuetext(value) { + return `${value}°C`; + } + + const marks = [ + { + value: 0, + label: '0°C', + }, + { + value: 20, + label: '20°C', + }, + { + value: 37, + label: '37°C', + }, + { + value: 100, + label: '100°C', + }, + ]; + + return ( + <> + + + + + + + + + ); +}; + +export default PerfExample; diff --git a/docs/pages/performance/slider-wrapper.js b/docs/pages/performance/slider-wrapper.js new file mode 100644 index 00000000000000..16e085af01aa4b --- /dev/null +++ b/docs/pages/performance/slider-wrapper.js @@ -0,0 +1,82 @@ +import React from 'react'; +import Slider from '@material-ui/core/Slider'; + +const PerfExample = () => { + function valuetext(value) { + return `${value}°C`; + } + + const marks = [ + { + value: 0, + label: '0°C', + }, + { + value: 20, + label: '20°C', + }, + { + value: 37, + label: '37°C', + }, + { + value: 100, + label: '100°C', + }, + ]; + + return ( + <> + + + + + + + + + ); +}; + +export default PerfExample; diff --git a/packages/material-ui/package.json b/packages/material-ui/package.json index 35883805fcfd63..7aa2e04ba85292 100644 --- a/packages/material-ui/package.json +++ b/packages/material-ui/package.json @@ -50,12 +50,16 @@ }, "dependencies": { "@babel/runtime": "^7.4.4", + "@emotion/core": "^10.0.28", + "@emotion/is-prop-valid": "^0.8.8", + "@emotion/styled": "^10.0.27", "@material-ui/styles": "^5.0.0-alpha.1", "@material-ui/system": "^5.0.0-alpha.1", "@material-ui/types": "^5.1.0", "@material-ui/utils": "^5.0.0-alpha.1", "@types/react-transition-group": "^4.2.0", "clsx": "^1.0.4", + "emotion-theming": "^10.0.27", "hoist-non-react-statics": "^3.3.2", "popper.js": "1.16.1-lts", "prop-types": "^15.7.2", diff --git a/packages/material-ui/src/Slider/Slider.base.js b/packages/material-ui/src/Slider/Slider.base.js new file mode 100644 index 00000000000000..3a3ee9411ecb4c --- /dev/null +++ b/packages/material-ui/src/Slider/Slider.base.js @@ -0,0 +1,738 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { chainPropTypes } from '@material-ui/utils'; +import useIsFocusVisible from '../utils/useIsFocusVisible'; +import ownerDocument from '../utils/ownerDocument'; +import useEventCallback from '../utils/useEventCallback'; +import useForkRef from '../utils/useForkRef'; +import useControlled from '../utils/useControlled'; +import ValueLabel from './ValueLabel'; + +function asc(a, b) { + return a - b; +} + +function clamp(value, min, max) { + return Math.min(Math.max(min, value), max); +} + +function findClosest(values, currentValue) { + const { index: closestIndex } = values.reduce((acc, value, index) => { + const distance = Math.abs(currentValue - value); + + if (acc === null || distance < acc.distance || distance === acc.distance) { + return { + distance, + index, + }; + } + + return acc; + }, null); + return closestIndex; +} + +function trackFinger(event, touchId) { + if (touchId.current !== undefined && event.changedTouches) { + for (let i = 0; i < event.changedTouches.length; i += 1) { + const touch = event.changedTouches[i]; + if (touch.identifier === touchId.current) { + return { + x: touch.clientX, + y: touch.clientY, + }; + } + } + + return false; + } + + return { + x: event.clientX, + y: event.clientY, + }; +} + +function valueToPercent(value, min, max) { + return ((value - min) * 100) / (max - min); +} + +function percentToValue(percent, min, max) { + return (max - min) * percent + min; +} + +function getDecimalPrecision(num) { + // This handles the case when num is very small (0.00000001), js will turn this into 1e-8. + // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine. + if (Math.abs(num) < 1) { + const parts = num.toExponential().split('e-'); + const matissaDecimalPart = parts[0].split('.')[1]; + return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10); + } + + const decimalPart = num.toString().split('.')[1]; + return decimalPart ? decimalPart.length : 0; +} + +function roundValueToStep(value, step, min) { + const nearest = Math.round((value - min) / step) * step + min; + return Number(nearest.toFixed(getDecimalPrecision(step))); +} + +function setValueIndex({ values, source, newValue, index }) { + // Performance shortcut + if (source[index] === newValue) { + return source; + } + + const output = values.slice(); + output[index] = newValue; + return output; +} + +function focusThumb({ sliderRef, activeIndex, setActive }) { + if ( + !sliderRef.current.contains(document.activeElement) || + Number(document.activeElement.getAttribute('data-index')) !== activeIndex + ) { + sliderRef.current.querySelector(`[role="slider"][data-index="${activeIndex}"]`).focus(); + } + + if (setActive) { + setActive(activeIndex); + } +} + +const axisProps = { + horizontal: { + offset: (percent) => ({ left: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + 'horizontal-reverse': { + offset: (percent) => ({ right: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + vertical: { + offset: (percent) => ({ bottom: `${percent}%` }), + leap: (percent) => ({ height: `${percent}%` }), + }, +}; + +const Identity = (x) => x; + +const Slider = React.forwardRef(function Slider(props, ref) { + const { + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledby, + 'aria-valuetext': ariaValuetext, + classes = {}, + className, + color = 'primary', + component: Component = 'span', + defaultValue, + disabled = false, + getAriaLabel, + getAriaValueText, + marks: marksProp = false, + max = 100, + min = 0, + name, + onChange, + onChangeCommitted, + onMouseDown, + orientation = 'horizontal', + scale = Identity, + step = 1, + ThumbComponent = 'span', + track = 'normal', + value: valueProp, + ValueLabelComponent = ValueLabel, + valueLabelDisplay = 'off', + valueLabelFormat = Identity, + isRtl = false, + ...other + } = props; + + const touchId = React.useRef(); + // We can't use the :active browser pseudo-classes. + // - The active state isn't triggered when clicking on the rail. + // - The active state isn't transfered when inversing a range slider. + const [active, setActive] = React.useState(-1); + const [open, setOpen] = React.useState(-1); + + const [valueDerived, setValueState] = useControlled({ + controlled: valueProp, + default: defaultValue, + name: 'Slider', + }); + + const range = Array.isArray(valueDerived); + let values = range ? valueDerived.slice().sort(asc) : [valueDerived]; + values = values.map((value) => clamp(value, min, max)); + const marks = + marksProp === true && step !== null + ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({ + value: min + step * index, + })) + : marksProp || []; + + const { isFocusVisible, onBlurVisible, ref: focusVisibleRef } = useIsFocusVisible(); + const [focusVisible, setFocusVisible] = React.useState(-1); + + const sliderRef = React.useRef(); + const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); + const handleRef = useForkRef(ref, handleFocusRef); + + const handleFocus = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + if (isFocusVisible(event)) { + setFocusVisible(index); + } + setOpen(index); + }); + const handleBlur = useEventCallback(() => { + if (focusVisible !== -1) { + setFocusVisible(-1); + onBlurVisible(); + } + setOpen(-1); + }); + const handleMouseOver = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + setOpen(index); + }); + const handleMouseLeave = useEventCallback(() => { + setOpen(-1); + }); + + const handleKeyDown = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + const value = values[index]; + const tenPercents = (max - min) / 10; + const marksValues = marks.map((mark) => mark.value); + const marksIndex = marksValues.indexOf(value); + let newValue; + const increaseKey = isRtl ? 'ArrowLeft' : 'ArrowRight'; + const decreaseKey = isRtl ? 'ArrowRight' : 'ArrowLeft'; + + switch (event.key) { + case 'Home': + newValue = min; + break; + case 'End': + newValue = max; + break; + case 'PageUp': + if (step) { + newValue = value + tenPercents; + } + break; + case 'PageDown': + if (step) { + newValue = value - tenPercents; + } + break; + case increaseKey: + case 'ArrowUp': + if (step) { + newValue = value + step; + } else { + newValue = marksValues[marksIndex + 1] || marksValues[marksValues.length - 1]; + } + break; + case decreaseKey: + case 'ArrowDown': + if (step) { + newValue = value - step; + } else { + newValue = marksValues[marksIndex - 1] || marksValues[0]; + } + break; + default: + return; + } + + // Prevent scroll of the page + event.preventDefault(); + + if (step) { + newValue = roundValueToStep(newValue, step, min); + } + + newValue = clamp(newValue, min, max); + + if (range) { + const previousValue = newValue; + newValue = setValueIndex({ + values, + source: valueDerived, + newValue, + index, + }).sort(asc); + focusThumb({ sliderRef, activeIndex: newValue.indexOf(previousValue) }); + } + + setValueState(newValue); + setFocusVisible(index); + + if (onChange) { + onChange(event, newValue); + } + if (onChangeCommitted) { + onChangeCommitted(event, newValue); + } + }); + + const previousIndex = React.useRef(); + let axis = orientation; + if (isRtl && orientation === 'horizontal') { + axis += '-reverse'; + } + + const getFingerNewValue = ({ finger, move = false, values: values2, source }) => { + const { current: slider } = sliderRef; + const { width, height, bottom, left } = slider.getBoundingClientRect(); + let percent; + + if (axis.indexOf('vertical') === 0) { + percent = (bottom - finger.y) / height; + } else { + percent = (finger.x - left) / width; + } + + if (axis.indexOf('-reverse') !== -1) { + percent = 1 - percent; + } + + let newValue; + newValue = percentToValue(percent, min, max); + if (step) { + newValue = roundValueToStep(newValue, step, min); + } else { + const marksValues = marks.map((mark) => mark.value); + const closestIndex = findClosest(marksValues, newValue); + newValue = marksValues[closestIndex]; + } + + newValue = clamp(newValue, min, max); + let activeIndex = 0; + + if (range) { + if (!move) { + activeIndex = findClosest(values2, newValue); + } else { + activeIndex = previousIndex.current; + } + + const previousValue = newValue; + newValue = setValueIndex({ + values: values2, + source, + newValue, + index: activeIndex, + }).sort(asc); + activeIndex = newValue.indexOf(previousValue); + previousIndex.current = activeIndex; + } + + return { newValue, activeIndex }; + }; + + const handleTouchMove = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue, activeIndex } = getFingerNewValue({ + finger, + move: true, + values, + source: valueDerived, + }); + + focusThumb({ sliderRef, activeIndex, setActive }); + setValueState(newValue); + + if (onChange) { + onChange(nativeEvent, newValue); + } + }); + + const handleTouchEnd = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue } = getFingerNewValue({ finger, values, source: valueDerived }); + + setActive(-1); + if (nativeEvent.type === 'touchend') { + setOpen(-1); + } + + if (onChangeCommitted) { + onChangeCommitted(nativeEvent, newValue); + } + + touchId.current = undefined; + + const doc = ownerDocument(sliderRef.current); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }); + + const handleTouchStart = useEventCallback((event) => { + // Workaround as Safari has partial support for touchAction: 'none'. + event.preventDefault(); + const touch = event.changedTouches[0]; + if (touch != null) { + // A number that uniquely identifies the current finger in the touch session. + touchId.current = touch.identifier; + } + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('touchmove', handleTouchMove); + doc.addEventListener('touchend', handleTouchEnd); + }); + + React.useEffect(() => { + const { current: slider } = sliderRef; + slider.addEventListener('touchstart', handleTouchStart); + const doc = ownerDocument(slider); + + return () => { + slider.removeEventListener('touchstart', handleTouchStart); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }; + }, [handleTouchEnd, handleTouchMove, handleTouchStart]); + + const handleMouseDown = useEventCallback((event) => { + if (onMouseDown) { + onMouseDown(event); + } + + event.preventDefault(); + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('mousemove', handleTouchMove); + doc.addEventListener('mouseup', handleTouchEnd); + }); + + const trackOffset = valueToPercent(range ? values[0] : min, min, max); + const trackLeap = valueToPercent(values[values.length - 1], min, max) - trackOffset; + const trackStyle = { + ...axisProps[axis].offset(trackOffset), + ...axisProps[axis].leap(trackLeap), + }; + + return ( + + + + + {marks.map((mark, index) => { + const percent = valueToPercent(mark.value, min, max); + const style = axisProps[axis].offset(percent); + + let markActive; + if (track === false) { + markActive = values.indexOf(mark.value) !== -1; + } else { + 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])); + } + + return ( + + + {mark.label != null ? ( + + {mark.label} + + ) : null} + + ); + })} + {values.map((value, index) => { + const percent = valueToPercent(value, min, max); + const style = axisProps[axis].offset(percent); + + return ( + + + + ); + })} + + ); +}); + +Slider.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the d.ts file and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The label of the slider. + */ + 'aria-label': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-label'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaLabel` prop instead of `aria-label` when using a range slider.', + ); + } + + return null; + }), + /** + * The id of the element containing a label for the slider. + */ + 'aria-labelledby': PropTypes.string, + /** + * A string value that provides a user-friendly name for the current value of the slider. + */ + 'aria-valuetext': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-valuetext'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaValueText` prop instead of `aria-valuetext` when using a range slider.', + ); + } + + return null; + }), + /** + * @ignore + */ + children: PropTypes.node, + /** + * Override or extend the styles applied to the component. + * See [CSS API](#css) below for more details. + */ + classes: PropTypes.object, + /** + * @ignore + */ + className: PropTypes.string, + /** + * The color of the component. It supports those theme colors that make sense for this component. + */ + color: PropTypes.oneOf(['primary', 'secondary']), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The default element value. Use when the component is not controlled. + */ + defaultValue: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * If `true`, the slider will be disabled. + */ + disabled: PropTypes.bool, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider. + * + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaLabel: PropTypes.func, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider. + * + * @param {number} value The thumb label's value to format. + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaValueText: PropTypes.func, + /** + * Indicates whether the theme context has rtl direction. It is set automatically. + */ + isRtl: PropTypes.boolean, + /** + * Marks indicate predetermined values to which the user can move the slider. + * If `true` the marks will be spaced according the value of the `step` prop. + * If an array, it should contain objects with `value` and an optional `label` keys. + */ + marks: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.node, + value: PropTypes.number.isRequired, + }), + ), + PropTypes.bool, + ]), + /** + * The maximum allowed value of the slider. + * Should not be equal to min. + */ + max: PropTypes.number, + /** + * The minimum allowed value of the slider. + * Should not be equal to max. + */ + min: PropTypes.number, + /** + * Name attribute of the hidden `input` element. + */ + name: PropTypes.string, + /** + * Callback function that is fired when the slider's value changed. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChange: PropTypes.func, + /** + * Callback function that is fired when the `mouseup` is triggered. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChangeCommitted: PropTypes.func, + /** + * @ignore + */ + onMouseDown: PropTypes.func, + /** + * The slider orientation. + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A transformation function, to change the scale of the slider. + */ + scale: PropTypes.func, + /** + * The granularity with which the slider can step through values. (A "discrete" slider.) + * The `min` prop serves as the origin for the valid values. + * We recommend (max - min) to be evenly divisible by the step. + * + * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. + */ + step: PropTypes.number, + /** + * The component used to display the value label. + */ + ThumbComponent: PropTypes.elementType, + /** + * The track presentation: + * + * - `normal` the track will render a bar representing the slider value. + * - `inverted` the track will render a bar representing the remaining slider value. + * - `false` the track will render without a bar. + */ + track: PropTypes.oneOf(['inverted', 'normal', false]), + /** + * The value of the slider. + * For ranged sliders, provide an array with two values. + */ + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * The value label component. + */ + ValueLabelComponent: PropTypes.elementType, + /** + * Controls when the value label is displayed: + * + * - `auto` the value label will display when the thumb is hovered or focused. + * - `on` will display persistently. + * - `off` will never display. + */ + valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), + /** + * The format function the value label's value. + * + * When a function is provided, it should have the following signature: + * + * - {number} value The value label's value to format + * - {number} index The value label's index to format + */ + valueLabelFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), +}; + +export default Slider; diff --git a/packages/material-ui/src/Slider/Slider.js b/packages/material-ui/src/Slider/Slider.js index 1abb49565d0975..e9766a969ed119 100644 --- a/packages/material-ui/src/Slider/Slider.js +++ b/packages/material-ui/src/Slider/Slider.js @@ -1,129 +1,10 @@ import * as React from 'react'; -import PropTypes from 'prop-types'; import clsx from 'clsx'; -import { chainPropTypes } from '@material-ui/utils'; -import withStyles from '../styles/withStyles'; import useTheme from '../styles/useTheme'; +import withStyles from '../styles/withStyles'; import { fade, lighten, darken } from '../styles/colorManipulator'; -import useIsFocusVisible from '../utils/useIsFocusVisible'; -import ownerDocument from '../utils/ownerDocument'; -import useEventCallback from '../utils/useEventCallback'; -import useForkRef from '../utils/useForkRef'; import capitalize from '../utils/capitalize'; -import useControlled from '../utils/useControlled'; -import ValueLabel from './ValueLabel'; - -function asc(a, b) { - return a - b; -} - -function clamp(value, min, max) { - return Math.min(Math.max(min, value), max); -} - -function findClosest(values, currentValue) { - const { index: closestIndex } = values.reduce((acc, value, index) => { - const distance = Math.abs(currentValue - value); - - if (acc === null || distance < acc.distance || distance === acc.distance) { - return { - distance, - index, - }; - } - - return acc; - }, null); - return closestIndex; -} - -function trackFinger(event, touchId) { - if (touchId.current !== undefined && event.changedTouches) { - for (let i = 0; i < event.changedTouches.length; i += 1) { - const touch = event.changedTouches[i]; - if (touch.identifier === touchId.current) { - return { - x: touch.clientX, - y: touch.clientY, - }; - } - } - - return false; - } - - return { - x: event.clientX, - y: event.clientY, - }; -} - -function valueToPercent(value, min, max) { - return ((value - min) * 100) / (max - min); -} - -function percentToValue(percent, min, max) { - return (max - min) * percent + min; -} - -function getDecimalPrecision(num) { - // This handles the case when num is very small (0.00000001), js will turn this into 1e-8. - // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine. - if (Math.abs(num) < 1) { - const parts = num.toExponential().split('e-'); - const matissaDecimalPart = parts[0].split('.')[1]; - return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10); - } - - const decimalPart = num.toString().split('.')[1]; - return decimalPart ? decimalPart.length : 0; -} - -function roundValueToStep(value, step, min) { - const nearest = Math.round((value - min) / step) * step + min; - return Number(nearest.toFixed(getDecimalPrecision(step))); -} - -function setValueIndex({ values, source, newValue, index }) { - // Performance shortcut - if (source[index] === newValue) { - return source; - } - - const output = values.slice(); - output[index] = newValue; - return output; -} - -function focusThumb({ sliderRef, activeIndex, setActive }) { - if ( - !sliderRef.current.contains(document.activeElement) || - Number(document.activeElement.getAttribute('data-index')) !== activeIndex - ) { - sliderRef.current.querySelector(`[role="slider"][data-index="${activeIndex}"]`).focus(); - } - - if (setActive) { - setActive(activeIndex); - } -} - -const axisProps = { - horizontal: { - offset: (percent) => ({ left: `${percent}%` }), - leap: (percent) => ({ width: `${percent}%` }), - }, - 'horizontal-reverse': { - offset: (percent) => ({ right: `${percent}%` }), - leap: (percent) => ({ width: `${percent}%` }), - }, - vertical: { - offset: (percent) => ({ bottom: `${percent}%` }), - leap: (percent) => ({ height: `${percent}%` }), - }, -}; - -const Identity = (x) => x; +import SliderBase from './Slider.base'; export const styles = (theme) => ({ /* Styles applied to the root element. */ @@ -339,54 +220,20 @@ export const styles = (theme) => ({ }, }); -const Slider = React.forwardRef(function Slider(props, ref) { +const useSliderClasses = (props) => { const { - 'aria-label': ariaLabel, - 'aria-labelledby': ariaLabelledby, - 'aria-valuetext': ariaValuetext, classes, className, color = 'primary', - component: Component = 'span', - defaultValue, disabled = false, - getAriaLabel, - getAriaValueText, marks: marksProp = false, - max = 100, - min = 0, - name, - onChange, - onChangeCommitted, - onMouseDown, orientation = 'horizontal', - scale = Identity, step = 1, - ThumbComponent = 'span', track = 'normal', - value: valueProp, - ValueLabelComponent = ValueLabel, - valueLabelDisplay = 'off', - valueLabelFormat = Identity, - ...other + max = 100, + min = 0, } = props; - const theme = useTheme(); - const touchId = React.useRef(); - // We can't use the :active browser pseudo-classes. - // - The active state isn't triggered when clicking on the rail. - // - The active state isn't transfered when inversing a range slider. - const [active, setActive] = React.useState(-1); - const [open, setOpen] = React.useState(-1); - - const [valueDerived, setValueState] = useControlled({ - controlled: valueProp, - default: defaultValue, - name: 'Slider', - }); - const range = Array.isArray(valueDerived); - let values = range ? valueDerived.slice().sort(asc) : [valueDerived]; - values = values.map((value) => clamp(value, min, max)); const marks = marksProp === true && step !== null ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({ @@ -394,581 +241,40 @@ const Slider = React.forwardRef(function Slider(props, ref) { })) : marksProp || []; - const { isFocusVisible, onBlurVisible, ref: focusVisibleRef } = useIsFocusVisible(); - const [focusVisible, setFocusVisible] = React.useState(-1); - - const sliderRef = React.useRef(); - const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); - const handleRef = useForkRef(ref, handleFocusRef); - - const handleFocus = useEventCallback((event) => { - const index = Number(event.currentTarget.getAttribute('data-index')); - if (isFocusVisible(event)) { - setFocusVisible(index); - } - setOpen(index); - }); - const handleBlur = useEventCallback(() => { - if (focusVisible !== -1) { - setFocusVisible(-1); - onBlurVisible(); - } - setOpen(-1); - }); - const handleMouseOver = useEventCallback((event) => { - const index = Number(event.currentTarget.getAttribute('data-index')); - setOpen(index); - }); - const handleMouseLeave = useEventCallback(() => { - setOpen(-1); - }); - - const isRtl = theme.direction === 'rtl'; - - const handleKeyDown = useEventCallback((event) => { - const index = Number(event.currentTarget.getAttribute('data-index')); - const value = values[index]; - const tenPercents = (max - min) / 10; - const marksValues = marks.map((mark) => mark.value); - const marksIndex = marksValues.indexOf(value); - let newValue; - const increaseKey = isRtl ? 'ArrowLeft' : 'ArrowRight'; - const decreaseKey = isRtl ? 'ArrowRight' : 'ArrowLeft'; - - switch (event.key) { - case 'Home': - newValue = min; - break; - case 'End': - newValue = max; - break; - case 'PageUp': - if (step) { - newValue = value + tenPercents; - } - break; - case 'PageDown': - if (step) { - newValue = value - tenPercents; - } - break; - case increaseKey: - case 'ArrowUp': - if (step) { - newValue = value + step; - } else { - newValue = marksValues[marksIndex + 1] || marksValues[marksValues.length - 1]; - } - break; - case decreaseKey: - case 'ArrowDown': - if (step) { - newValue = value - step; - } else { - newValue = marksValues[marksIndex - 1] || marksValues[0]; - } - break; - default: - return; - } - - // Prevent scroll of the page - event.preventDefault(); - - if (step) { - newValue = roundValueToStep(newValue, step, min); - } - - newValue = clamp(newValue, min, max); - - if (range) { - const previousValue = newValue; - newValue = setValueIndex({ - values, - source: valueDerived, - newValue, - index, - }).sort(asc); - focusThumb({ sliderRef, activeIndex: newValue.indexOf(previousValue) }); - } - - setValueState(newValue); - setFocusVisible(index); - - if (onChange) { - onChange(event, newValue); - } - if (onChangeCommitted) { - onChangeCommitted(event, newValue); - } - }); - - const previousIndex = React.useRef(); - let axis = orientation; - if (isRtl && orientation === 'horizontal') { - axis += '-reverse'; - } - - const getFingerNewValue = ({ finger, move = false, values: values2, source }) => { - const { current: slider } = sliderRef; - const { width, height, bottom, left } = slider.getBoundingClientRect(); - let percent; - - if (axis.indexOf('vertical') === 0) { - percent = (bottom - finger.y) / height; - } else { - percent = (finger.x - left) / width; - } - - if (axis.indexOf('-reverse') !== -1) { - percent = 1 - percent; - } - - let newValue; - newValue = percentToValue(percent, min, max); - if (step) { - newValue = roundValueToStep(newValue, step, min); - } else { - const marksValues = marks.map((mark) => mark.value); - const closestIndex = findClosest(marksValues, newValue); - newValue = marksValues[closestIndex]; - } - - newValue = clamp(newValue, min, max); - let activeIndex = 0; - - if (range) { - if (!move) { - activeIndex = findClosest(values2, newValue); - } else { - activeIndex = previousIndex.current; - } - - const previousValue = newValue; - newValue = setValueIndex({ - values: values2, - source, - newValue, - index: activeIndex, - }).sort(asc); - activeIndex = newValue.indexOf(previousValue); - previousIndex.current = activeIndex; - } - - return { newValue, activeIndex }; - }; - - const handleTouchMove = useEventCallback((nativeEvent) => { - const finger = trackFinger(nativeEvent, touchId); - - if (!finger) { - return; - } - - const { newValue, activeIndex } = getFingerNewValue({ - finger, - move: true, - values, - source: valueDerived, - }); - - focusThumb({ sliderRef, activeIndex, setActive }); - setValueState(newValue); - - if (onChange) { - onChange(nativeEvent, newValue); - } - }); - - const handleTouchEnd = useEventCallback((nativeEvent) => { - const finger = trackFinger(nativeEvent, touchId); - - if (!finger) { - return; - } - - const { newValue } = getFingerNewValue({ finger, values, source: valueDerived }); - - setActive(-1); - if (nativeEvent.type === 'touchend') { - setOpen(-1); - } - - if (onChangeCommitted) { - onChangeCommitted(nativeEvent, newValue); - } - - touchId.current = undefined; - - const doc = ownerDocument(sliderRef.current); - doc.removeEventListener('mousemove', handleTouchMove); - doc.removeEventListener('mouseup', handleTouchEnd); - doc.removeEventListener('touchmove', handleTouchMove); - doc.removeEventListener('touchend', handleTouchEnd); - }); - - const handleTouchStart = useEventCallback((event) => { - // Workaround as Safari has partial support for touchAction: 'none'. - event.preventDefault(); - const touch = event.changedTouches[0]; - if (touch != null) { - // A number that uniquely identifies the current finger in the touch session. - touchId.current = touch.identifier; - } - const finger = trackFinger(event, touchId); - const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); - focusThumb({ sliderRef, activeIndex, setActive }); - - setValueState(newValue); - - if (onChange) { - onChange(event, newValue); - } - - const doc = ownerDocument(sliderRef.current); - doc.addEventListener('touchmove', handleTouchMove); - doc.addEventListener('touchend', handleTouchEnd); - }); - - React.useEffect(() => { - const { current: slider } = sliderRef; - slider.addEventListener('touchstart', handleTouchStart); - const doc = ownerDocument(slider); - - return () => { - slider.removeEventListener('touchstart', handleTouchStart); - doc.removeEventListener('mousemove', handleTouchMove); - doc.removeEventListener('mouseup', handleTouchEnd); - doc.removeEventListener('touchmove', handleTouchMove); - doc.removeEventListener('touchend', handleTouchEnd); - }; - }, [handleTouchEnd, handleTouchMove, handleTouchStart]); - - const handleMouseDown = useEventCallback((event) => { - if (onMouseDown) { - onMouseDown(event); - } - - event.preventDefault(); - const finger = trackFinger(event, touchId); - const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); - focusThumb({ sliderRef, activeIndex, setActive }); - - setValueState(newValue); - - if (onChange) { - onChange(event, newValue); - } - - const doc = ownerDocument(sliderRef.current); - doc.addEventListener('mousemove', handleTouchMove); - doc.addEventListener('mouseup', handleTouchEnd); - }); - - const trackOffset = valueToPercent(range ? values[0] : min, min, max); - const trackLeap = valueToPercent(values[values.length - 1], min, max) - trackOffset; - const trackStyle = { - ...axisProps[axis].offset(trackOffset), - ...axisProps[axis].leap(trackLeap), + return { + root: clsx( + classes.root, + classes[`color${capitalize(color)}`], + { + [classes.disabled]: disabled, + [classes.marked]: marks.length > 0 && marks.some((mark) => mark.label), + [classes.vertical]: orientation === 'vertical', + [classes.trackInverted]: track === 'inverted', + [classes.trackFalse]: track === false, + }, + className, + ), + rail: classes.rail, + track: classes.track, + mark: classes.mark, + markActive: classes.markActive, + markLabel: classes.markLabel, + markLabelActive: classes.markLabelActive, + valueLabel: classes.valueLabel, + thumb: clsx(classes.thumb, classes[`thumbColor${capitalize(color)}`], { + [classes.disabled]: disabled, + }), + thumbActive: classes.active, + thumbFocusVisible: classes.focusVisible, }; +}; - return ( - 0 && marks.some((mark) => mark.label), - [classes.vertical]: orientation === 'vertical', - [classes.trackInverted]: track === 'inverted', - [classes.trackFalse]: track === false, - }, - className, - )} - onMouseDown={handleMouseDown} - {...other} - > - - - - {marks.map((mark, index) => { - const percent = valueToPercent(mark.value, min, max); - const style = axisProps[axis].offset(percent); - - let markActive; - if (track === false) { - markActive = values.indexOf(mark.value) !== -1; - } else { - 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])); - } - - return ( - - - {mark.label != null ? ( - - {mark.label} - - ) : null} - - ); - })} - {values.map((value, index) => { - const percent = valueToPercent(value, min, max); - const style = axisProps[axis].offset(percent); +const Slider = React.forwardRef(function Slider(props, ref) { + const cs = useSliderClasses(props); + const theme = useTheme(); + const isRtl = theme.direction === 'rtl'; - return ( - - - - ); - })} - - ); + return ; }); -Slider.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the d.ts file and run "yarn proptypes" | - // ---------------------------------------------------------------------- - /** - * The label of the slider. - */ - 'aria-label': chainPropTypes(PropTypes.string, (props) => { - const range = Array.isArray(props.value || props.defaultValue); - - if (range && props['aria-label'] != null) { - return new Error( - 'Material-UI: You need to use the `getAriaLabel` prop instead of `aria-label` when using a range slider.', - ); - } - - return null; - }), - /** - * The id of the element containing a label for the slider. - */ - 'aria-labelledby': PropTypes.string, - /** - * A string value that provides a user-friendly name for the current value of the slider. - */ - 'aria-valuetext': chainPropTypes(PropTypes.string, (props) => { - const range = Array.isArray(props.value || props.defaultValue); - - if (range && props['aria-valuetext'] != null) { - return new Error( - 'Material-UI: You need to use the `getAriaValueText` prop instead of `aria-valuetext` when using a range slider.', - ); - } - - return null; - }), - /** - * @ignore - */ - children: PropTypes.node, - /** - * Override or extend the styles applied to the component. - * See [CSS API](#css) below for more details. - */ - classes: PropTypes.object, - /** - * @ignore - */ - className: PropTypes.string, - /** - * The color of the component. It supports those theme colors that make sense for this component. - */ - color: PropTypes.oneOf(['primary', 'secondary']), - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, - /** - * The default element value. Use when the component is not controlled. - */ - defaultValue: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), - /** - * If `true`, the slider will be disabled. - */ - disabled: PropTypes.bool, - /** - * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider. - * - * @param {number} index The thumb label's index to format. - * @returns {string} - */ - getAriaLabel: PropTypes.func, - /** - * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider. - * - * @param {number} value The thumb label's value to format. - * @param {number} index The thumb label's index to format. - * @returns {string} - */ - getAriaValueText: PropTypes.func, - /** - * Marks indicate predetermined values to which the user can move the slider. - * If `true` the marks will be spaced according the value of the `step` prop. - * If an array, it should contain objects with `value` and an optional `label` keys. - */ - marks: PropTypes.oneOfType([ - PropTypes.arrayOf( - PropTypes.shape({ - label: PropTypes.node, - value: PropTypes.number.isRequired, - }), - ), - PropTypes.bool, - ]), - /** - * The maximum allowed value of the slider. - * Should not be equal to min. - */ - max: PropTypes.number, - /** - * The minimum allowed value of the slider. - * Should not be equal to max. - */ - min: PropTypes.number, - /** - * Name attribute of the hidden `input` element. - */ - name: PropTypes.string, - /** - * Callback function that is fired when the slider's value changed. - * - * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. - * @param {number | number[]} value The new value. - */ - onChange: PropTypes.func, - /** - * Callback function that is fired when the `mouseup` is triggered. - * - * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. - * @param {number | number[]} value The new value. - */ - onChangeCommitted: PropTypes.func, - /** - * @ignore - */ - onMouseDown: PropTypes.func, - /** - * The slider orientation. - */ - orientation: PropTypes.oneOf(['horizontal', 'vertical']), - /** - * A transformation function, to change the scale of the slider. - */ - scale: PropTypes.func, - /** - * The granularity with which the slider can step through values. (A "discrete" slider.) - * The `min` prop serves as the origin for the valid values. - * We recommend (max - min) to be evenly divisible by the step. - * - * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. - */ - step: PropTypes.number, - /** - * The component used to display the value label. - */ - ThumbComponent: PropTypes.elementType, - /** - * The track presentation: - * - * - `normal` the track will render a bar representing the slider value. - * - `inverted` the track will render a bar representing the remaining slider value. - * - `false` the track will render without a bar. - */ - track: PropTypes.oneOf(['inverted', 'normal', false]), - /** - * The value of the slider. - * For ranged sliders, provide an array with two values. - */ - value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), - /** - * The value label component. - */ - ValueLabelComponent: PropTypes.elementType, - /** - * Controls when the value label is displayed: - * - * - `auto` the value label will display when the thumb is hovered or focused. - * - `on` will display persistently. - * - `off` will never display. - */ - valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), - /** - * The format function the value label's value. - * - * When a function is provided, it should have the following signature: - * - * - {number} value The value label's value to format - * - {number} index The value label's index to format - */ - valueLabelFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), -}; - export default withStyles(styles, { name: 'MuiSlider' })(Slider); diff --git a/packages/material-ui/src/Slider/SliderComponents.base.js b/packages/material-ui/src/Slider/SliderComponents.base.js new file mode 100644 index 00000000000000..771abd0e2c3868 --- /dev/null +++ b/packages/material-ui/src/Slider/SliderComponents.base.js @@ -0,0 +1,832 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { chainPropTypes } from '@material-ui/utils'; +import useIsFocusVisible from '../utils/useIsFocusVisible'; +import ownerDocument from '../utils/ownerDocument'; +import useEventCallback from '../utils/useEventCallback'; +import useForkRef from '../utils/useForkRef'; +import useControlled from '../utils/useControlled'; +import ValueLabelComponent from './ValueLabel'; +import { getClassWithValueAndKey, getClassWithKeyOnly } from '../styles/classNameBuilders'; + +function asc(a, b) { + return a - b; +} + +function clamp(value, min, max) { + return Math.min(Math.max(min, value), max); +} + +function findClosest(values, currentValue) { + const { index: closestIndex } = values.reduce((acc, value, index) => { + const distance = Math.abs(currentValue - value); + + if (acc === null || distance < acc.distance || distance === acc.distance) { + return { + distance, + index, + }; + } + + return acc; + }, null); + return closestIndex; +} + +function trackFinger(event, touchId) { + if (touchId.current !== undefined && event.changedTouches) { + for (let i = 0; i < event.changedTouches.length; i += 1) { + const touch = event.changedTouches[i]; + if (touch.identifier === touchId.current) { + return { + x: touch.clientX, + y: touch.clientY, + }; + } + } + + return false; + } + + return { + x: event.clientX, + y: event.clientY, + }; +} + +function valueToPercent(value, min, max) { + return ((value - min) * 100) / (max - min); +} + +function percentToValue(percent, min, max) { + return (max - min) * percent + min; +} + +function getDecimalPrecision(num) { + // This handles the case when num is very small (0.00000001), js will turn this into 1e-8. + // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine. + if (Math.abs(num) < 1) { + const parts = num.toExponential().split('e-'); + const matissaDecimalPart = parts[0].split('.')[1]; + return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10); + } + + const decimalPart = num.toString().split('.')[1]; + return decimalPart ? decimalPart.length : 0; +} + +function roundValueToStep(value, step, min) { + const nearest = Math.round((value - min) / step) * step + min; + return Number(nearest.toFixed(getDecimalPrecision(step))); +} + +function setValueIndex({ values, source, newValue, index }) { + // Performance shortcut + if (source[index] === newValue) { + return source; + } + + const output = values.slice(); + output[index] = newValue; + return output; +} + +function focusThumb({ sliderRef, activeIndex, setActive }) { + if ( + !sliderRef.current.contains(document.activeElement) || + Number(document.activeElement.getAttribute('data-index')) !== activeIndex + ) { + sliderRef.current.querySelector(`[role="slider"][data-index="${activeIndex}"]`).focus(); + } + + if (setActive) { + setActive(activeIndex); + } +} + +const axisProps = { + horizontal: { + offset: (percent) => ({ left: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + 'horizontal-reverse': { + offset: (percent) => ({ right: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + vertical: { + offset: (percent) => ({ bottom: `${percent}%` }), + leap: (percent) => ({ height: `${percent}%` }), + }, +}; + +const Identity = (x) => x; + +const useSliderClasses = (props) => { + const slots = ['root', 'rail', 'thumb', 'track', 'valueLabel', 'mark', 'markLabel']; + const utilityClasses = {}; + + slots.forEach((slot) => { + const slotClassName = `MuiSlider-${slot === 'root' ? '' : slot}`; + utilityClasses[slot] = clsx( + slotClassName, + getClassWithValueAndKey(props.color, 'color', slotClassName), + getClassWithValueAndKey(props.orientation, 'orientation', slotClassName), + getClassWithKeyOnly(props.disabled, 'disabled', slotClassName), + getClassWithKeyOnly(props.marked, 'marked', slotClassName), + getClassWithValueAndKey(props.track, 'track', slotClassName), + getClassWithKeyOnly(props.focusVisible, 'focusVisible', slotClassName), + ); + }); + + return utilityClasses; +}; + +const Slider = React.forwardRef(function Slider(props, ref) { + const { + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledby, + 'aria-valuetext': ariaValuetext, + className, + classes = {}, + color = 'primary', + component: Component = 'span', + defaultValue, + disabled = false, + getAriaLabel, + getAriaValueText, + marks: marksProp = false, + max = 100, + min = 0, + name, + onChange, + onChangeCommitted, + onMouseDown, + orientation = 'horizontal', + scale = Identity, + step = 1, + track = 'normal', + value: valueProp, + valueLabelDisplay = 'off', + valueLabelFormat = Identity, + isRtl = false, + components = {}, + componentsProps = {}, + ...other + } = props; + + const touchId = React.useRef(); + // We can't use the :active browser pseudo-classes. + // - The active state isn't triggered when clicking on the rail. + // - The active state isn't transfered when inversing a range slider. + const [active, setActive] = React.useState(-1); + const [open, setOpen] = React.useState(-1); + + const [valueDerived, setValueState] = useControlled({ + controlled: valueProp, + default: defaultValue, + name: 'Slider', + }); + + const range = Array.isArray(valueDerived); + let values = range ? valueDerived.slice().sort(asc) : [valueDerived]; + values = values.map((value) => clamp(value, min, max)); + const marks = + marksProp === true && step !== null + ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({ + value: min + step * index, + })) + : marksProp || []; + + const { isFocusVisible, onBlurVisible, ref: focusVisibleRef } = useIsFocusVisible(); + const [focusVisible, setFocusVisible] = React.useState(-1); + + const sliderRef = React.useRef(); + const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); + const handleRef = useForkRef(ref, handleFocusRef); + + const handleFocus = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + if (isFocusVisible(event)) { + setFocusVisible(index); + } + setOpen(index); + }); + const handleBlur = useEventCallback(() => { + if (focusVisible !== -1) { + setFocusVisible(-1); + onBlurVisible(); + } + setOpen(-1); + }); + const handleMouseOver = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + setOpen(index); + }); + const handleMouseLeave = useEventCallback(() => { + setOpen(-1); + }); + + const handleKeyDown = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + const value = values[index]; + const tenPercents = (max - min) / 10; + const marksValues = marks.map((mark) => mark.value); + const marksIndex = marksValues.indexOf(value); + let newValue; + const increaseKey = isRtl ? 'ArrowLeft' : 'ArrowRight'; + const decreaseKey = isRtl ? 'ArrowRight' : 'ArrowLeft'; + + switch (event.key) { + case 'Home': + newValue = min; + break; + case 'End': + newValue = max; + break; + case 'PageUp': + if (step) { + newValue = value + tenPercents; + } + break; + case 'PageDown': + if (step) { + newValue = value - tenPercents; + } + break; + case increaseKey: + case 'ArrowUp': + if (step) { + newValue = value + step; + } else { + newValue = marksValues[marksIndex + 1] || marksValues[marksValues.length - 1]; + } + break; + case decreaseKey: + case 'ArrowDown': + if (step) { + newValue = value - step; + } else { + newValue = marksValues[marksIndex - 1] || marksValues[0]; + } + break; + default: + return; + } + + // Prevent scroll of the page + event.preventDefault(); + + if (step) { + newValue = roundValueToStep(newValue, step, min); + } + + newValue = clamp(newValue, min, max); + + if (range) { + const previousValue = newValue; + newValue = setValueIndex({ + values, + source: valueDerived, + newValue, + index, + }).sort(asc); + focusThumb({ sliderRef, activeIndex: newValue.indexOf(previousValue) }); + } + + setValueState(newValue); + setFocusVisible(index); + + if (onChange) { + onChange(event, newValue); + } + if (onChangeCommitted) { + onChangeCommitted(event, newValue); + } + }); + + const previousIndex = React.useRef(); + let axis = orientation; + if (isRtl && orientation === 'horizontal') { + axis += '-reverse'; + } + + const getFingerNewValue = ({ finger, move = false, values: values2, source }) => { + const { current: slider } = sliderRef; + const { width, height, bottom, left } = slider.getBoundingClientRect(); + let percent; + + if (axis.indexOf('vertical') === 0) { + percent = (bottom - finger.y) / height; + } else { + percent = (finger.x - left) / width; + } + + if (axis.indexOf('-reverse') !== -1) { + percent = 1 - percent; + } + + let newValue; + newValue = percentToValue(percent, min, max); + if (step) { + newValue = roundValueToStep(newValue, step, min); + } else { + const marksValues = marks.map((mark) => mark.value); + const closestIndex = findClosest(marksValues, newValue); + newValue = marksValues[closestIndex]; + } + + newValue = clamp(newValue, min, max); + let activeIndex = 0; + + if (range) { + if (!move) { + activeIndex = findClosest(values2, newValue); + } else { + activeIndex = previousIndex.current; + } + + const previousValue = newValue; + newValue = setValueIndex({ + values: values2, + source, + newValue, + index: activeIndex, + }).sort(asc); + activeIndex = newValue.indexOf(previousValue); + previousIndex.current = activeIndex; + } + + return { newValue, activeIndex }; + }; + + const handleTouchMove = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue, activeIndex } = getFingerNewValue({ + finger, + move: true, + values, + source: valueDerived, + }); + + focusThumb({ sliderRef, activeIndex, setActive }); + setValueState(newValue); + + if (onChange) { + onChange(nativeEvent, newValue); + } + }); + + const handleTouchEnd = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue } = getFingerNewValue({ finger, values, source: valueDerived }); + + setActive(-1); + if (nativeEvent.type === 'touchend') { + setOpen(-1); + } + + if (onChangeCommitted) { + onChangeCommitted(nativeEvent, newValue); + } + + touchId.current = undefined; + + const doc = ownerDocument(sliderRef.current); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }); + + const handleTouchStart = useEventCallback((event) => { + // Workaround as Safari has partial support for touchAction: 'none'. + event.preventDefault(); + const touch = event.changedTouches[0]; + if (touch != null) { + // A number that uniquely identifies the current finger in the touch session. + touchId.current = touch.identifier; + } + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('touchmove', handleTouchMove); + doc.addEventListener('touchend', handleTouchEnd); + }); + + React.useEffect(() => { + const { current: slider } = sliderRef; + slider.addEventListener('touchstart', handleTouchStart); + const doc = ownerDocument(slider); + + return () => { + slider.removeEventListener('touchstart', handleTouchStart); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }; + }, [handleTouchEnd, handleTouchMove, handleTouchStart]); + + const handleMouseDown = useEventCallback((event) => { + if (onMouseDown) { + onMouseDown(event); + } + + event.preventDefault(); + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('mousemove', handleTouchMove); + doc.addEventListener('mouseup', handleTouchEnd); + }); + + const trackOffset = valueToPercent(range ? values[0] : min, min, max); + const trackLeap = valueToPercent(values[values.length - 1], min, max) - trackOffset; + const trackStyle = { + ...axisProps[axis].offset(trackOffset), + ...axisProps[axis].leap(trackLeap), + }; + + const Root = components.root || 'span'; + const rootProps = componentsProps.root || {}; + + const Rail = components.rail || 'span'; + const railProps = componentsProps.rail || {}; + + const Track = components.track || 'span'; + const trackProps = componentsProps.track || {}; + + const Thumb = components.thumb || 'span'; + const thumbProps = componentsProps.thumb || {}; + + const ValueLabel = components.valueLabel || ValueLabelComponent; + const valueLabelProps = componentsProps.valueLabel || {}; + + const Mark = components.mark || 'span'; + const markProps = componentsProps.mark || {}; + + const MarkLabel = components.markLabel || 'span'; + const markLabelProps = componentsProps.markLabel || {}; + + // all props with defaults + // consider extracting to hook an reusing the lint rule for the varints + const stateAndProps = { + ...props, + color, + disabled, + max, + min, + orientation, + scale, + step, + track, + valueLabelDisplay, + valueLabelFormat, + isRtl, + }; + + const utilityClasses = useSliderClasses({ + ...stateAndProps, + marked: marks.length > 0 && marks.some((mark) => mark.label), + }); + + return ( + 0 && marks.some((mark) => mark.label)} + {...stateAndProps} + {...rootProps} + > + + + + {marks.map((mark, index) => { + const percent = valueToPercent(mark.value, min, max); + const style = axisProps[axis].offset(percent); + + let markActive; + if (track === false) { + markActive = values.indexOf(mark.value) !== -1; + } else { + 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])); + } + + return ( + + + {mark.label != null ? ( + + {mark.label} + + ) : null} + + ); + })} + {values.map((value, index) => { + const percent = valueToPercent(value, min, max); + const style = axisProps[axis].offset(percent); + + return ( + + + + ); + })} + + ); +}); + +Slider.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the d.ts file and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The label of the slider. + */ + 'aria-label': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-label'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaLabel` prop instead of `aria-label` when using a range slider.', + ); + } + + return null; + }), + /** + * The id of the element containing a label for the slider. + */ + 'aria-labelledby': PropTypes.string, + /** + * A string value that provides a user-friendly name for the current value of the slider. + */ + 'aria-valuetext': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-valuetext'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaValueText` prop instead of `aria-valuetext` when using a range slider.', + ); + } + + return null; + }), + /** + * @ignore + */ + children: PropTypes.node, + /** + * Override or extend the styles applied to the component. + * See [CSS API](#css) below for more details. + */ + classes: PropTypes.object, + /** + * @ignore + */ + className: PropTypes.string, + /** + * The color of the component. It supports those theme colors that make sense for this component. + */ + color: PropTypes.oneOf(['primary', 'secondary']), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The default element value. Use when the component is not controlled. + */ + defaultValue: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * If `true`, the slider will be disabled. + */ + disabled: PropTypes.bool, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider. + * + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaLabel: PropTypes.func, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider. + * + * @param {number} value The thumb label's value to format. + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaValueText: PropTypes.func, + /** + * Indicates whether the theme context has rtl direction. It is set automatically. + */ + isRtl: PropTypes.boolean, + /** + * Marks indicate predetermined values to which the user can move the slider. + * If `true` the marks will be spaced according the value of the `step` prop. + * If an array, it should contain objects with `value` and an optional `label` keys. + */ + marks: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.node, + value: PropTypes.number.isRequired, + }), + ), + PropTypes.bool, + ]), + /** + * The maximum allowed value of the slider. + * Should not be equal to min. + */ + max: PropTypes.number, + /** + * The minimum allowed value of the slider. + * Should not be equal to max. + */ + min: PropTypes.number, + /** + * Name attribute of the hidden `input` element. + */ + name: PropTypes.string, + /** + * Callback function that is fired when the slider's value changed. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChange: PropTypes.func, + /** + * Callback function that is fired when the `mouseup` is triggered. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChangeCommitted: PropTypes.func, + /** + * @ignore + */ + onMouseDown: PropTypes.func, + /** + * The slider orientation. + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A transformation function, to change the scale of the slider. + */ + scale: PropTypes.func, + /** + * The granularity with which the slider can step through values. (A "discrete" slider.) + * The `min` prop serves as the origin for the valid values. + * We recommend (max - min) to be evenly divisible by the step. + * + * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. + */ + step: PropTypes.number, + /** + * The component used to display the value label. + */ + ThumbComponent: PropTypes.elementType, + /** + * The track presentation: + * + * - `normal` the track will render a bar representing the slider value. + * - `inverted` the track will render a bar representing the remaining slider value. + * - `false` the track will render without a bar. + */ + track: PropTypes.oneOf(['inverted', 'normal', false]), + /** + * The value of the slider. + * For ranged sliders, provide an array with two values. + */ + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * The value label component. + */ + ValueLabelComponent: PropTypes.elementType, + /** + * Controls when the value label is displayed: + * + * - `auto` the value label will display when the thumb is hovered or focused. + * - `on` will display persistently. + * - `off` will never display. + */ + valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), + /** + * The format function the value label's value. + * + * When a function is provided, it should have the following signature: + * + * - {number} value The value label's value to format + * - {number} index The value label's index to format + */ + valueLabelFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), +}; + +export default Slider; diff --git a/packages/material-ui/src/Slider/SliderEmotionClassName.js b/packages/material-ui/src/Slider/SliderEmotionClassName.js new file mode 100644 index 00000000000000..5b107ebfb920e1 --- /dev/null +++ b/packages/material-ui/src/Slider/SliderEmotionClassName.js @@ -0,0 +1,306 @@ +import * as React from 'react'; +import { ClassNames } from '@emotion/core'; +import { ThemeProvider } from 'emotion-theming'; +import useTheme from '../styles/useTheme'; +import { fade, lighten, darken } from '../styles/colorManipulator'; +import capitalize from '../utils/capitalize'; +import SliderBase from './Slider.base'; + +const callable = (input) => (...arg) => { + if (typeof input === 'function') return input(...arg); + return input; +}; + +export const classes = { + /* Styles applied to the root element. */ + root: (theme, props) => ({ + height: 2, + width: '100%', + boxSizing: 'content-box', + padding: '13px 0', + display: 'inline-block', + position: 'relative', + cursor: 'pointer', + touchAction: 'none', + color: theme.palette.primary.main, + WebkitTapHighlightColor: 'transparent', + ...(props.disabled && { + pointerEvents: 'none', + cursor: 'default', + color: theme.palette.grey[400], + }), + ...(props.orientation === 'vertical' && { + width: 2, + height: '100%', + padding: '0 13px', + }), + // The primary input mechanism of the device includes a pointing device of limited accuracy. + '@media (pointer: coarse)': { + // Reach 42px touch target, about ~8mm on screen. + padding: '20px 0', + ...(props.orientation === 'vertical' && { + padding: '0 20px', + }), + }, + '@media print': { + colorAdjust: 'exact', + }, + }), + /* Styles applied to the root element if `color="primary"`. */ + colorPrimary: { + // TODO v5: move the style here + }, + /* Styles applied to the root element if `color="secondary"`. */ + colorSecondary: (theme) => ({ + color: theme.palette.secondary.main, + }), + /* Styles applied to the root element if `marks` is provided with at least one label. */ + marked: (theme, props) => ({ + marginBottom: 20, + ...(props.orientation === 'vertical' && { + marginBottom: 'auto', + marginRight: 20, + }), + }), + /* Pseudo-class applied to the root element if `orientation="vertical"`. */ + vertical: {}, + /* Pseudo-class applied to the root and thumb element if `disabled={true}`. */ + disabled: {}, + /* Styles applied to the rail element. */ + rail: (theme, props) => ({ + display: 'block', + position: 'absolute', + width: '100%', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + opacity: 0.38, + ...(props.orientation === 'vertical' && { + height: '100%', + width: 2, + }), + }), + /* Styles applied to the track element. */ + track: (theme, props) => ({ + display: 'block', + position: 'absolute', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + ...(props.orientation === 'vertical' && { + width: 2, + }), + }), + /* Styles applied to the track element if `track={false}`. */ + trackFalse: { + ' .MuiSlider--track': { + display: 'none', + }, + }, + /* Styles applied to the track element if `track="inverted"`. */ + trackInverted: (theme) => ({ + ' .MuiSlider--track': { + backgroundColor: + // Same logic as the LinearProgress track color + theme.palette.type === 'light' + ? lighten(theme.palette.primary.main, 0.62) + : darken(theme.palette.primary.main, 0.5), + }, + ' .MuiSlider--rail': { + opacity: 1, + }, + }), + /* Styles applied to the thumb element. */ + thumb: (theme, props) => ({ + position: 'absolute', + width: 12, + height: 12, + marginLeft: -6, + marginTop: -5, + boxSizing: 'border-box', + borderRadius: '50%', + outline: 0, + backgroundColor: 'currentColor', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + transition: theme.transitions.create(['box-shadow'], { + duration: theme.transitions.duration.shortest, + }), + '::after': { + position: 'absolute', + content: '""', + borderRadius: '50%', + // reach 42px hit target (2 * 15 + thumb diameter) + left: -15, + top: -15, + right: -15, + bottom: -15, + }, + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(theme.palette.primary.main, 0.16)}`, + }, + ...(props.disabled && { + width: 8, + height: 8, + marginLeft: -4, + marginTop: -3, + ':hover': { + boxShadow: 'none', + }, + }), + ...(props.orientation === 'vertical' && { + marginLeft: -5, + marginBottom: -6, + }), + ...((props.orientation === 'vertical' || props.disabled) && { + marginLeft: -3, + marginBottom: -4, + }), + }), + /* Styles applied to the thumb element if `color="primary"`. */ + thumbColorPrimary: { + // TODO v5: move the style here + }, + /* Styles applied to the thumb element if `color="secondary"`. */ + thumbColorSecondary: (theme, props) => ({ + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(theme.palette.secondary.main, 0.16)}`, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(theme.palette.secondary.main, 0.16)}`, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(theme.palette.secondary.main, 0.16)}`, + }, + }), + /* Pseudo-class applied to the thumb element if it's active. */ + active: {}, + /* Pseudo-class applied to the thumb element if keyboard focused. */ + focusVisible: {}, + /* Styles applied to the thumb label element. */ + valueLabel: { + // IE 11 centering bug, to remove from the customization demos once no longer supported + left: 'calc(-50% - 4px)', + }, + /* Styles applied to the mark element. */ + mark: { + position: 'absolute', + width: 2, + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + }, + /* Styles applied to the mark element if active (depending on the value). */ + markActive: (theme) => ({ + backgroundColor: theme.palette.background.paper, + opacity: 0.8, + }), + /* Styles applied to the mark label element. */ + markLabel: (theme, props = {}) => ({ + ...theme.typography.body2, + color: theme.palette.text.secondary, + position: 'absolute', + top: 26, + transform: 'translateX(-50%)', + whiteSpace: 'nowrap', + ...(props.orientation === 'vertical' && { + top: 'auto', + left: 26, + transform: 'translateY(50%)', + }), + '@media (pointer: coarse)': { + top: 40, + ...(props.orientation === 'vertical' && { + left: 31, + }), + }, + }), + /* Styles applied to the mark label element if active (depending on the value). */ + markLabelActive: (theme) => ({ + color: theme.palette.text.primary, + }), +}; + +// This implementatino uses the ClassNames component https://emotion.sh/docs/class-names +const Slider = React.forwardRef(function Slider(props, ref) { + const { + className, + color = 'primary', + disabled = false, + marks: marksProp = false, + orientation = 'horizontal', + step = 1, + track = 'normal', + max = 100, + min = 0, + } = props; + const theme = useTheme(); + + const marks = + marksProp === true && step !== null + ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({ + value: min + step * index, + })) + : marksProp || []; + const isRtl = theme.direction === 'rtl'; + + return ( + + + {({ css, cx }) => { + const cs = { + root: cx( + css(callable(classes.root)(theme, props)), + css(callable(classes[`color${capitalize(color)}`])(theme, props)), + { + [css(callable(classes.disabled)(theme, props))]: disabled, + [css(callable(classes.marked)(theme, props))]: + marks.length > 0 && marks.some((mark) => mark.label), + [css(callable(classes.vertical)(theme, props))]: orientation === 'vertical', + [css(callable(classes.trackInverted)(theme, props))]: track === 'inverted', + [css(callable(classes.trackFalse)(theme, props))]: track === false, + }, + className, + ), + rail: cx(css(callable(classes.rail)(theme, props)), 'MuiSlider--rail'), + track: cx(css(callable(classes.track)(theme, props)), 'MuiSlider--rail'), + mark: css(callable(classes.mark)(theme, props)), + markActive: css(callable(classes.markActive)(theme, props)), + markLabel: css(callable(classes.markLabel)(theme, props)), + markLabelActive: css(callable(classes.markLabelActive)(theme, props)), + valueLabel: css(callable(classes.valueLabel)(theme, props)), + thumb: cx( + css(callable(classes.thumb)(theme, props)), + css(callable(classes[`thumbColor${capitalize(color)}`])(theme, props)), + { + [css(callable(classes.disabled)(theme, props))]: disabled, + }, + ), + thumbActive: 'MuiSlider--active', + thumbFocusVisible: cx( + css(callable(classes.focusVisible)(theme, props)), + 'MuiSlider--focusVisible', + ), + }; + + return ; + }} + + + ); +}); + +export default Slider; diff --git a/packages/material-ui/src/Slider/SliderEmotionStyled.js b/packages/material-ui/src/Slider/SliderEmotionStyled.js new file mode 100644 index 00000000000000..18f140f116be09 --- /dev/null +++ b/packages/material-ui/src/Slider/SliderEmotionStyled.js @@ -0,0 +1,233 @@ +import * as React from 'react'; +import styled from '@emotion/styled'; +import isPropValid from '@emotion/is-prop-valid'; +import { ThemeProvider } from 'emotion-theming'; +import useTheme from '../styles/useTheme'; +import { fade, lighten, darken } from '../styles/colorManipulator'; +import SliderBase from './SliderComponents.base'; +import ValueLabel from './ValueLabel'; + +const shouldForwardProp = (prop) => + isPropValid(prop) && prop !== 'color' && prop !== 'orientation' && prop !== 'disabled'; + +const StyledComponent = styled('span', { shouldForwardProp })((props) => ({ + height: 2, + width: '100%', + boxSizing: 'content-box', + padding: '13px 0', + display: 'inline-block', + position: 'relative', + cursor: 'pointer', + touchAction: 'none', + color: props.theme.palette.primary.main, + WebkitTapHighlightColor: 'transparent', + ...(props.color === 'secondary' && { + color: props.theme.palette.secondary.main, + }), + ...(props.disabled && { + pointerEvents: 'none', + cursor: 'default', + color: props.theme.palette.grey[400], + }), + ...(props.orientation === 'vertical' && { + width: 2, + height: '100%', + padding: '0 13px', + }), + // The primary input mechanism of the device includes a pointing device of limited accuracy. + '@media (pointer: coarse)': { + // Reach 42px touch target, about ~8mm on screen. + padding: '20px 0', + ...(props.orientation === 'vertical' && { + padding: '0 20px', + }), + }, + '@media print': { + colorAdjust: 'exact', + }, + ...(props.marked && { + marginBottom: 20, + ...(props.orientation === 'vertical' && { + marginBottom: 'auto', + marginRight: 20, + }), + }), +})); + +const StyledRail = styled('span', { shouldForwardProp })((props) => ({ + display: 'block', + position: 'absolute', + width: '100%', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + opacity: 0.38, + ...(props.orientation === 'vertical' && { + height: '100%', + width: 2, + }), + ...(props.track === 'inverted' && { + opacity: 1, + }), +})); + +const StyledTrack = styled('span', { shouldForwardProp })((props) => ({ + display: 'block', + position: 'absolute', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + ...(props.orientation === 'vertical' && { + width: 2, + }), + ...(props.track === false && { + display: 'none', + }), + ...(props.track === 'inverted' && { + backgroundColor: + // Same logic as the LinearProgress track color + props.theme.palette.type === 'light' + ? lighten(props.theme.palette.primary.main, 0.62) + : darken(props.theme.palette.primary.main, 0.5), + }), +})); + +const StyledThumb = styled('span', { shouldForwardProp })((props) => ({ + position: 'absolute', + width: 12, + height: 12, + marginLeft: -6, + marginTop: -5, + boxSizing: 'border-box', + borderRadius: '50%', + outline: 0, + backgroundColor: 'currentColor', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + transition: props.theme.transitions.create(['box-shadow'], { + duration: props.theme.transitions.duration.shortest, + }), + '::after': { + position: 'absolute', + content: '""', + borderRadius: '50%', + // reach 42px hit target (2 * 15 + thumb diameter) + left: -15, + top: -15, + right: -15, + bottom: -15, + }, + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(props.theme.palette.primary.main, 0.16)}`, + }, + ...(props.disabled && { + width: 8, + height: 8, + marginLeft: -4, + marginTop: -3, + ':hover': { + boxShadow: 'none', + }, + }), + ...(props.orientation === 'vertical' && { + marginLeft: -5, + marginBottom: -6, + }), + ...((props.orientation === 'vertical' || props.disabled) && { + marginLeft: -3, + marginBottom: -4, + }), + ...(props.color === 'secondary' && { + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }, + }), +})); + +const StyledValueLabel = styled(ValueLabel)({ + // IE 11 centering bug, to remove from the customization demos once no longer supported + left: 'calc(-50% - 4px)', +}); + +const StyledMark = styled('span', { shouldForwardProp })((props) => ({ + position: 'absolute', + width: 2, + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + ...(props.markActive && { + backgroundColor: props.theme.palette.background.paper, + opacity: 0.8, + }), +})); + +const StyledMarkLabel = styled('span', { shouldForwardProp })((props) => ({ + ...props.theme.typography.body2, + color: props.theme.palette.text.secondary, + position: 'absolute', + top: 26, + transform: 'translateX(-50%)', + whiteSpace: 'nowrap', + ...(props.orientation === 'vertical' && { + top: 'auto', + left: 26, + transform: 'translateY(50%)', + }), + '@media (pointer: coarse)': { + top: 40, + ...(props.orientation === 'vertical' && { + left: 31, + }), + }, + ...(props.markLabelActive && { + color: props.theme.palette.text.primary, + }), +})); + +// This implementatino uses the ClassNames component https://emotion.sh/docs/class-names +const Slider = React.forwardRef(function Slider(props, ref) { + const theme = useTheme(); + const isRtl = theme.direction === 'rtl'; + + return ( + + + + ); +}); + +export default Slider; diff --git a/packages/material-ui/src/Slider/SliderEmotionStyledDefaultProps.js b/packages/material-ui/src/Slider/SliderEmotionStyledDefaultProps.js new file mode 100644 index 00000000000000..24513cc6bd296b --- /dev/null +++ b/packages/material-ui/src/Slider/SliderEmotionStyledDefaultProps.js @@ -0,0 +1,1033 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { chainPropTypes } from '@material-ui/utils'; +import styled from '@emotion/styled'; +import isPropValid from '@emotion/is-prop-valid'; +import useIsFocusVisible from '../utils/useIsFocusVisible'; +import ownerDocument from '../utils/ownerDocument'; +import useEventCallback from '../utils/useEventCallback'; +import useForkRef from '../utils/useForkRef'; +import useControlled from '../utils/useControlled'; +import ValueLabel from './ValueLabel'; +import { getClassWithValueAndKey, getClassWithKeyOnly } from '../styles/classNameBuilders'; +import { ThemeProvider } from 'emotion-theming'; +import useTheme from '../styles/useTheme'; +import { fade, lighten, darken } from '../styles/colorManipulator'; + +function asc(a, b) { + return a - b; +} + +function clamp(value, min, max) { + return Math.min(Math.max(min, value), max); +} + +function findClosest(values, currentValue) { + const { index: closestIndex } = values.reduce((acc, value, index) => { + const distance = Math.abs(currentValue - value); + + if (acc === null || distance < acc.distance || distance === acc.distance) { + return { + distance, + index, + }; + } + + return acc; + }, null); + return closestIndex; +} + +function trackFinger(event, touchId) { + if (touchId.current !== undefined && event.changedTouches) { + for (let i = 0; i < event.changedTouches.length; i += 1) { + const touch = event.changedTouches[i]; + if (touch.identifier === touchId.current) { + return { + x: touch.clientX, + y: touch.clientY, + }; + } + } + + return false; + } + + return { + x: event.clientX, + y: event.clientY, + }; +} + +function valueToPercent(value, min, max) { + return ((value - min) * 100) / (max - min); +} + +function percentToValue(percent, min, max) { + return (max - min) * percent + min; +} + +function getDecimalPrecision(num) { + // This handles the case when num is very small (0.00000001), js will turn this into 1e-8. + // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine. + if (Math.abs(num) < 1) { + const parts = num.toExponential().split('e-'); + const matissaDecimalPart = parts[0].split('.')[1]; + return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10); + } + + const decimalPart = num.toString().split('.')[1]; + return decimalPart ? decimalPart.length : 0; +} + +function roundValueToStep(value, step, min) { + const nearest = Math.round((value - min) / step) * step + min; + return Number(nearest.toFixed(getDecimalPrecision(step))); +} + +function setValueIndex({ values, source, newValue, index }) { + // Performance shortcut + if (source[index] === newValue) { + return source; + } + + const output = values.slice(); + output[index] = newValue; + return output; +} + +function focusThumb({ sliderRef, activeIndex, setActive }) { + if ( + !sliderRef.current.contains(document.activeElement) || + Number(document.activeElement.getAttribute('data-index')) !== activeIndex + ) { + sliderRef.current.querySelector(`[role="slider"][data-index="${activeIndex}"]`).focus(); + } + + if (setActive) { + setActive(activeIndex); + } +} + +const axisProps = { + horizontal: { + offset: (percent) => ({ left: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + 'horizontal-reverse': { + offset: (percent) => ({ right: `${percent}%` }), + leap: (percent) => ({ width: `${percent}%` }), + }, + vertical: { + offset: (percent) => ({ bottom: `${percent}%` }), + leap: (percent) => ({ height: `${percent}%` }), + }, +}; + +const Identity = (x) => x; + +const useSliderClasses = (props) => { + const slots = ['root', 'rail', 'thumb', 'track', 'valueLabel', 'mark', 'markLabel']; + const classes = {}; + + slots.forEach((slot) => { + const slotClassName = `MuiSlider__${slot}`; + classes[slot] = clsx( + slotClassName, + getClassWithValueAndKey(props.color, 'color', slotClassName), + getClassWithValueAndKey(props.orientation, 'orientation', slotClassName), + getClassWithKeyOnly(props.disabled, 'disabled', slotClassName), + getClassWithKeyOnly(props.marked, 'marked', slotClassName), + getClassWithValueAndKey(props.track, 'track', slotClassName), + getClassWithKeyOnly(props.focusVisible, 'focusVisible', slotClassName), + ); + }); + + return classes; +}; + +const shouldForwardProp = (prop) => + isPropValid(prop) && prop !== 'color' && prop !== 'orientation' && prop !== 'disabled'; + +const StyledComponent = styled('span', { shouldForwardProp })((props) => ({ + height: 2, + width: '100%', + boxSizing: 'content-box', + padding: '13px 0', + display: 'inline-block', + position: 'relative', + cursor: 'pointer', + touchAction: 'none', + color: props.theme.palette.primary.main, + WebkitTapHighlightColor: 'transparent', + ...(props.color === 'secondary' && { + color: props.theme.palette.secondary.main, + }), + ...(props.disabled && { + pointerEvents: 'none', + cursor: 'default', + color: props.theme.palette.grey[400], + }), + ...(props.orientation === 'vertical' && { + width: 2, + height: '100%', + padding: '0 13px', + }), + // The primary input mechanism of the device includes a pointing device of limited accuracy. + '@media (pointer: coarse)': { + // Reach 42px touch target, about ~8mm on screen. + padding: '20px 0', + ...(props.orientation === 'vertical' && { + padding: '0 20px', + }), + }, + '@media print': { + colorAdjust: 'exact', + }, + ...(props.marked && { + marginBottom: 20, + ...(props.orientation === 'vertical' && { + marginBottom: 'auto', + marginRight: 20, + }), + }), +})); + +const StyledRail = styled('span', { shouldForwardProp })((props) => ({ + display: 'block', + position: 'absolute', + width: '100%', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + opacity: 0.38, + ...(props.orientation === 'vertical' && { + height: '100%', + width: 2, + }), + ...(props.track === 'inverted' && { + opacity: 1, + }), +})); + +const StyledTrack = styled('span', { shouldForwardProp })((props) => ({ + display: 'block', + position: 'absolute', + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + ...(props.orientation === 'vertical' && { + width: 2, + }), + ...(props.track === false && { + display: 'none', + }), + ...(props.track === 'inverted' && { + backgroundColor: + // Same logic as the LinearProgress track color + props.theme.palette.type === 'light' + ? lighten(props.theme.palette.primary.main, 0.62) + : darken(props.theme.palette.primary.main, 0.5), + }), +})); + +const StyledThumb = styled('span', { shouldForwardProp })((props) => ({ + position: 'absolute', + width: 12, + height: 12, + marginLeft: -6, + marginTop: -5, + boxSizing: 'border-box', + borderRadius: '50%', + outline: 0, + backgroundColor: 'currentColor', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + transition: props.theme.transitions.create(['box-shadow'], { + duration: props.theme.transitions.duration.shortest, + }), + '::after': { + position: 'absolute', + content: '""', + borderRadius: '50%', + // reach 42px hit target (2 * 15 + thumb diameter) + left: -15, + top: -15, + right: -15, + bottom: -15, + }, + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.primary.main, 0.16)}`, + '@media (hover: none)': { + boxShadow: 'none', + }, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(props.theme.palette.primary.main, 0.16)}`, + }, + ...(props.disabled && { + width: 8, + height: 8, + marginLeft: -4, + marginTop: -3, + ':hover': { + boxShadow: 'none', + }, + }), + ...(props.orientation === 'vertical' && { + marginLeft: -5, + marginBottom: -6, + }), + ...((props.orientation === 'vertical' || props.disabled) && { + marginLeft: -3, + marginBottom: -4, + }), + ...(props.color === 'secondary' && { + ':hover': { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }, + ...(props.focusVisible && { + boxShadow: `0px 0px 0px 8px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }), + '&.MuiSlider--active': { + boxShadow: `0px 0px 0px 14px ${fade(props.theme.palette.secondary.main, 0.16)}`, + }, + }), +})); + +const StyledValueLabel = styled(ValueLabel)({ + // IE 11 centering bug, to remove from the customization demos once no longer supported + left: 'calc(-50% - 4px)', +}); + +const StyledMark = styled('span', { shouldForwardProp })((props) => ({ + position: 'absolute', + width: 2, + height: 2, + borderRadius: 1, + backgroundColor: 'currentColor', + ...(props.markActive && { + backgroundColor: props.theme.palette.background.paper, + opacity: 0.8, + }), +})); + +const StyledMarkLabel = styled('span', { shouldForwardProp })((props) => ({ + ...props.theme.typography.body2, + color: props.theme.palette.text.secondary, + position: 'absolute', + top: 26, + transform: 'translateX(-50%)', + whiteSpace: 'nowrap', + ...(props.orientation === 'vertical' && { + top: 'auto', + left: 26, + transform: 'translateY(50%)', + }), + '@media (pointer: coarse)': { + top: 40, + ...(props.orientation === 'vertical' && { + left: 31, + }), + }, + ...(props.markLabelActive && { + color: props.theme.palette.text.primary, + }), +})); + +const Slider = React.forwardRef(function Slider(props, ref) { + const { + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledby, + 'aria-valuetext': ariaValuetext, + className, + color = 'primary', + component: Component = 'span', + defaultValue, + disabled = false, + getAriaLabel, + getAriaValueText, + marks: marksProp = false, + max = 100, + min = 0, + name, + onChange, + onChangeCommitted, + onMouseDown, + orientation = 'horizontal', + scale = Identity, + step = 1, + track = 'normal', + value: valueProp, + valueLabelDisplay = 'off', + valueLabelFormat = Identity, + isRtl = false, + components = {}, + componentsProps = {}, + ...other + } = props; + + const theme = useTheme(); + + const touchId = React.useRef(); + // We can't use the :active browser pseudo-classes. + // - The active state isn't triggered when clicking on the rail. + // - The active state isn't transfered when inversing a range slider. + const [active, setActive] = React.useState(-1); + const [open, setOpen] = React.useState(-1); + + const [valueDerived, setValueState] = useControlled({ + controlled: valueProp, + default: defaultValue, + name: 'Slider', + }); + + const range = Array.isArray(valueDerived); + let values = range ? valueDerived.slice().sort(asc) : [valueDerived]; + values = values.map((value) => clamp(value, min, max)); + const marks = + marksProp === true && step !== null + ? [...Array(Math.floor((max - min) / step) + 1)].map((_, index) => ({ + value: min + step * index, + })) + : marksProp || []; + + const { isFocusVisible, onBlurVisible, ref: focusVisibleRef } = useIsFocusVisible(); + const [focusVisible, setFocusVisible] = React.useState(-1); + + const sliderRef = React.useRef(); + const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); + const handleRef = useForkRef(ref, handleFocusRef); + + const handleFocus = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + if (isFocusVisible(event)) { + setFocusVisible(index); + } + setOpen(index); + }); + const handleBlur = useEventCallback(() => { + if (focusVisible !== -1) { + setFocusVisible(-1); + onBlurVisible(); + } + setOpen(-1); + }); + const handleMouseOver = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + setOpen(index); + }); + const handleMouseLeave = useEventCallback(() => { + setOpen(-1); + }); + + const handleKeyDown = useEventCallback((event) => { + const index = Number(event.currentTarget.getAttribute('data-index')); + const value = values[index]; + const tenPercents = (max - min) / 10; + const marksValues = marks.map((mark) => mark.value); + const marksIndex = marksValues.indexOf(value); + let newValue; + const increaseKey = isRtl ? 'ArrowLeft' : 'ArrowRight'; + const decreaseKey = isRtl ? 'ArrowRight' : 'ArrowLeft'; + + switch (event.key) { + case 'Home': + newValue = min; + break; + case 'End': + newValue = max; + break; + case 'PageUp': + if (step) { + newValue = value + tenPercents; + } + break; + case 'PageDown': + if (step) { + newValue = value - tenPercents; + } + break; + case increaseKey: + case 'ArrowUp': + if (step) { + newValue = value + step; + } else { + newValue = marksValues[marksIndex + 1] || marksValues[marksValues.length - 1]; + } + break; + case decreaseKey: + case 'ArrowDown': + if (step) { + newValue = value - step; + } else { + newValue = marksValues[marksIndex - 1] || marksValues[0]; + } + break; + default: + return; + } + + // Prevent scroll of the page + event.preventDefault(); + + if (step) { + newValue = roundValueToStep(newValue, step, min); + } + + newValue = clamp(newValue, min, max); + + if (range) { + const previousValue = newValue; + newValue = setValueIndex({ + values, + source: valueDerived, + newValue, + index, + }).sort(asc); + focusThumb({ sliderRef, activeIndex: newValue.indexOf(previousValue) }); + } + + setValueState(newValue); + setFocusVisible(index); + + if (onChange) { + onChange(event, newValue); + } + if (onChangeCommitted) { + onChangeCommitted(event, newValue); + } + }); + + const previousIndex = React.useRef(); + let axis = orientation; + if (isRtl && orientation === 'horizontal') { + axis += '-reverse'; + } + + const getFingerNewValue = ({ finger, move = false, values: values2, source }) => { + const { current: slider } = sliderRef; + const { width, height, bottom, left } = slider.getBoundingClientRect(); + let percent; + + if (axis.indexOf('vertical') === 0) { + percent = (bottom - finger.y) / height; + } else { + percent = (finger.x - left) / width; + } + + if (axis.indexOf('-reverse') !== -1) { + percent = 1 - percent; + } + + let newValue; + newValue = percentToValue(percent, min, max); + if (step) { + newValue = roundValueToStep(newValue, step, min); + } else { + const marksValues = marks.map((mark) => mark.value); + const closestIndex = findClosest(marksValues, newValue); + newValue = marksValues[closestIndex]; + } + + newValue = clamp(newValue, min, max); + let activeIndex = 0; + + if (range) { + if (!move) { + activeIndex = findClosest(values2, newValue); + } else { + activeIndex = previousIndex.current; + } + + const previousValue = newValue; + newValue = setValueIndex({ + values: values2, + source, + newValue, + index: activeIndex, + }).sort(asc); + activeIndex = newValue.indexOf(previousValue); + previousIndex.current = activeIndex; + } + + return { newValue, activeIndex }; + }; + + const handleTouchMove = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue, activeIndex } = getFingerNewValue({ + finger, + move: true, + values, + source: valueDerived, + }); + + focusThumb({ sliderRef, activeIndex, setActive }); + setValueState(newValue); + + if (onChange) { + onChange(nativeEvent, newValue); + } + }); + + const handleTouchEnd = useEventCallback((nativeEvent) => { + const finger = trackFinger(nativeEvent, touchId); + + if (!finger) { + return; + } + + const { newValue } = getFingerNewValue({ finger, values, source: valueDerived }); + + setActive(-1); + if (nativeEvent.type === 'touchend') { + setOpen(-1); + } + + if (onChangeCommitted) { + onChangeCommitted(nativeEvent, newValue); + } + + touchId.current = undefined; + + const doc = ownerDocument(sliderRef.current); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }); + + const handleTouchStart = useEventCallback((event) => { + // Workaround as Safari has partial support for touchAction: 'none'. + event.preventDefault(); + const touch = event.changedTouches[0]; + if (touch != null) { + // A number that uniquely identifies the current finger in the touch session. + touchId.current = touch.identifier; + } + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('touchmove', handleTouchMove); + doc.addEventListener('touchend', handleTouchEnd); + }); + + React.useEffect(() => { + const { current: slider } = sliderRef; + slider.addEventListener('touchstart', handleTouchStart); + const doc = ownerDocument(slider); + + return () => { + slider.removeEventListener('touchstart', handleTouchStart); + doc.removeEventListener('mousemove', handleTouchMove); + doc.removeEventListener('mouseup', handleTouchEnd); + doc.removeEventListener('touchmove', handleTouchMove); + doc.removeEventListener('touchend', handleTouchEnd); + }; + }, [handleTouchEnd, handleTouchMove, handleTouchStart]); + + const handleMouseDown = useEventCallback((event) => { + if (onMouseDown) { + onMouseDown(event); + } + + event.preventDefault(); + const finger = trackFinger(event, touchId); + const { newValue, activeIndex } = getFingerNewValue({ finger, values, source: valueDerived }); + focusThumb({ sliderRef, activeIndex, setActive }); + + setValueState(newValue); + + if (onChange) { + onChange(event, newValue); + } + + const doc = ownerDocument(sliderRef.current); + doc.addEventListener('mousemove', handleTouchMove); + doc.addEventListener('mouseup', handleTouchEnd); + }); + + const trackOffset = valueToPercent(range ? values[0] : min, min, max); + const trackLeap = valueToPercent(values[values.length - 1], min, max) - trackOffset; + const trackStyle = { + ...axisProps[axis].offset(trackOffset), + ...axisProps[axis].leap(trackLeap), + }; + + const Root = components.root || StyledComponent; + const rootProps = componentsProps.root || {}; + + const Rail = components.rail || StyledRail; + const railProps = componentsProps.rail || {}; + + const Track = components.track || StyledTrack; + const trackProps = componentsProps.track || {}; + + const Thumb = components.thumb || StyledThumb; + const thumbProps = componentsProps.thumb || {}; + + const ValueLabel = components.valueLabel || StyledValueLabel; + const valueLabelProps = componentsProps.valueLabel || {}; + + const Mark = components.mark || StyledMark; + const markProps = componentsProps.mark || {}; + + const MarkLabel = components.markLabel || StyledMarkLabel; + const markLabelProps = componentsProps.markLabel || {}; + + // all props with defaults + // consider extracting to hook an reusing the lint rule for the varints + const stateAndProps = { + ...props, + color, + disabled, + max, + min, + orientation, + scale, + step, + track, + valueLabelDisplay, + valueLabelFormat, + isRtl, + }; + + const classes = useSliderClasses({ + ...stateAndProps, + marked: marks.length > 0 && marks.some((mark) => mark.label), + }); + + return ( + + 0 && marks.some((mark) => mark.label)} + {...stateAndProps} + {...rootProps} + > + + + + {marks.map((mark, index) => { + const percent = valueToPercent(mark.value, min, max); + const style = axisProps[axis].offset(percent); + + let markActive; + if (track === false) { + markActive = values.indexOf(mark.value) !== -1; + } else { + 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])); + } + + return ( + + + {mark.label != null ? ( + + {mark.label} + + ) : null} + + ); + })} + {values.map((value, index) => { + const percent = valueToPercent(value, min, max); + const style = axisProps[axis].offset(percent); + + return ( + + + + ); + })} + + + ); +}); + +Slider.propTypes = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit the d.ts file and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The label of the slider. + */ + 'aria-label': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-label'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaLabel` prop instead of `aria-label` when using a range slider.', + ); + } + + return null; + }), + /** + * The id of the element containing a label for the slider. + */ + 'aria-labelledby': PropTypes.string, + /** + * A string value that provides a user-friendly name for the current value of the slider. + */ + 'aria-valuetext': chainPropTypes(PropTypes.string, (props) => { + const range = Array.isArray(props.value || props.defaultValue); + + if (range && props['aria-valuetext'] != null) { + return new Error( + 'Material-UI: You need to use the `getAriaValueText` prop instead of `aria-valuetext` when using a range slider.', + ); + } + + return null; + }), + /** + * @ignore + */ + children: PropTypes.node, + /** + * Override or extend the styles applied to the component. + * See [CSS API](#css) below for more details. + */ + classes: PropTypes.object, + /** + * @ignore + */ + className: PropTypes.string, + /** + * The color of the component. It supports those theme colors that make sense for this component. + */ + color: PropTypes.oneOf(['primary', 'secondary']), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The default element value. Use when the component is not controlled. + */ + defaultValue: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * If `true`, the slider will be disabled. + */ + disabled: PropTypes.bool, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider. + * + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaLabel: PropTypes.func, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider. + * + * @param {number} value The thumb label's value to format. + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaValueText: PropTypes.func, + /** + * Indicates whether the theme context has rtl direction. It is set automatically. + */ + isRtl: PropTypes.boolean, + /** + * Marks indicate predetermined values to which the user can move the slider. + * If `true` the marks will be spaced according the value of the `step` prop. + * If an array, it should contain objects with `value` and an optional `label` keys. + */ + marks: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.node, + value: PropTypes.number.isRequired, + }), + ), + PropTypes.bool, + ]), + /** + * The maximum allowed value of the slider. + * Should not be equal to min. + */ + max: PropTypes.number, + /** + * The minimum allowed value of the slider. + * Should not be equal to max. + */ + min: PropTypes.number, + /** + * Name attribute of the hidden `input` element. + */ + name: PropTypes.string, + /** + * Callback function that is fired when the slider's value changed. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChange: PropTypes.func, + /** + * Callback function that is fired when the `mouseup` is triggered. + * + * @param {object} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChangeCommitted: PropTypes.func, + /** + * @ignore + */ + onMouseDown: PropTypes.func, + /** + * The slider orientation. + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A transformation function, to change the scale of the slider. + */ + scale: PropTypes.func, + /** + * The granularity with which the slider can step through values. (A "discrete" slider.) + * The `min` prop serves as the origin for the valid values. + * We recommend (max - min) to be evenly divisible by the step. + * + * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. + */ + step: PropTypes.number, + /** + * The component used to display the value label. + */ + ThumbComponent: PropTypes.elementType, + /** + * The track presentation: + * + * - `normal` the track will render a bar representing the slider value. + * - `inverted` the track will render a bar representing the remaining slider value. + * - `false` the track will render without a bar. + */ + track: PropTypes.oneOf(['inverted', 'normal', false]), + /** + * The value of the slider. + * For ranged sliders, provide an array with two values. + */ + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * The value label component. + */ + ValueLabelComponent: PropTypes.elementType, + /** + * Controls when the value label is displayed: + * + * - `auto` the value label will display when the thumb is hovered or focused. + * - `on` will display persistently. + * - `off` will never display. + */ + valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), + /** + * The format function the value label's value. + * + * When a function is provided, it should have the following signature: + * + * - {number} value The value label's value to format + * - {number} index The value label's index to format + */ + valueLabelFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), +}; + +export default Slider; diff --git a/packages/material-ui/src/Slider/index.d.ts b/packages/material-ui/src/Slider/index.d.ts index 006f966fe2404f..b8cc19dc95c284 100644 --- a/packages/material-ui/src/Slider/index.d.ts +++ b/packages/material-ui/src/Slider/index.d.ts @@ -1,2 +1,3 @@ -export { default } from './Slider'; -export * from './Slider'; +export { default } from './SliderEmotionStyled'; +export * from './SliderEmotionStyled'; +export { default as SliderBase } from './SliderEmotionStyledDefaultProps'; diff --git a/packages/material-ui/src/Slider/index.js b/packages/material-ui/src/Slider/index.js index 9898d6a85d1d01..3e151439b6bfd7 100644 --- a/packages/material-ui/src/Slider/index.js +++ b/packages/material-ui/src/Slider/index.js @@ -1 +1,2 @@ -export { default } from './Slider'; +export { default } from './SliderEmotionStyled'; +export { default as SliderBase } from './SliderEmotionStyledDefaultProps'; diff --git a/packages/material-ui/src/styles/classNameBuilders.d.ts b/packages/material-ui/src/styles/classNameBuilders.d.ts new file mode 100644 index 00000000000000..e3717352a3e00b --- /dev/null +++ b/packages/material-ui/src/styles/classNameBuilders.d.ts @@ -0,0 +1,2 @@ +export function getClassWithValueAndKey(value: any, key: string, prefix: string): string; +export function getClassWithKeyOnly(value: any, key: string, prefix: string): string; diff --git a/packages/material-ui/src/styles/classNameBuilders.js b/packages/material-ui/src/styles/classNameBuilders.js new file mode 100644 index 00000000000000..de8cb39618961c --- /dev/null +++ b/packages/material-ui/src/styles/classNameBuilders.js @@ -0,0 +1,20 @@ +import capitalize from '../utils/capitalize'; +/** + * Converts to class name by using both the key and the value + * + * + * + */ +export function getClassWithValueAndKey(value, key, prefix) { + return value ? `${prefix}${capitalize(key)}${capitalize(value)}` : ''; +} + +/** + * Converts to class name using the key if the value is truthy + * + * + * + */ +export function getClassWithKeyOnly(value, key, prefix) { + return value ? `${prefix}${capitalize(key)}` : ''; +} diff --git a/packages/material-ui/src/styles/classNameBuilders.test.js b/packages/material-ui/src/styles/classNameBuilders.test.js new file mode 100644 index 00000000000000..cea4138d0f7c30 --- /dev/null +++ b/packages/material-ui/src/styles/classNameBuilders.test.js @@ -0,0 +1,36 @@ +import { expect } from 'chai'; +import { getClassWithKeyOnly, getClassWithValueAndKey } from './classNameBuilders'; + +describe('classNameBuilders', () => { + describe('getClassWithKeyOnly', () => { + it('should create classname using the prefix and the key if the value is truthy', () => { + expect(getClassWithKeyOnly(true, 'disabled', 'MuiTest-')).to.equal( + 'MuiTest-disabled', + ); + }); + + it('should return empty string it he value is undefined', () => { + expect(getClassWithKeyOnly(undefined, 'disabled', 'MuiTest-')).to.equal(''); + }); + + it('should return empty string it he value is null', () => { + expect(getClassWithKeyOnly(null, 'disabled', 'MuiTest-')).to.equal(''); + }); + }); + + describe('getClassWithValueAndKey', () => { + it('should create classname using the prefix, the key and the value if the value is truthy', () => { + expect(getClassWithValueAndKey('primary', 'color', 'MuiTest-')).to.equal( + 'MuiTest-colorPrimary', + ); + }); + + it('should return empty string it he value is undefined', () => { + expect(getClassWithValueAndKey(undefined, 'color', 'MuiTest-')).to.equal(''); + }); + + it('should return empty string it he value is null', () => { + expect(getClassWithValueAndKey(null, 'color', 'MuiTest-')).to.equal(''); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index b46c7b9993a185..7fe5ce0d868419 100644 --- a/yarn.lock +++ b/yarn.lock @@ -68,7 +68,14 @@ optionalDependencies: chokidar "^2.1.8" -"@babel/code-frame@7.8.3", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.8.3": +"@babel/code-frame@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== @@ -84,7 +91,36 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.7.7", "@babel/core@^7.1.6", "@babel/core@^7.10.2", "@babel/core@^7.4.5", "@babel/core@^7.5.4", "@babel/core@^7.7.5": +"@babel/compat-data@^7.9.6": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== + dependencies: + browserslist "^4.12.0" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" + integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.7.7" + "@babel/helpers" "^7.7.4" + "@babel/parser" "^7.7.7" + "@babel/template" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@babel/types" "^7.7.4" + convert-source-map "^1.7.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.1.6", "@babel/core@^7.10.2", "@babel/core@^7.4.5", "@babel/core@^7.5.4", "@babel/core@^7.7.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.4.tgz#780e8b83e496152f8dd7df63892b2e052bf1d51d" integrity sha512-3A0tS0HWpy4XujGc7QtOIHTeNwUgWaZc/WuS5YQrfhU67jnVmsD6OGPc1AKHH0LJHQICGncy3+YUjIhVlfDdcA== @@ -116,6 +152,15 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.7.7": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== + dependencies: + "@babel/types" "^7.11.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" @@ -148,7 +193,7 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.10.4": +"@babel/helper-compilation-targets@^7.10.4", "@babel/helper-compilation-targets@^7.9.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== @@ -171,6 +216,18 @@ "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" +"@babel/helper-create-class-features-plugin@^7.10.5", "@babel/helper-create-class-features-plugin@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-create-regexp-features-plugin@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" @@ -227,6 +284,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" @@ -247,6 +311,19 @@ "@babel/types" "^7.10.4" lodash "^4.17.13" +"@babel/helper-module-transforms@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" @@ -309,7 +386,14 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-validator-identifier@^7.10.4": +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.9.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== @@ -324,7 +408,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helpers@^7.10.4": +"@babel/helpers@^7.10.4", "@babel/helpers@^7.7.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== @@ -333,7 +417,7 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/highlight@^7.10.4": +"@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== @@ -361,6 +445,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.4.tgz#9eedf27e1998d87739fb5028a5120557c06a1a64" integrity sha512-8jHII4hf+YVDsskTF6WuMB3X4Eh+PsUkC2ljq22so5rHvH+T8BzyL94VOdyFLNR8tBSVXOTbNHOKpR4TfRxVtA== +"@babel/parser@^7.7.7": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.2.tgz#0882ab8a455df3065ea2dcb4c753b2460a24bead" + integrity sha512-Vuj/+7vLo6l1Vi7uuO+1ngCDNeVmNbTngcJFKCR/oEtz8tKz0CJxZEGmPt9KcIloZhOZ3Zit6xbpXT2MDlS9Vw== + "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.4.tgz#4b65abb3d9bacc6c657aaa413e56696f9f170fc6" @@ -370,7 +459,24 @@ "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@7.8.3", "@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.10.4": +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" + integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== @@ -378,7 +484,7 @@ "@babel/helper-create-class-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-dynamic-import@^7.10.4": +"@babel/plugin-proposal-dynamic-import@^7.10.4", "@babel/plugin-proposal-dynamic-import@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== @@ -386,7 +492,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.10.4": +"@babel/plugin-proposal-json-strings@^7.10.4", "@babel/plugin-proposal-json-strings@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== @@ -394,7 +500,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": +"@babel/plugin-proposal-nullish-coalescing-operator@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4", "@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== @@ -402,7 +516,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@7.8.3", "@babel/plugin-proposal-numeric-separator@^7.10.4": +"@babel/plugin-proposal-numeric-separator@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" + integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.10.4", "@babel/plugin-proposal-numeric-separator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== @@ -410,7 +532,16 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@7.9.6", "@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.10.1", "@babel/plugin-proposal-object-rest-spread@^7.10.4": +"@babel/plugin-proposal-object-rest-spread@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" + integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.9.5" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.10.1", "@babel/plugin-proposal-object-rest-spread@^7.10.4", "@babel/plugin-proposal-object-rest-spread@^7.9.6": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== @@ -419,7 +550,7 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.10.4": +"@babel/plugin-proposal-optional-catch-binding@^7.10.4", "@babel/plugin-proposal-optional-catch-binding@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== @@ -427,7 +558,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@7.9.0", "@babel/plugin-proposal-optional-chaining@^7.1.0", "@babel/plugin-proposal-optional-chaining@^7.10.1", "@babel/plugin-proposal-optional-chaining@^7.10.4": +"@babel/plugin-proposal-optional-chaining@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" + integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.1.0", "@babel/plugin-proposal-optional-chaining@^7.10.4", "@babel/plugin-proposal-optional-chaining@^7.9.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== @@ -444,7 +583,7 @@ "@babel/helper-create-class-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": +"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== @@ -508,7 +647,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4": +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -536,7 +675,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.4": +"@babel/plugin-syntax-top-level-await@^7.10.4", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== @@ -550,14 +689,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.10.4": +"@babel/plugin-transform-arrow-functions@^7.10.4", "@babel/plugin-transform-arrow-functions@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.10.4": +"@babel/plugin-transform-async-to-generator@^7.10.4", "@babel/plugin-transform-async-to-generator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== @@ -566,7 +705,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.10.4": +"@babel/plugin-transform-block-scoped-functions@^7.10.4", "@babel/plugin-transform-block-scoped-functions@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== @@ -581,7 +720,14 @@ "@babel/helper-plugin-utils" "^7.10.4" lodash "^4.17.13" -"@babel/plugin-transform-classes@^7.10.4": +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.10.4", "@babel/plugin-transform-classes@^7.9.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== @@ -595,21 +741,21 @@ "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.10.4": +"@babel/plugin-transform-computed-properties@^7.10.4", "@babel/plugin-transform-computed-properties@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.10.4", "@babel/plugin-transform-destructuring@npm:@minh.nguyen/plugin-transform-destructuring@^7.5.2": - version "7.5.2" - resolved "https://registry.yarnpkg.com/@minh.nguyen/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.2.tgz#49de3e25c373fadd11471a2fc99ec0ce07d92f19" - integrity sha512-DIzWFKl5nzSk9Hj9ZsEXAvvgHiyuAsw52queJMuKqfZOk1BOr9u1i2h0tc6tPF3rQieubP+eX4DPLTKSMpbyMg== +"@babel/plugin-transform-destructuring@^7.10.4", "@babel/plugin-transform-destructuring@^7.9.5": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": +"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== @@ -617,14 +763,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.10.4": +"@babel/plugin-transform-duplicate-keys@^7.10.4", "@babel/plugin-transform-duplicate-keys@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.10.4": +"@babel/plugin-transform-exponentiation-operator@^7.10.4", "@babel/plugin-transform-exponentiation-operator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== @@ -640,14 +786,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-flow" "^7.10.4" -"@babel/plugin-transform-for-of@^7.10.4": +"@babel/plugin-transform-for-of@^7.10.4", "@babel/plugin-transform-for-of@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.10.4": +"@babel/plugin-transform-function-name@^7.10.4", "@babel/plugin-transform-function-name@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== @@ -655,14 +801,14 @@ "@babel/helper-function-name" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.10.4": +"@babel/plugin-transform-literals@^7.10.4", "@babel/plugin-transform-literals@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.10.4": +"@babel/plugin-transform-member-expression-literals@^7.10.4", "@babel/plugin-transform-member-expression-literals@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== @@ -678,6 +824,15 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-amd@^7.9.6": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== + dependencies: + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@7.9.6": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" @@ -688,7 +843,7 @@ "@babel/helper-simple-access" "^7.8.3" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.1.0", "@babel/plugin-transform-modules-commonjs@^7.10.4": +"@babel/plugin-transform-modules-commonjs@^7.1.0", "@babel/plugin-transform-modules-commonjs@^7.10.4", "@babel/plugin-transform-modules-commonjs@^7.9.6": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== @@ -708,7 +863,17 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.10.4": +"@babel/plugin-transform-modules-systemjs@^7.9.6": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.10.4", "@babel/plugin-transform-modules-umd@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== @@ -716,14 +881,14 @@ "@babel/helper-module-transforms" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4", "@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-new-target@^7.10.4": +"@babel/plugin-transform-new-target@^7.10.4", "@babel/plugin-transform-new-target@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== @@ -737,7 +902,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.10.4": +"@babel/plugin-transform-object-super@^7.10.4", "@babel/plugin-transform-object-super@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== @@ -753,7 +918,15 @@ "@babel/helper-get-function-arity" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.10.4": +"@babel/plugin-transform-parameters@^7.9.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-property-literals@^7.10.4", "@babel/plugin-transform-property-literals@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== @@ -767,14 +940,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.10.4": +"@babel/plugin-transform-react-display-name@^7.10.4", "@babel/plugin-transform-react-display-name@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.10.4": +"@babel/plugin-transform-react-jsx-development@^7.10.4", "@babel/plugin-transform-react-jsx-development@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== @@ -783,7 +956,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-self@^7.10.4": +"@babel/plugin-transform-react-jsx-self@^7.10.4", "@babel/plugin-transform-react-jsx-self@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== @@ -799,7 +972,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.10.4": +"@babel/plugin-transform-react-jsx-source@^7.9.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + +"@babel/plugin-transform-react-jsx@^7.10.4", "@babel/plugin-transform-react-jsx@^7.9.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== @@ -817,21 +998,31 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.10.4": +"@babel/plugin-transform-regenerator@^7.10.4", "@babel/plugin-transform-regenerator@^7.8.7": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.10.4": +"@babel/plugin-transform-reserved-words@^7.10.4", "@babel/plugin-transform-reserved-words@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-runtime@7.9.6", "@babel/plugin-transform-runtime@^7.10.1": +"@babel/plugin-transform-runtime@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.6.tgz#3ba804438ad0d880a17bca5eaa0cdf1edeedb2fd" + integrity sha512-qcmiECD0mYOjOIt8YHNsAP1SxPooC/rDmfmiSK9BNY72EitdSc7l44WTEklaWuFtbOEBjNhWWyph/kOImbNJ4w== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + resolve "^1.8.1" + semver "^5.5.1" + +"@babel/plugin-transform-runtime@^7.10.1": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.4.tgz#594fb53453ea1b6f0779cceb48ce0718a447feb7" integrity sha512-8ULlGv8p+Vuxu+kz2Y1dk6MYS2b/Dki+NO6/0ZlfSj5tMalfDL7jI/o/2a+rrWLqSXvnadEqc2WguB4gdQIxZw== @@ -841,7 +1032,7 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.10.4": +"@babel/plugin-transform-shorthand-properties@^7.10.4", "@babel/plugin-transform-shorthand-properties@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== @@ -855,7 +1046,15 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-sticky-regex@^7.10.4": +"@babel/plugin-transform-spread@^7.8.3": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + +"@babel/plugin-transform-sticky-regex@^7.10.4", "@babel/plugin-transform-sticky-regex@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== @@ -871,7 +1070,15 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.10.4": +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.10.4", "@babel/plugin-transform-typeof-symbol@^7.8.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== @@ -887,6 +1094,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-typescript" "^7.10.4" +"@babel/plugin-transform-typescript@^7.9.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" + integrity sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.10.4" + "@babel/plugin-transform-unicode-escapes@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" @@ -894,7 +1110,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.10.4": +"@babel/plugin-transform-unicode-regex@^7.10.4", "@babel/plugin-transform-unicode-regex@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== @@ -910,7 +1126,73 @@ core-js "^2.6.5" regenerator-runtime "^0.13.4" -"@babel/preset-env@7.9.6", "@babel/preset-env@^7.1.6", "@babel/preset-env@^7.10.2": +"@babel/preset-env@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" + integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== + dependencies: + "@babel/compat-data" "^7.9.6" + "@babel/helper-compilation-targets" "^7.9.6" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.9.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.9.5" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.9.5" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.9.0" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.9.6" + "@babel/plugin-transform-modules-commonjs" "^7.9.6" + "@babel/plugin-transform-modules-systemjs" "^7.9.6" + "@babel/plugin-transform-modules-umd" "^7.9.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.9.6" + browserslist "^4.11.1" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-env@^7.1.6", "@babel/preset-env@^7.10.2": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== @@ -999,7 +1281,19 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@7.9.4", "@babel/preset-react@^7.10.1": +"@babel/preset-react@7.9.4": + version "7.9.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d" + integrity sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-react-display-name" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.9.4" + "@babel/plugin-transform-react-jsx-development" "^7.9.0" + "@babel/plugin-transform-react-jsx-self" "^7.9.0" + "@babel/plugin-transform-react-jsx-source" "^7.9.0" + +"@babel/preset-react@^7.10.1": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== @@ -1012,7 +1306,15 @@ "@babel/plugin-transform-react-jsx-source" "^7.10.4" "@babel/plugin-transform-react-pure-annotations" "^7.10.4" -"@babel/preset-typescript@7.9.0", "@babel/preset-typescript@^7.1.0", "@babel/preset-typescript@^7.10.4", "@babel/preset-typescript@^7.7.4": +"@babel/preset-typescript@7.9.0": + version "7.9.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz#87705a72b1f0d59df21c179f7c3d2ef4b16ce192" + integrity sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-typescript" "^7.9.0" + +"@babel/preset-typescript@^7.1.0", "@babel/preset-typescript@^7.7.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" integrity sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ== @@ -1047,7 +1349,21 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.0.0", "@babel/runtime@7.9.6", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c" + integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA== + dependencies: + regenerator-runtime "^0.12.0" + +"@babel/runtime@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" + integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.4.tgz#a6724f1a6b8d2f6ea5236dbfe58c7d7ea9c5eb99" integrity sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw== @@ -1078,7 +1394,25 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/types@7.8.3", "@babel/types@7.9.6", "@babel/types@^7.0.0", "@babel/types@^7.10.2", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0", "@babel/types@^7.6.1": +"@babel/types@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@babel/types@7.9.6": + version "7.9.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" + integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== + dependencies: + "@babel/helper-validator-identifier" "^7.9.5" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0", "@babel/types@^7.6.1", "@babel/types@^7.7.4", "@babel/types@^7.9.6": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== @@ -1184,7 +1518,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.27": +"@emotion/core@^10.0.27", "@emotion/core@^10.0.28": version "10.0.28" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== @@ -4249,7 +4583,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@4.13.0, browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.3: +browserslist@4.13.0, browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.12.0, browserslist@^4.8.3: version "4.13.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== @@ -6459,7 +6793,21 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^3.0.0, dot-prop@^4.1.1, dot-prop@^4.2.0, dot-prop@^5.2.0: +dot-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" + integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc= + dependencies: + is-obj "^1.0.0" + +dot-prop@^4.1.1, dot-prop@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +dot-prop@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== @@ -9119,6 +9467,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -13797,6 +14150,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" + integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== + regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" @@ -15571,7 +15929,16 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@4.8.0, terser@^4.1.2, terser@^4.7.0: +terser@4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^4.1.2, terser@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== @@ -16607,7 +16974,36 @@ webpack-sources@1.4.3, webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-s source-list-map "^2.0.0" source-map "~0.6.1" -webpack@4.44.0, webpack@^4.28.2, webpack@^4.41.0, webpack@^4.43.0, webpack@^4.44.1: +webpack@4.44.0: + version "4.44.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.0.tgz#3b08f88a89470175f036f4a9496b8a0428668802" + integrity sha512-wAuJxK123sqAw31SpkPiPW3iKHgFUiKvO7E7UZjtdExcsRe3fgav4mvoMM7vvpjLHVoJ6a0Mtp2fzkoA13e0Zw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.3.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.3" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.7.4" + webpack-sources "^1.4.1" + +webpack@^4.28.2, webpack@^4.41.0, webpack@^4.43.0: version "4.44.1" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==