From 3cb34139b36de8c98b6052e0c691a8eed25e6061 Mon Sep 17 00:00:00 2001 From: Brian Stone Date: Wed, 24 Apr 2019 16:59:50 -0700 Subject: [PATCH] refactor: remove support for custom thumbs via `children` BREAKING CHANGE: custom thumbs via `children` is no longer supported. To customize thumbs, use the `renderThumb` render prop instead. --- src/components/ReactSlider/ReactSlider.jsx | 79 +++------------------- src/components/ReactSlider/ReactSlider.md | 71 ++++++------------- 2 files changed, 32 insertions(+), 118 deletions(-) diff --git a/src/components/ReactSlider/ReactSlider.jsx b/src/components/ReactSlider/ReactSlider.jsx index c8d5b532..fe2eeec6 100644 --- a/src/components/ReactSlider/ReactSlider.jsx +++ b/src/components/ReactSlider/ReactSlider.jsx @@ -21,18 +21,6 @@ function stopPropagation(e) { } } -/** - * Spreads `count` values equally between `min` and `max`. - */ -function linspace(min, max, count) { - const range = (max - min) / (count - 1); - const res = []; - for (let i = 0; i < count; i += 1) { - res.push(min + range * i); - } - return res; -} - function ensureArray(x) { if (x == null) { return []; @@ -104,13 +92,11 @@ class ReactSlider extends React.Component { minDistance: PropTypes.number, /** - * Determines the initial positions of the thumbs and the number of thumbs if the - * component has no children. + * Determines the initial positions of the thumbs and the number of thumbs. * * If a number is passed a slider with one thumb will be rendered. * If an array is passed each value will determine the position of one thumb. * The values in the array must be sorted. - * If the component has children, the length of the array must match the number of children. */ defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.arrayOf(PropTypes.number)]), @@ -206,22 +192,6 @@ class ReactSlider extends React.Component { // eslint-disable-next-line zillow/react/require-default-props onSliderClick: PropTypes.func, - /** - * Provide custom thumbs: - * - * - *
1
- *
2
- *
3
- *
- * - * Note: the children nodes must match the number of values provided - * to `value` or `defaultValue`. To dynamically create custom thumb - * content, use the `renderThumb` render prop. - */ - // eslint-disable-next-line zillow/react/require-default-props - children: PropTypes.node, - /** * aria-label for screen-readers to apply to the thumbs. * Use an array for more than one thumb. @@ -250,7 +220,6 @@ class ReactSlider extends React.Component { /** * Provide a custom render function for dynamic thumb content. - * For static thumb content, you can use the `children` prop. * The render function will be passed a single argument, * an object with the following properties: * @@ -284,7 +253,10 @@ class ReactSlider extends React.Component { constructor(props) { super(props); - const value = this.or(ensureArray(props.value), ensureArray(props.defaultValue)); + let value = ensureArray(props.value); + if (!value.length) { + value = ensureArray(props.defaultValue); + } // reused throughout the component to store results of iterations over `value` this.tempArray = value.slice(); @@ -317,7 +289,11 @@ class ReactSlider extends React.Component { // Keep the internal `value` consistent with an outside `value` if present. // This basically allows the slider to be a controlled component. componentWillReceiveProps(newProps) { - const value = this.or(ensureArray(newProps.value), this.state.value); + let value = ensureArray(newProps.value); + if (!value.length) { + // eslint-disable-next-line prefer-destructuring + value = this.state.value; + } // ensure the array keeps the same size as `value` this.tempArray = value.slice(); @@ -638,35 +614,6 @@ class ReactSlider extends React.Component { } while (this.pendingResizeTimeouts.length); } - // Check if the arity of `value` or `defaultValue` matches the number of children - // (= number of custom thumbs). - // If no custom thumbs are provided, - // just returns `value` if present and `defaultValue` otherwise. - // If custom thumbs are present but neither `value` nor `defaultValue` are applicable - // the thumbs are spread out equally. - // TODO: better name? better solution? - or(value, defaultValue) { - const count = React.Children.count(this.props.children); - switch (count) { - case 0: - return value.length > 0 ? value : defaultValue; - case value.length: - return value; - case defaultValue.length: - return defaultValue; - default: - if (value.length !== count || defaultValue.length !== count) { - // eslint-disable-next-line no-console - console.warn( - `${ - this.constructor.displayName - }: Number of values does not match number of children.` - ); - } - return linspace(this.props.min, this.props.max, count); - } - } - start(i, position) { const activeEl = document.activeElement; const thumbRef = this[`thumb${i}`]; @@ -912,11 +859,7 @@ class ReactSlider extends React.Component { } const res = []; - if (React.Children.count(this.props.children) > 0) { - React.Children.forEach(this.props.children, (child, i) => { - res[i] = this.renderThumb(styles[i], child, i); - }); - } else if (this.props.renderThumb) { + if (this.props.renderThumb) { for (let i = 0; i < length; i += 1) { const child = this.props.renderThumb({ index: i, diff --git a/src/components/ReactSlider/ReactSlider.md b/src/components/ReactSlider/ReactSlider.md index 8a6f0094..2ba12dd2 100644 --- a/src/components/ReactSlider/ReactSlider.md +++ b/src/components/ReactSlider/ReactSlider.md @@ -1,90 +1,62 @@ -### Single slider - -Similar to `` +Single slider, similar to `` ```jsx -initialState = { value: 0 }; - setState({ value })} - orientation="horizontal" - ariaLabel="This is a single thumb" -> -
{state.value}
-
+ trackClassName="example-track" + renderThumb={({ value }) => value} +/> ``` -### Double slider (with tracks between the thumbs) +Double slider ```jsx -initialState = { value: [0, 100] }; - setState({ value })} - orientation="horizontal" - withTracks + trackClassName="example-track" + defaultValue={[0, 100]} ariaLabel={['Lower thumb', 'Upper thumb']} - ariaValuetext="Some arbitrary value" + renderThumb={({ value }) => value} pearling minDistance={10} -> - {state.value.map((value, i) =>
{value}
)} -
+/> ``` -### Multi slider +Multi slider ```jsx -initialState = { value: [0, 50, 100] }; - setState({ value })} - orientation="horizontal" - withTracks + trackClassName="example-track" + defaultValue={[0, 50, 100]} ariaLabel={['Leftmost thumb', 'Middle thumb', 'Rightmost thumb']} + renderThumb={({ value }) => value} pearling minDistance={10} -> - {state.value.map((value, i) =>
{value}
)} -
+/> ``` -### Vertical slider +Vertical slider ```jsx -initialState = { value: [0, 50, 100] }; - setState({ value })} + trackClassName="example-track" + defaultValue={[0, 50, 100]} + ariaLabel={['Lowest thumb', 'Middle thumb', 'Top thumb']} + renderThumb={({ value }) => value} orientation="vertical" - withTracks invert - ariaLabel={['Lowest thumb', 'Middle thumb', 'Top thumb']} pearling minDistance={10} -> - {state.value.map((value, i) =>
{value}
)} -
+/> ``` -### Custom styling with [styled-components](https://www.styled-components.com/) - -The track and thumb nodes can be customized with the `renderTrack` and `renderThumb` render props. +Custom styling using [styled-components](https://www.styled-components.com/) ```jsx import styled from 'styled-components'; @@ -118,7 +90,6 @@ const Track = ({ className, ...props }) => ;