tuya-panel-kit
Version:
a functional component library for developing tuya device panels!
1,166 lines (1,089 loc) • 33.2 kB
JavaScript
/* eslint-disable max-len */
/* eslint-disable prettier/prettier */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import {
ColorPropType,
Animated,
StyleSheet,
PanResponder,
View,
Easing,
ViewPropTypes,
} from 'react-native';
import _ from 'lodash';
// import Utils from '../../utils';
import { NumberUtils } from '../../utils';
const shallowCompare = require('react-addons-shallow-compare');
const styleEqual = require('style-equal');
const TRACK_SIZE = 4;
const THUMB_SIZE = 20;
const DEFAULT_ANIMATION_CONFIGS = {
spring: {
friction: 7,
tension: 100,
},
timing: {
duration: 150,
easing: Easing.inOut(Easing.ease),
delay: 0,
},
// decay : { // This has a serious bug
// velocity : 1,
// deceleration : 0.997
// }
};
class Rect {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
containsPoint(x, y) {
return x >= this.x && y >= this.y && x <= this.x + this.width && y <= this.y + this.height;
}
}
/* eslint-disable no-mixed-operators */
export default class Slider extends Component {
/* eslint-disable react/require-default-props */
static propTypes = {
/**
* 测试标志
*/
accessibilityLabel: PropTypes.string,
/**
* onLayout回调
*/
onLayout: PropTypes.func,
/**
* 当前值
*/
value: PropTypes.number,
/**
* 是否禁用
*/
disabled: PropTypes.bool,
/**
* 最小值
*/
minimumValue: PropTypes.number,
/**
* 最大值
*/
maximumValue: PropTypes.number,
/**
* 步长,取值必须大于 0,并且可被 (max - min) 整除
*/
stepValue: PropTypes.number,
/**
* 是否翻转数值
*/
reverseValue: PropTypes.bool, // eslint-disable-line
/**
* 小于当前值的轨道颜色
*/
minimumTrackTintColor: ColorPropType,
/**
* 大于当前值的轨道颜色
*/
maximumTrackTintColor: ColorPropType,
/**
* 滑块颜色
*/
thumbTintColor: ColorPropType,
/**
* 滑块大小
*/
thumbTouchSize: PropTypes.shape({
width: PropTypes.number,
height: PropTypes.number,
}),
/**
* 滑动值变更回调
*/
onValueChange: PropTypes.func,
/**
* 滑动开始回调
*/
onSlidingStart: PropTypes.func, // eslint-disable-line
/**
* 滑动结束回调
*/
onSlidingComplete: PropTypes.func, // eslint-disable-line
/**
* 滑动事件
*/
onScrollEvent: PropTypes.func,
/**
* 容器样式
*/
style: ViewPropTypes.style,
/**
* 通用的轨道样式
*/
trackStyle: ViewPropTypes.style,
/**
* 滑块样式
*/
thumbStyle: ViewPropTypes.style,
/**
* 是否开启调试区域
*/
debugTouchArea: PropTypes.bool,
/**
* 是否只显示大于当前值的轨道颜色
*/
onlyMaximumTrack: PropTypes.bool,
/**
* 触摸轨道是否可以更改值
*/
canTouchTrack: PropTypes.bool,
/**
* 是否添加动画滑动效果
*/
animateTransitions: PropTypes.bool,
/**
* 动画类型,spring 弹性动画或 timing 线性动画
*/
animationType: PropTypes.oneOf(['spring', 'timing']),
/**
* 动画配置
*/
animationConfig: PropTypes.object,
/**
* 定制渲染小于当前值的轨道
*/
renderMinimumTrack: PropTypes.func,
/**
* 定制渲染大于当前值的轨道
*/
renderMaximumTrack: PropTypes.func,
/**
* 定制渲染滑块
*/
renderThumb: PropTypes.func,
/**
* 是否为水平方向
*/
horizontal: PropTypes.bool,
/**
* 滑动条分为 2 种类型,parcel:轨道包裹滑块
*
*/
type: PropTypes.oneOf(['parcel', 'normal']),
/**
* 是否使用刻度
*
*/
useNoun: PropTypes.bool,
/**
* 大于当前值的刻度样式
*
*/
maxNounStyle: ViewPropTypes.style,
/**
* 小于当前值的刻度样式
*
*/
minNounStyle: ViewPropTypes.style,
};
static defaultProps = {
accessibilityLabel: 'Slider',
value: 0,
minimumValue: 0,
maximumValue: 1,
stepValue: 0,
reverseValue: false,
minimumTrackTintColor: '#3f3f3f',
maximumTrackTintColor: '#b3b3b3',
thumbTintColor: '#343434',
thumbTouchSize: { width: 40, height: 40 },
canTouchTrack: false,
animateTransitions: false,
debugTouchArea: false,
animationType: 'timing',
horizontal: true,
onlyMaximumTrack: false, // 大小滑动条一致时, 可以设置为True, 优化性能
type: 'normal',
useNoun: false,
maxNounStyle: null,
minNounStyle: null,
};
constructor(props) {
super(props);
this._measureContainer = this._measureContainer.bind(this);
this._measureTrack = this._measureTrack.bind(this);
this._measureThumb = this._measureThumb.bind(this);
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder.bind(this),
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder.bind(this),
onPanResponderGrant: this._handlePanResponderGrant.bind(this),
onPanResponderMove: this._handlePanResponderMove.bind(this),
onPanResponderRelease: this._handlePanResponderEnd.bind(this),
onPanResponderTerminationRequest: this._handlePanResponderRequestEnd.bind(this),
onPanResponderTerminate: this._handlePanResponderEnd.bind(this),
onStartShouldSetResponderCapture: this._handlePanResponderRequestEnd.bind(this),
onMoveShouldSetPanResponderCapture: this._handlePanResponderRequestEnd.bind(this),
});
this.oldValue = this._testValue(props.value, props);
this.touchLocked = false;
this.state = {
containerSize: { width: 0, height: 0 },
trackSize: { width: 0, height: 0 },
thumbSize: { width: 0, height: 0 },
allMeasured: false,
value: new Animated.Value(this.oldValue),
actualValue: this.oldValue,
};
}
componentWillReceiveProps(nextProps) {
if (this.props.value !== nextProps.value && !this.touchLocked) {
const newValue = this._testValue(nextProps.value, nextProps);
this.oldValue = newValue;
this.setState({
actualValue: newValue,
});
if (this.props.animateTransitions) {
this._setCurrentValueAnimated(newValue);
} else {
this._setCurrentValue(newValue);
}
}
}
shouldComponentUpdate(nextProps, nextState) {
return (
shallowCompare(
{ props: this._getPropsForComponentUpdate(this.props), state: this.state },
this._getPropsForComponentUpdate(nextProps),
nextState
) ||
!styleEqual(this.props.style, nextProps.style) ||
!styleEqual(this.props.trackStyle, nextProps.trackStyle) ||
!styleEqual(this.props.thumbStyle, nextProps.thumbStyle) ||
!styleEqual(this.props.thumbTouchSize, nextProps.thumbTouchSize)
);
}
setValue(value) {
if (this.touchLocked) return;
if (this.props.animateTransitions) {
this._setCurrentValueAnimated(value);
} else {
this._setCurrentValue(value);
}
}
/* istanbul ignore next */
// eslint-disable-next-line
setGestureGrant(gestureDistance) {
this._previousLeft = this._getThumbLeft(this._getCurrentValue());
this._fireChangeEvent('onSlidingStart');
}
/* istanbul ignore next */
setGestureMove(gestureDistance) {
const thumbLeft = this._previousLeft + gestureDistance;
this._setCurrentValue(this.__getValue(thumbLeft));
this._fireValueChange();
}
/* istanbul ignore next */
setGestureEnd(gestureDistance) {
const thumbLeft = this._previousLeft + gestureDistance;
this._setCurrentValue(this.__getValue(thumbLeft));
this._fireChangeEvent('onSlidingComplete');
}
_testValue(value, props) {
const v = props.reverseValue ? props.maximumValue + props.minimumValue - value : value;
return NumberUtils.inMaxMin(props.minimumValue, props.maximumValue, v);
}
_getPropsForComponentUpdate(props) {
const {
value, // eslint-disable-line
onValueChange, // eslint-disable-line
onSlidingStart, // eslint-disable-line
onSlidingComplete, // eslint-disable-line
onScrollEvent, // eslint-disable-line
style, // eslint-disable-line
trackStyle, // eslint-disable-line
thumbStyle, // eslint-disable-line
renderMinimumTrack, // eslint-disable-line
renderMaximumTrack, // eslint-disable-line
renderThumb, // eslint-disable-line
onLayout, // eslint-disable-line
thumbTouchSize, // eslint-disable-line
...neededProps
} = props;
return neededProps;
}
_handleStartShouldSetPanResponder(e) {
if (this.props.disabled) return false;
if (this.props.canTouchTrack) return true;
return this._thumbHitTest(e);
}
_handleMoveShouldSetPanResponder() {
return false;
}
// eslint-disable-next-line
_handlePanResponderGrant(event, gestureState) {
this.touchLocked = true;
if (this.props.canTouchTrack) {
const newValue = this._getValueByGestureEvent(event);
if (this.props.animateTransitions) {
this._setCurrentValueAnimated(newValue);
} else {
this._setCurrentValue(newValue);
}
this._previousLeft = this._getThumbLeft(newValue);
} else {
this._previousLeft = this._getThumbLeft(this._getCurrentValue());
}
this._fireChangeEvent('onSlidingStart');
// if (this.props.canTouchTrack) {
// this._fireValueChange();
// }
}
_handlePanResponderMove(event, gestureState) {
this._setCurrentValue(this._getValueByGestureState(gestureState));
this._fireValueChange();
}
_handlePanResponderRequestEnd() {
return false;
}
_handlePanResponderEnd(event, gestureState) {
this._setCurrentValue(this._getValueByGestureState(gestureState));
this._fireChangeEvent('onSlidingComplete');
this.touchLocked = false;
}
_measureContainer(x) {
this._handleMeasure('containerSize', x);
if (this.props.onLayout) this.props.onLayout(x);
}
_measureTrack(x) {
this._handleMeasure('trackSize', x);
}
_measureThumb(x) {
this._handleMeasure('thumbSize', x);
}
_handleMeasure(name, x) {
const { width, height } = x.nativeEvent.layout;
const size = { width, height };
const storeName = `_${name}`;
const currentSize = this[storeName];
if (currentSize && width === currentSize.width && height === currentSize.height) {
return;
}
this[storeName] = size;
if (this._containerSize && this._trackSize && this._thumbSize) {
this.setState({
containerSize: this._containerSize,
trackSize: this._trackSize,
thumbSize: this._thumbSize,
allMeasured: true,
});
}
}
_getRatio(value) {
return (value - this.props.minimumValue) / (this.props.maximumValue - this.props.minimumValue);
}
_getThumbLeft(value) {
return this._getThumbTranslate(value);
}
_getThumbTranslate(value) {
const ratio = this._getRatio(value);
const length = this.props.horizontal
? this.state.containerSize.width - this.state.thumbSize.width
: this.state.containerSize.height - this.state.thumbSize.height;
return ratio * length;
}
_getValueByGestureEvent(e) {
const thumbLeft = this.props.horizontal
? e.nativeEvent.locationX - this.props.thumbTouchSize.width / 2
: e.nativeEvent.locationY - this.props.thumbTouchSize.height / 2;
return this.__getValue(thumbLeft);
}
_getValueByGestureState(gestureState) {
const dsize = this.props.horizontal ? gestureState.dx : gestureState.dy;
const thumbLeft = this._previousLeft + dsize;
return this.__getValue(thumbLeft);
}
__getValue(thumbLeft) {
const length = this.props.horizontal
? this.state.containerSize.width - this.state.thumbSize.width
: this.state.containerSize.height - this.state.thumbSize.height;
const ratio = thumbLeft / length;
if (this.props.stepValue) {
return Math.max(
this.props.minimumValue,
Math.min(
this.props.maximumValue,
Math.round(
(ratio * (this.props.maximumValue - this.props.minimumValue)) / this.props.stepValue
) *
this.props.stepValue +
this.props.minimumValue
)
);
}
return Math.max(
this.props.minimumValue,
Math.min(
this.props.maximumValue,
ratio * (this.props.maximumValue - this.props.minimumValue) + this.props.minimumValue
)
);
}
_getCurrentValue() {
return this.state.value.__getValue();
}
_setCurrentValue(value) {
this.setState({
actualValue: value,
});
this.state.value.setValue(value);
}
_setCurrentValueAnimated(value) {
const { animationType } = this.props;
const animationConfig = Object.assign(
{},
DEFAULT_ANIMATION_CONFIGS[animationType],
this.props.animationConfig,
{ toValue: value }
);
Animated[animationType](this.state.value, animationConfig).start();
}
_fireValueChange() {
const value = this._getCurrentValue();
const newValue = this._testValue(value, this.props);
if (this.props.onValueChange && this.oldValue !== value) {
this.oldValue = value;
this.props.onValueChange(newValue);
}
if (this.props.onScrollEvent) {
this.props.onScrollEvent({ value: newValue });
}
}
_fireChangeEvent(event) {
const value = this._getCurrentValue();
const newValue = this._testValue(value, this.props);
if (this.props[event]) {
this.props[event](newValue);
}
if (this.props.onScrollEvent) {
this.props.onScrollEvent({ value: newValue });
}
}
_getTouchOverflowSize() {
const { state, props } = this;
const size = {};
if (state.allMeasured === true) {
if (this.props.horizontal) {
size.width = Math.max(0, props.thumbTouchSize.width - state.thumbSize.width);
size.height = Math.max(0, props.thumbTouchSize.height - state.containerSize.height);
} else {
size.width = Math.max(0, props.thumbTouchSize.width - state.containerSize.width);
size.height = Math.max(0, props.thumbTouchSize.height - state.thumbSize.height);
}
}
return size;
}
_getTouchOverflowStyle() {
const { width, height } = this._getTouchOverflowSize();
const touchOverflowStyle = {};
if (width !== undefined && height !== undefined) {
const verticalMargin = -height / 2;
touchOverflowStyle.marginTop = verticalMargin;
touchOverflowStyle.marginBottom = verticalMargin;
const horizontalMargin = -width / 2;
touchOverflowStyle.marginLeft = horizontalMargin;
touchOverflowStyle.marginRight = horizontalMargin;
}
if (this.props.debugTouchArea === true) {
touchOverflowStyle.backgroundColor = 'orange';
touchOverflowStyle.opacity = 0.5;
}
return touchOverflowStyle;
}
_thumbHitTest(e) {
const { nativeEvent } = e;
const thumbTouchRect = this._getThumbTouchRect();
return thumbTouchRect.containsPoint(nativeEvent.locationX, nativeEvent.locationY);
}
_getThumbTouchRect() {
const { state, props } = this;
const touchOverflowSize = this._getTouchOverflowSize();
const rect = this.props.horizontal
? new Rect(
touchOverflowSize.width / 2 +
this._getThumbLeft(this._getCurrentValue()) +
(state.thumbSize.width - props.thumbTouchSize.width) / 2,
touchOverflowSize.height / 2 +
(state.containerSize.height - props.thumbTouchSize.height) / 2,
props.thumbTouchSize.width,
props.thumbTouchSize.height
)
: new Rect(
touchOverflowSize.width / 2 +
(state.containerSize.width - props.thumbTouchSize.width) / 2,
touchOverflowSize.height / 2 +
this._getThumbLeft(this._getCurrentValue()) +
(state.thumbSize.height - props.thumbTouchSize.height) / 2,
props.thumbTouchSize.width,
props.thumbTouchSize.height
);
return rect;
}
_renderDebugThumbTouchRect(thumbLeft) {
const thumbTouchRect = this._getThumbTouchRect();
const positionStyle = this.props.horizontal
? {
left: thumbLeft,
top: thumbTouchRect.y,
width: thumbTouchRect.width,
height: thumbTouchRect.height,
}
: {
left: thumbTouchRect.x,
top: thumbLeft,
width: thumbTouchRect.width,
height: thumbTouchRect.height,
};
return (
<Animated.View
style={[defaultStyles.debugThumbTouchArea, positionStyle]}
pointerEvents="none"
/>
);
}
renderMaxNounView = () => {
const {
horizontal,
maxNounStyle,
stepValue,
minimumValue,
maximumValue,
type,
thumbTouchSize,
reverseValue,
} = this.props;
const { trackSize } = this.state;
const time = Math.floor((maximumValue - minimumValue) / stepValue);
if (horizontal) {
if (type === 'parcel') {
return _.times(time + 1, n => {
return (
<View
key={n}
style={[
{
width: 3,
height: 14,
borderRadius: 1.5,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
right:
thumbTouchSize.width / 2 +
(n * (trackSize.width - thumbTouchSize.width)) / time,
}
: {
left:
thumbTouchSize.width / 2 +
(n * (trackSize.width - thumbTouchSize.width)) / time,
},
maxNounStyle,
]}
/>
);
});
}
return _.times(time + 1, n => {
return (
<View
key={n}
style={[
{
width: trackSize.height,
height: trackSize.height,
borderRadius: trackSize.height,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
right:
n * trackSize.height +
(n * (trackSize.width - trackSize.height * (time + 1))) / time,
}
: {
left:
n * trackSize.height +
(n * (trackSize.width - trackSize.height * (time + 1))) / time,
},
maxNounStyle,
]}
/>
);
});
}
if (type === 'parcel') {
return _.times(time + 1, n => {
return (
<View
key={n}
style={[
{
width: 14,
height: 3,
borderRadius: 1.5,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
bottom:
thumbTouchSize.height / 2 +
(n * (trackSize.height - thumbTouchSize.height)) / time,
}
: {
top:
thumbTouchSize.height / 2 +
(n * (trackSize.height - thumbTouchSize.height)) / time,
},
maxNounStyle,
]}
/>
);
});
}
return _.times(time + 1, n => {
return (
<View
key={n}
style={[
{
width: trackSize.width,
height: trackSize.width,
borderRadius: trackSize.width,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
bottom:
n * trackSize.width +
(n * (trackSize.height - trackSize.width * (time + 1))) / time,
}
: {
top:
n * trackSize.width +
(n * (trackSize.height - trackSize.width * (time + 1))) / time,
},
maxNounStyle,
]}
/>
);
});
};
renderMinNounView = () => {
const {
horizontal,
minNounStyle,
stepValue,
minimumValue,
maximumValue,
type,
reverseValue,
thumbTouchSize,
} = this.props;
const { actualValue, trackSize } = this.state;
const actualNounNum = reverseValue
? Math.floor(maximumValue - actualValue) / stepValue + 1
: Math.floor(actualValue - minimumValue) / stepValue + 1;
const time = Math.floor(maximumValue - minimumValue) / stepValue;
if (horizontal) {
if (type === 'parcel') {
return _.times(actualNounNum, n => {
return (
<View
key={n}
style={[
{
width: 3,
height: 14,
borderRadius: 1.5,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
right:
thumbTouchSize.width / 2 +
(n * (trackSize.width - thumbTouchSize.width)) / time,
}
: {
left:
thumbTouchSize.width / 2 +
(n * (trackSize.width - thumbTouchSize.width)) / time,
},
minNounStyle,
]}
/>
);
});
}
return _.times(actualNounNum, n => {
if (n === actualNounNum - 1) return null;
return (
<View
key={n}
style={[
{
width: trackSize.height,
height: trackSize.height,
borderRadius: trackSize.height,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
right:
n * trackSize.height +
(n * (trackSize.width - trackSize.height * (time + 1))) / time,
}
: {
left:
n * trackSize.height +
(n * (trackSize.width - trackSize.height * (time + 1))) / time,
},
minNounStyle,
]}
/>
);
});
}
if (type === 'parcel') {
return _.times(actualNounNum, n => {
return (
<View
key={n}
style={[
{
width: 14,
height: 3,
borderRadius: 1.5,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
bottom:
thumbTouchSize.height / 2 +
n * 3 +
(n * (trackSize.height - 3 * (time + 1) - thumbTouchSize.height)) / time,
}
: {
top:
thumbTouchSize.height / 2 +
n * 3 +
(n * (trackSize.height - 3 * (time + 1) - thumbTouchSize.height)) / time,
},
minNounStyle,
]}
/>
);
});
}
return _.times(actualNounNum, n => {
if (n === actualNounNum - 1) return null;
return (
<View
key={n}
style={[
{
width: trackSize.width,
height: trackSize.width,
borderRadius: trackSize.width,
},
defaultStyles.parcelNumStyle,
reverseValue
? {
bottom:
n * trackSize.width +
(n * (trackSize.height - trackSize.width * (time + 1))) / time,
}
: {
top:
n * trackSize.width +
(n * (trackSize.height - trackSize.width * (time + 1))) / time,
},
minNounStyle,
]}
/>
);
});
};
render() {
const {
minimumValue,
maximumValue,
minimumTrackTintColor,
maximumTrackTintColor,
thumbTintColor,
styles, //eslint-disable-line
style,
trackStyle,
thumbStyle,
debugTouchArea,
renderMinimumTrack,
renderMaximumTrack,
renderThumb,
horizontal,
thumbTouchSize,
onlyMaximumTrack,
type,
reverseValue,
stepValue,
useNoun,
} = this.props;
const { value, containerSize, trackSize, thumbSize, allMeasured } = this.state;
const mainStyles = styles || defaultStyles;
const valueVisibleStyle = {};
let containerStyle = {};
let minimumTrackStyle = {};
let thumbTransformStyle = {};
let thumbTranslate = 0;
if (horizontal) {
containerStyle = { height: thumbTouchSize.height, flexDirection: 'column' };
const marginHeight = (containerSize.height - thumbSize.height) / 2;
if (allMeasured) {
thumbTranslate =
type === 'normal'
? value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [0, containerSize.width - thumbSize.width],
})
: value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [marginHeight, containerSize.width - thumbSize.width - marginHeight],
});
thumbTransformStyle = {
transform: [
{ translateX: thumbTranslate },
// 暂时注释 Y 轴 transform 保证基础样式渲染正常,不知什么原因
// { translateY: -(trackSize.height + thumbSize.height) / 2 },
],
};
if (!onlyMaximumTrack) {
if (type === 'normal') {
minimumTrackStyle = {
width: Animated.add(thumbTranslate, thumbSize.width / 2),
};
} else if (type === 'parcel' && reverseValue) {
minimumTrackStyle = {
overflow: 'hidden',
position: 'absolute',
right: 0,
width: Animated.add(
value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [containerSize.width - thumbSize.width - marginHeight, marginHeight],
}),
thumbSize.width + marginHeight
),
};
} else if (type === 'parcel' && !reverseValue) {
minimumTrackStyle = {
width: Animated.add(thumbTranslate, thumbSize.width + marginHeight),
};
}
}
}
} else {
containerStyle = { width: thumbTouchSize.width, flexDirection: 'row' };
const marginWidth = (containerSize.width - thumbSize.width) / 2;
if (allMeasured) {
thumbTranslate =
type === 'normal'
? value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [0, containerSize.height - thumbSize.height],
})
: value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [marginWidth, containerSize.height - thumbSize.height - marginWidth],
});
thumbTransformStyle = {
transform: [
{ translateY: thumbTranslate },
// { translateX: -(trackSize.width + thumbSize.width) / 2 },
],
};
if (!onlyMaximumTrack) {
if (type === 'normal') {
minimumTrackStyle = {
overflow: 'hidden',
position: 'absolute',
height: Animated.add(thumbTranslate, thumbSize.height / 2),
};
} else if (type === 'parcel' && reverseValue) {
minimumTrackStyle = {
overflow: 'hidden',
position: 'absolute',
bottom: 0,
height: Animated.add(
value.interpolate({
inputRange: [minimumValue, maximumValue],
outputRange: [containerSize.height - thumbSize.height - marginWidth, marginWidth],
}),
thumbSize.height + marginWidth
),
};
} else if (type === 'parcel' && !reverseValue) {
minimumTrackStyle = {
overflow: 'hidden',
position: 'absolute',
height: Animated.add(thumbTranslate, thumbSize.height + marginWidth),
};
}
}
}
}
if (!allMeasured) {
valueVisibleStyle.opacity = 0;
}
const touchOverflowStyle = this._getTouchOverflowStyle();
return (
<View
accessibilityLabel={this.props.accessibilityLabel}
onLayout={this._measureContainer}
style={[mainStyles.container, containerStyle, style]}
>
<View
style={[
{ overflow: 'hidden', backgroundColor: maximumTrackTintColor },
mainStyles.track,
trackStyle,
]}
onLayout={this._measureTrack}
>
{!!renderMaximumTrack && renderMaximumTrack()}
</View>
{!!stepValue && !!useNoun && this.renderMaxNounView()}
{!onlyMaximumTrack && (
<Animated.View
style={[
{
overflow: 'hidden',
position: 'absolute',
backgroundColor: minimumTrackTintColor,
},
horizontal ? { justifyContent: 'center' } : { alignItems: 'center' },
mainStyles.track,
trackStyle,
minimumTrackStyle,
valueVisibleStyle,
]}
>
{!!renderMinimumTrack && renderMinimumTrack()}
</Animated.View>
)}
{!!stepValue && !!useNoun && reverseValue && type !== 'parcel' && this.renderMaxNounView()}
<Animated.View
renderToHardwareTextureAndroid={true}
style={[
{ position: 'absolute', backgroundColor: thumbTintColor },
mainStyles.thumb,
thumbStyle,
thumbTransformStyle,
valueVisibleStyle,
]}
onLayout={this._measureThumb}
>
{!!renderThumb && renderThumb()}
</Animated.View>
{!!stepValue && !!useNoun && this.renderMinNounView()}
<View
style={[defaultStyles.touchArea, touchOverflowStyle]}
{...this._panResponder.panHandlers}
>
{debugTouchArea === true && this._renderDebugThumbTouchRect(thumbTranslate)}
</View>
</View>
);
}
}
Slider.Vertical = _props => (
<Slider {..._props} ref={_props.sliderRef} horizontal={false} styles={verticalStyles} />
);
Slider.Horizontal = _props => <Slider {..._props} ref={_props.sliderRef} horizontal={true} />;
Slider.dpView = WrappedComponent => _props => (
<WrappedComponent
{..._props}
minimumValue={_props.min || _props.minimumValue}
maximumValue={_props.max || _props.maximumValue}
stepValue={_props.step || _props.stepValue}
/>
);
const defaultStyles = StyleSheet.create({
// eslint-disable-next-line
container: {
justifyContent: 'center',
flexDirection: 'column',
},
// eslint-disable-next-line
track: {
height: TRACK_SIZE,
borderRadius: TRACK_SIZE / 2,
},
// eslint-disable-next-line
thumb: {
width: THUMB_SIZE,
height: THUMB_SIZE,
borderRadius: THUMB_SIZE / 2,
shadowColor: 'rgba(0,0,0,0.3)',
shadowOffset: {
width: 2,
height: 2,
},
shadowOpacity: 1,
shadowRadius: 2,
elevation: 2,
},
touchArea: {
position: 'absolute',
backgroundColor: 'transparent',
top: 0,
left: 0,
right: 0,
bottom: 0,
},
debugThumbTouchArea: {
position: 'absolute',
backgroundColor: 'green',
opacity: 0.5,
},
parcelNumStyle: {
backgroundColor: '#FFF',
position: 'absolute',
justifyContent: 'center',
},
});
export const verticalStyles = StyleSheet.create({
// eslint-disable-next-line
container: {
justifyContent: 'center',
flexDirection: 'row',
},
// eslint-disable-next-line
track: {
width: TRACK_SIZE,
borderRadius: TRACK_SIZE / 2,
},
// eslint-disable-next-line
thumb: {
width: THUMB_SIZE,
height: THUMB_SIZE,
borderRadius: THUMB_SIZE / 2,
shadowColor: 'rgba(0,0,0,0.3)',
shadowOffset: {
width: 2,
height: 2,
},
shadowOpacity: 1,
shadowRadius: 2,
elevation: 2,
},
});