Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…terial-kit into awaidmann-master

# Conflicts:
#	lib/index.js
  • Loading branch information
xinthink committed Feb 12, 2016
2 parents 3ad17b2 + c3c5d17 commit 37c9962
Show file tree
Hide file tree
Showing 6 changed files with 672 additions and 145 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Have fun! :metal:
- [Progress bar](#progress-bar)
- [Spinner](#spinner)
- [Sliders](#sliders)
- [Range Slider](#range-slider)
- [Textfields](#text-fields)
- [Toggles](#toggles)
- [Checkbox](#checkbox)
Expand Down Expand Up @@ -258,10 +259,38 @@ const SliderWithValue = mdl.Slider.slider()

👉 [props reference][slider-props-doc] and [example code][slider-sample]

### Range Slider
![range-slider-demo]

```jsx
<mdl.RangeSlider style={styles.slider}/>
const SliderWithRange = mdl.RangeSlider.slider()
.withStyle(styles.slider)
.withMin(10)
.withMax(100)
.withMinValue(30)
.withMaxValue(50)
.build();
<SliderWithRange
ref=“sliderWithRange”
onChange={(curValue) => this.setState({
min: curValue.min,
max: curValue.max,
})
}
/>
```

👉 [props reference][range-slider-props-doc] and [example code][slider-sample]

[mdl-slider]: http://www.getmdl.io/components/index.html#sliders-section
[slider-demo]: https://cloud.githubusercontent.com/assets/390805/10123318/6c502e6e-6569-11e5-924a-62c8b850511c.gif
[range-slider-demo]: https://cloud.githubusercontent.com/assets/16245422/12763284/63a2dafc-c9a8-11e5-8fde-37b6f42a60c2.gif
[slider-sample]: https://github.com/xinthink/rnmk-demo/blob/master/app/sliders.js
[slider-props-doc]: http://www.xinthink.com/react-native-material-kit/docs/lib/mdl/Slider.html#props
[range-slider-props-doc]: http://www.xinthink.com/react-native-material-kit/docs/lib/mdl/RangeSlider.html#props

### Text Fields

Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export {
Ripple as MKRipple,
Progress as MKProgress,
Slider as MKSlider,
RangeSlider as MKRangeSlider,
Spinner as MKSpinner,
RadioButton as MKRadioButton,
Checkbox as MKCheckbox,
Expand Down
226 changes: 226 additions & 0 deletions lib/internal/Thumb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
//
// RangeSlider component.
//
// - [Props](#props)
// - [Defaults](#defaults)
// - [Built-in builders](#builders)
//
// Created by awaidman on 16/1/21.
//

const React = require('react-native');
const MKColor = require('../MKColor');

const {
Component,
Animated,
View,
PanResponder,
PropTypes,
} = React;


// Default color of the upper part of the track
const DEFAULT_UPPER_TRACK_COLOR = '#cccccc';

// Color of the thumb when lowest value is chosen
const LOWEST_VALUE_THUMB_COLOR = 'white';

// The max scale of the thumb
const THUMB_SCALE_RATIO = 1.3;

// Width of the thumb border
const THUMB_BORDER_WIDTH = 2;

// extra spacing enlarging the touchable area
const TRACK_EXTRA_MARGIN_H = 5;

// ## <section id='Thumb'>Thumb</section>
// `Thumb` component of the [`Slider`](#Slider).
class Thumb extends Component {
constructor(props) {
super(props);
this.x = 0; // current x-axis position

this._trackMarginH = (props.radius + THUMB_BORDER_WIDTH) * THUMB_SCALE_RATIO +
TRACK_EXTRA_MARGIN_H;
this._panResponder = {};
this._animatedLeft = new Animated.Value(0);
this._animatedScale = new Animated.Value(1);
this.state = {
color: LOWEST_VALUE_THUMB_COLOR,
borderColor: DEFAULT_UPPER_TRACK_COLOR,
};
}

componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onStartShouldSetPanResponderCapture: () => true,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onShouldBlockNativeResponder: () => true,

onPanResponderGrant: (evt) => { this.props.onGrant(this, evt); },
onPanResponderMove: (evt) => { this.props.onMove(this, evt); },
onPanResponderRelease: (evt) => { this.props.onEnd(this, evt); },
onPanResponderTerminate: (evt) => { this.props.onEnd(this, evt); },
});

this._onRadiiUpdate(this.props);
this.setState({
borderColor: this.props.disabledColor,
});
}

componentDidMount() {
this._animatedLeft.addListener(this._getOnSliding());
}

componentWillReceiveProps(nextProps) {
this._onRadiiUpdate(nextProps);
}

componentWillUnmount() {
this._animatedLeft.removeAllListeners();
}

// when thumb radii updated, re-calc the dimens
_onRadiiUpdate(props) {
this._radii = props.radius;
this._dia = this._radii * 2;
this._containerRadii = this._radii + THUMB_BORDER_WIDTH;
this._containerDia = this._containerRadii * 2;
}

// return a memoized function to handle sliding animation events
_getOnSliding() {
let prevX = this.x; // memorize the previous x

// on sliding of the thumb
// `value` - the `left` of the thumb, relative to the container
return ({ value }) => {
// convert to value relative to the track
const x = value + this._containerRadii - this._trackMarginH;

if (prevX <= 0 && x > 0) {
// leaving the lowest value, scale up the thumb
this._onExplode();
} else if (prevX > 0 && x <= 0) {
// at lowest value, scale down the thumb
this._onCollapse();
}

prevX = x;
};
}

// animate the sliding
// `x` - target position, relative to the track
moveTo(x) {
this.x = x;
const x0 = this.x + this._trackMarginH;

Animated.parallel([
Animated.timing(this._animatedScale, {
toValue: THUMB_SCALE_RATIO,
duration: 100,
}),
Animated.timing(this._animatedLeft, {
toValue: x0 - this._containerRadii,
duration: 0,
}),
]).start();
}

// stop sliding
confirmMoveTo() {
Animated.timing(this._animatedScale, {
toValue: 1,
duration: 100,
}).start();
}

// from 'lowest' to 'non-lowest'
_onExplode() {
this.setState({
borderColor: this.props.enabledColor,
color: this.props.enabledColor,
});
}

// from 'non-lowest' to 'lowest'
_onCollapse() {
this.setState({
borderColor: this.props.disabledColor,
color: LOWEST_VALUE_THUMB_COLOR,
});
}

// Rendering the `Thumb`
render() {
return (
<Animated.View
style={[ // the outer circle to draw the border
this.props.style,
{
width: this._containerDia,
height: this._containerDia,
backgroundColor: this.state.borderColor,
borderRadius: this._containerRadii,
position: 'absolute',
left: this._animatedLeft,
transform: [
{ scale: this._animatedScale },
],
},
]}
{ ...this._panResponder.panHandlers }
>
<View
style={{ // the inner circle
width: this._dia,
height: this._dia,
backgroundColor: this.state.color,
borderRadius: this._radii,
top: THUMB_BORDER_WIDTH,
left: THUMB_BORDER_WIDTH,
}}
/>
</Animated.View>
);
}
}

Thumb.propTypes = {
// [RN.View Props](https://facebook.github.io/react-native/docs/view.html#props)...
...View.propTypes,

// Callback to handle onPanResponderGrant gesture
onGrant: PropTypes.func,

// Callback to handle onPanResponderMove gesture
onMove: PropTypes.func,

// Callback to handle onPanResponderRelease/Terminate gesture
onEnd: PropTypes.func,

// Color when thumb has no value
disabledColor: PropTypes.string,

// Color when thumb has value
enabledColor: PropTypes.string,

// Radius of thumb component
radius: PropTypes.number,
};

// ## <section id='defaults'>Defaults</section>
Thumb.defaultProps = {
radius: 6,
disabledColor: DEFAULT_UPPER_TRACK_COLOR,
};

// ## Public interface
module.exports = Thumb;
Loading

0 comments on commit 37c9962

Please sign in to comment.