Skip to content

Commit 3cb3413

Browse files
Brian Stonestonebk
authored andcommitted
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.
1 parent a450420 commit 3cb3413

File tree

2 files changed

+32
-118
lines changed

2 files changed

+32
-118
lines changed

src/components/ReactSlider/ReactSlider.jsx

Lines changed: 11 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,6 @@ function stopPropagation(e) {
2121
}
2222
}
2323

24-
/**
25-
* Spreads `count` values equally between `min` and `max`.
26-
*/
27-
function linspace(min, max, count) {
28-
const range = (max - min) / (count - 1);
29-
const res = [];
30-
for (let i = 0; i < count; i += 1) {
31-
res.push(min + range * i);
32-
}
33-
return res;
34-
}
35-
3624
function ensureArray(x) {
3725
if (x == null) {
3826
return [];
@@ -104,13 +92,11 @@ class ReactSlider extends React.Component {
10492
minDistance: PropTypes.number,
10593

10694
/**
107-
* Determines the initial positions of the thumbs and the number of thumbs if the
108-
* component has no children.
95+
* Determines the initial positions of the thumbs and the number of thumbs.
10996
*
11097
* If a number is passed a slider with one thumb will be rendered.
11198
* If an array is passed each value will determine the position of one thumb.
11299
* The values in the array must be sorted.
113-
* If the component has children, the length of the array must match the number of children.
114100
*/
115101
defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.arrayOf(PropTypes.number)]),
116102

@@ -206,22 +192,6 @@ class ReactSlider extends React.Component {
206192
// eslint-disable-next-line zillow/react/require-default-props
207193
onSliderClick: PropTypes.func,
208194

209-
/**
210-
* Provide custom thumbs:
211-
*
212-
* <ReactSlider withTracks>
213-
* <div className="my-thumb">1</div>
214-
* <div className="my-thumb">2</div>
215-
* <div className="my-thumb">3</div>
216-
* </ReactSlider>
217-
*
218-
* Note: the children nodes must match the number of values provided
219-
* to `value` or `defaultValue`. To dynamically create custom thumb
220-
* content, use the `renderThumb` render prop.
221-
*/
222-
// eslint-disable-next-line zillow/react/require-default-props
223-
children: PropTypes.node,
224-
225195
/**
226196
* aria-label for screen-readers to apply to the thumbs.
227197
* Use an array for more than one thumb.
@@ -250,7 +220,6 @@ class ReactSlider extends React.Component {
250220

251221
/**
252222
* Provide a custom render function for dynamic thumb content.
253-
* For static thumb content, you can use the `children` prop.
254223
* The render function will be passed a single argument,
255224
* an object with the following properties:
256225
*
@@ -284,7 +253,10 @@ class ReactSlider extends React.Component {
284253
constructor(props) {
285254
super(props);
286255

287-
const value = this.or(ensureArray(props.value), ensureArray(props.defaultValue));
256+
let value = ensureArray(props.value);
257+
if (!value.length) {
258+
value = ensureArray(props.defaultValue);
259+
}
288260

289261
// reused throughout the component to store results of iterations over `value`
290262
this.tempArray = value.slice();
@@ -317,7 +289,11 @@ class ReactSlider extends React.Component {
317289
// Keep the internal `value` consistent with an outside `value` if present.
318290
// This basically allows the slider to be a controlled component.
319291
componentWillReceiveProps(newProps) {
320-
const value = this.or(ensureArray(newProps.value), this.state.value);
292+
let value = ensureArray(newProps.value);
293+
if (!value.length) {
294+
// eslint-disable-next-line prefer-destructuring
295+
value = this.state.value;
296+
}
321297

322298
// ensure the array keeps the same size as `value`
323299
this.tempArray = value.slice();
@@ -638,35 +614,6 @@ class ReactSlider extends React.Component {
638614
} while (this.pendingResizeTimeouts.length);
639615
}
640616

641-
// Check if the arity of `value` or `defaultValue` matches the number of children
642-
// (= number of custom thumbs).
643-
// If no custom thumbs are provided,
644-
// just returns `value` if present and `defaultValue` otherwise.
645-
// If custom thumbs are present but neither `value` nor `defaultValue` are applicable
646-
// the thumbs are spread out equally.
647-
// TODO: better name? better solution?
648-
or(value, defaultValue) {
649-
const count = React.Children.count(this.props.children);
650-
switch (count) {
651-
case 0:
652-
return value.length > 0 ? value : defaultValue;
653-
case value.length:
654-
return value;
655-
case defaultValue.length:
656-
return defaultValue;
657-
default:
658-
if (value.length !== count || defaultValue.length !== count) {
659-
// eslint-disable-next-line no-console
660-
console.warn(
661-
`${
662-
this.constructor.displayName
663-
}: Number of values does not match number of children.`
664-
);
665-
}
666-
return linspace(this.props.min, this.props.max, count);
667-
}
668-
}
669-
670617
start(i, position) {
671618
const activeEl = document.activeElement;
672619
const thumbRef = this[`thumb${i}`];
@@ -912,11 +859,7 @@ class ReactSlider extends React.Component {
912859
}
913860

914861
const res = [];
915-
if (React.Children.count(this.props.children) > 0) {
916-
React.Children.forEach(this.props.children, (child, i) => {
917-
res[i] = this.renderThumb(styles[i], child, i);
918-
});
919-
} else if (this.props.renderThumb) {
862+
if (this.props.renderThumb) {
920863
for (let i = 0; i < length; i += 1) {
921864
const child = this.props.renderThumb({
922865
index: i,

src/components/ReactSlider/ReactSlider.md

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,62 @@
1-
### Single slider
2-
3-
Similar to `<input type="range" defaultValue={50} />`
1+
Single slider, similar to `<input type="range" defaultValue={0} />`
42

53
```jsx
6-
initialState = { value: 0 };
7-
84
<ReactSlider
95
className="horizontal-slider"
106
thumbClassName="example-thumb"
11-
value={state.value}
12-
onChange={value => setState({ value })}
13-
orientation="horizontal"
14-
ariaLabel="This is a single thumb"
15-
>
16-
<div>{state.value}</div>
17-
</ReactSlider>
7+
trackClassName="example-track"
8+
renderThumb={({ value }) => value}
9+
/>
1810
```
1911

20-
### Double slider (with tracks between the thumbs)
12+
Double slider
2113

2214
```jsx
23-
initialState = { value: [0, 100] };
24-
2515
<ReactSlider
2616
className="horizontal-slider"
27-
trackClassName="example-track"
2817
thumbClassName="example-thumb"
29-
value={state.value}
30-
onChange={value => setState({ value })}
31-
orientation="horizontal"
32-
withTracks
18+
trackClassName="example-track"
19+
defaultValue={[0, 100]}
3320
ariaLabel={['Lower thumb', 'Upper thumb']}
34-
ariaValuetext="Some arbitrary value"
21+
renderThumb={({ value }) => value}
3522
pearling
3623
minDistance={10}
37-
>
38-
{state.value.map((value, i) => <div key={i}>{value}</div>)}
39-
</ReactSlider>
24+
/>
4025
```
4126

42-
### Multi slider
27+
Multi slider
4328

4429
```jsx
45-
initialState = { value: [0, 50, 100] };
46-
4730
<ReactSlider
4831
className="horizontal-slider"
49-
trackClassName="example-track"
5032
thumbClassName="example-thumb"
51-
value={state.value}
52-
onChange={value => setState({ value })}
53-
orientation="horizontal"
54-
withTracks
33+
trackClassName="example-track"
34+
defaultValue={[0, 50, 100]}
5535
ariaLabel={['Leftmost thumb', 'Middle thumb', 'Rightmost thumb']}
36+
renderThumb={({ value }) => value}
5637
pearling
5738
minDistance={10}
58-
>
59-
{state.value.map((value, i) => <div key={i}>{value}</div>)}
60-
</ReactSlider>
39+
/>
6140
```
6241

63-
### Vertical slider
42+
Vertical slider
6443

6544
```jsx
66-
initialState = { value: [0, 50, 100] };
67-
6845
<ReactSlider
6946
className="vertical-slider"
70-
trackClassName="example-track"
7147
thumbClassName="example-thumb"
72-
value={state.value}
73-
onChange={value => setState({ value })}
48+
trackClassName="example-track"
49+
defaultValue={[0, 50, 100]}
50+
ariaLabel={['Lowest thumb', 'Middle thumb', 'Top thumb']}
51+
renderThumb={({ value }) => value}
7452
orientation="vertical"
75-
withTracks
7653
invert
77-
ariaLabel={['Lowest thumb', 'Middle thumb', 'Top thumb']}
7854
pearling
7955
minDistance={10}
80-
>
81-
{state.value.map((value, i) => <div key={i}>{value}</div>)}
82-
</ReactSlider>
56+
/>
8357
```
8458

85-
### Custom styling with [styled-components](https://www.styled-components.com/)
86-
87-
The track and thumb nodes can be customized with the `renderTrack` and `renderThumb` render props.
59+
Custom styling using [styled-components](https://www.styled-components.com/)
8860

8961
```jsx
9062
import styled from 'styled-components';
@@ -118,7 +90,6 @@ const Track = ({ className, ...props }) => <StyledTrack {...props} />;
11890

11991
<StyledSlider
12092
defaultValue={[50, 75]}
121-
withTracks
12293
renderTrack={Track}
12394
renderThumb={Thumb}
12495
/>

0 commit comments

Comments
 (0)