Skip to content

Commit 207bf75

Browse files
jbindahypest
authored andcommitted
[RNMobile] add RangeControl mobile implementation (slider) (#17282)
* add RangeCell
1 parent f94dadb commit 207bf75

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

packages/components/src/mobile/bottom-sheet/index.native.js

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import Button from './button';
1919
import Cell from './cell';
2020
import PickerCell from './picker-cell';
2121
import SwitchCell from './switch-cell';
22+
import RangeCell from './range-cell';
2223
import KeyboardAvoidingView from './keyboard-avoiding-view';
2324

2425
class BottomSheet extends Component {
@@ -173,5 +174,6 @@ ThemedBottomSheet.Button = Button;
173174
ThemedBottomSheet.Cell = Cell;
174175
ThemedBottomSheet.PickerCell = PickerCell;
175176
ThemedBottomSheet.SwitchCell = SwitchCell;
177+
ThemedBottomSheet.RangeCell = RangeCell;
176178

177179
export default ThemedBottomSheet;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { Platform } from 'react-native';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import Cell from './cell';
10+
import Slider from '../slider';
11+
12+
export default function BottomSheetRangeCell( props ) {
13+
const {
14+
value,
15+
defaultValue,
16+
onChangeValue,
17+
minimumValue = 0,
18+
maximumValue = 10,
19+
disabled,
20+
step = 1,
21+
minimumTrackTintColor = '#00669b',
22+
maximumTrackTintColor = Platform.OS === 'ios' ? '#e9eff3' : '#909090',
23+
thumbTintColor = Platform.OS === 'ios' ? '#fff' : '#00669b',
24+
...cellProps
25+
} = props;
26+
27+
return (
28+
<Cell
29+
editable={ false }
30+
{ ...cellProps }
31+
>
32+
<Slider
33+
value={ value }
34+
defaultValue={ defaultValue }
35+
disabled={ disabled }
36+
step={ step }
37+
minimumValue={ minimumValue }
38+
maximumValue={ maximumValue }
39+
minimumTrackTintColor={ minimumTrackTintColor }
40+
maximumTrackTintColor={ maximumTrackTintColor }
41+
thumbTintColor={ thumbTintColor }
42+
onChangeValue={ onChangeValue }
43+
/>
44+
</Cell>
45+
);
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { Slider as RNSlider, TextInput, View } from 'react-native';
5+
6+
/**
7+
* WordPress dependencies
8+
*/
9+
import { Component } from '@wordpress/element';
10+
11+
/**
12+
* Internal dependencies
13+
*/
14+
import styles from './styles.scss';
15+
16+
class Slider extends Component {
17+
constructor( props ) {
18+
super( props );
19+
this.handleToggleFocus = this.handleToggleFocus.bind( this );
20+
this.handleChange = this.handleChange.bind( this );
21+
this.handleValueSave = this.handleValueSave.bind( this );
22+
this.handleReset = this.handleReset.bind( this );
23+
24+
const initialValue = this.validateInput( props.value || props.defaultValue || props.minimumValue );
25+
26+
this.state = { hasFocus: false, initialValue, sliderValue: initialValue };
27+
}
28+
29+
componentDidUpdate( ) {
30+
const reset = this.props.value === null;
31+
if ( reset ) {
32+
this.handleReset();
33+
}
34+
}
35+
36+
handleToggleFocus( validateInput = true ) {
37+
const newState = { hasFocus: ! this.state.hasFocus };
38+
39+
if ( validateInput ) {
40+
const sliderValue = this.validateInput( this.state.sliderValue );
41+
this.handleValueSave( sliderValue );
42+
}
43+
44+
this.setState( newState );
45+
}
46+
47+
validateInput( text ) {
48+
const { minimumValue, maximumValue } = this.props;
49+
if ( ! text ) {
50+
return minimumValue;
51+
}
52+
if ( typeof text === 'number' ) {
53+
return Math.min( Math.max( text, minimumValue ), maximumValue );
54+
}
55+
return Math.min( Math.max( text.replace( /[^0-9]/g, '' ).replace( /^0+(?=\d)/, '' ), minimumValue ), maximumValue );
56+
}
57+
58+
handleChange( text ) {
59+
if ( ! isNaN( Number( text ) ) ) {
60+
this.setState( { sliderValue: text } );
61+
}
62+
}
63+
64+
handleValueSave( text ) {
65+
if ( ! isNaN( Number( text ) ) ) {
66+
if ( this.props.onChangeValue ) {
67+
this.props.onChangeValue( text );
68+
}
69+
this.setState( { sliderValue: text } );
70+
}
71+
}
72+
73+
handleReset() {
74+
this.handleValueSave( this.props.defaultValue || this.state.initialValue );
75+
}
76+
77+
render() {
78+
const {
79+
minimumValue,
80+
maximumValue,
81+
disabled,
82+
step,
83+
minimumTrackTintColor,
84+
maximumTrackTintColor,
85+
thumbTintColor,
86+
} = this.props;
87+
88+
const { hasFocus, sliderValue } = this.state;
89+
90+
return (
91+
<View style={ styles.sliderContainer }>
92+
<RNSlider
93+
value={ this.validateInput( sliderValue ) }
94+
disabled={ disabled }
95+
style={ styles.slider }
96+
step={ step }
97+
minimumValue={ minimumValue }
98+
maximumValue={ maximumValue }
99+
minimumTrackTintColor={ minimumTrackTintColor }
100+
maximumTrackTintColor={ maximumTrackTintColor }
101+
thumbTintColor={ thumbTintColor }
102+
onValueChange={ this.handleChange }
103+
onSlidingComplete={ this.handleValueSave }
104+
/>
105+
<TextInput
106+
style={ [ styles.sliderTextInput, hasFocus ? styles.isSelected : {} ] }
107+
onChangeText={ this.handleChange }
108+
onFocus={ this.handleToggleFocus }
109+
onBlur={ this.handleToggleFocus }
110+
keyboardType="numeric"
111+
value={ `${ sliderValue }` }
112+
/>
113+
</View>
114+
);
115+
}
116+
}
117+
118+
export default Slider;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.sliderContainer {
2+
flex: 1;
3+
flex-direction: row;
4+
align-content: center;
5+
justify-content: space-evenly;
6+
}
7+
8+
.slider {
9+
flex-grow: 1;
10+
}
11+
12+
.sliderTextInput {
13+
width: 40px;
14+
height: 25px;
15+
align-self: center;
16+
margin-left: 10px;
17+
border-width: 1px;
18+
border-radius: 4px;
19+
border-color: $dark-gray-150;
20+
padding-top: 0;
21+
padding-bottom: 0;
22+
}
23+
24+
.isSelected {
25+
border-width: 2px;
26+
border-color: $blue-wordpress;
27+
}

0 commit comments

Comments
 (0)