tuya-panel-kit
Version:
a functional component library for developing tuya device panels!
309 lines (290 loc) • 8.49 kB
JavaScript
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { StyleSheet, ViewPropTypes } from 'react-native';
import { CoreUtils, TimeUtils, RatioUtils, ThemeUtils } from '../../utils';
import Picker from '../picker-view';
import { getHourSelections, getMinsSelections, getTimePrefixSelections, getPrefix } from './utils';
import { StyledTimerPickerContainer, StyledTimerPickerRow } from '../popup/styled';
const { omit } = CoreUtils;
const { parseTimer } = TimeUtils;
const { convertX: cx } = RatioUtils;
const { getPropsFromStyle } = ThemeUtils;
const TIME_PICKER_PROPS = [
'style',
'startTime',
'endTime',
'onTimerChange',
'is12Hours',
'singlePicker',
'prefixPosition',
];
export default class TimerPicker extends Component {
static propTypes = {
/**
* 测试标志
*/
accessibilityLabel: PropTypes.string,
/**
* 内容样式
*/
style: ViewPropTypes.style,
/**
* picker 是否支持手势
*/
disabled: PropTypes.bool,
/**
* 开始时间,minutes(0 - 1440)
*/
startTime: PropTypes.number,
/**
* 结束时间,minutes(0 - 1440)
*/
endTime: PropTypes.number,
/**
* 时间段更改回调
*/
onTimerChange: PropTypes.func,
/**
* 是否为 12 小时制
*/
is12Hours: PropTypes.bool,
/**
* 是否只需要一个picker
*/
singlePicker: PropTypes.bool,
/**
* 前缀位置(即 AMPM 位置)
*/
prefixPosition: PropTypes.oneOfType([PropTypes.array, PropTypes.oneOf(['left', 'right'])]),
/**
* picker 字体颜色
*/
pickerFontColor: PropTypes.string,
/**
* picker 字体大小
*/
pickerFontSize: PropTypes.number,
/**
* 前缀字符
*/
symbol: PropTypes.string,
/**
* 是否支持 picker 循环滚动
*/
loop: PropTypes.bool,
/**
* 上午文本
*/
amText: PropTypes.string,
/**
* 下午文本
*/
pmText: PropTypes.string,
};
static defaultProps = {
accessibilityLabel: 'TimerPicker',
style: {},
disabled: false,
startTime: 480,
endTime: 840,
onTimerChange: null,
is12Hours: true,
singlePicker: false,
prefixPosition: ['left', 'right'],
pickerFontColor: '#333',
symbol: '—',
pickerFontSize: cx(20),
loop: true,
amText: 'AM',
pmText: 'PM',
};
constructor(props) {
super(props);
const hours = getHourSelections(props.is12Hours);
this.minutes = getMinsSelections();
this.prefixs = getTimePrefixSelections(props.amText, props.pmText);
const [startHour, startMin] = parseTimer(props.startTime * 60)
.split(':')
.map(v => +v);
const [endHour, endMin] = parseTimer(props.endTime * 60)
.split(':')
.map(v => +v);
this.state = {
startHour,
startMin,
endHour,
endMin,
hours,
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.startTime !== this.props.startTime || nextProps.endTime !== this.props.endTime) {
this.parseTimer(nextProps.startTime, nextProps.endTime);
}
if (nextProps.is12Hours !== this.props.is12Hours) {
const hours = getHourSelections(nextProps.is12Hours);
this.setState({ hours });
}
}
componentWillUpdate(nextProps, nextState) {
const { onTimerChange } = nextProps;
if (nextState !== this.state) {
const startTime = parseInt(nextState.startHour, 10) * 60 + parseInt(nextState.startMin, 10);
const endTime = parseInt(nextState.endHour, 10) * 60 + parseInt(nextState.endMin, 10);
typeof onTimerChange === 'function' && onTimerChange(startTime, endTime);
}
}
onStartHourChange = startHour => {
this.setState({ startHour });
};
onStartMinChange = startMin => {
this.setState({ startMin });
};
onEndHourChange = endHour => {
this.setState({ endHour });
};
onEndMinChange = endMin => {
this.setState({ endMin });
};
onStartPrefixChange = startPrefix => {
const start = this.state.startHour;
if (startPrefix === 'AM' && start >= 12) {
this.setState({
startHour: start - 12,
});
}
if (startPrefix === 'PM' && start < 12) {
this.setState({
startHour: start + 12,
});
}
};
onEndPrefixChange = endPrefix => {
const end = this.state.endHour;
if (endPrefix === 'AM' && end >= 12) {
this.setState({
endHour: end - 12,
});
}
if (endPrefix === 'PM' && end < 12) {
this.setState({
endHour: end + 12,
});
}
};
parseTimer(startTime, endTime) {
const [startHour, startMin] = parseTimer(startTime * 60)
.split(':')
.map(v => +v);
const [endHour, endMin] = parseTimer(endTime * 60)
.split(':')
.map(v => +v);
this.setState({
startHour,
startMin,
endHour,
endMin,
});
}
renderPickView(values, value, onValueChange, loop, key) {
const { accessibilityLabel, pickerFontColor, pickerFontSize } = this.props;
const pickerProps = omit(this.props, TIME_PICKER_PROPS);
const style = StyleSheet.flatten([this.props.style]);
return (
<Picker
{...pickerProps}
accessibilityLabel={`${accessibilityLabel}_${key}`}
theme={{ fontColor: pickerFontColor, fontSize: pickerFontSize }}
selectedValue={value}
onValueChange={onValueChange}
contentContainerStyle={{ flex: 1 }}
style={[
{
flex: key === 'symbol' ? 0 : 1,
height: style.height || 200,
justifyContent: 'center',
backgroundColor: getPropsFromStyle('backgroundColor', style) || '#fff',
},
key === 'symbol' && {
width: cx(48),
},
]}
loop={loop}
>
{values.map((d, idx) => (
// eslint-disable-next-line react/no-array-index-key
<Picker.Item key={idx} value={d.value} label={d.label} />
))}
</Picker>
);
}
render() {
const { style, disabled, is12Hours, singlePicker, prefixPosition, symbol, loop } = this.props;
const { startHour, startMin, endHour, endMin, hours } = this.state;
const startPrefix = getPrefix(startHour);
const endPrefix = getPrefix(endHour);
let prefixPositionStart = prefixPosition;
let prefixPositionEnd = prefixPosition;
if (Array.isArray(prefixPosition)) {
[prefixPositionStart, prefixPositionEnd] = prefixPosition;
}
return (
<StyledTimerPickerContainer style={style} pointerEvents={disabled ? 'none' : 'auto'}>
<StyledTimerPickerRow>
{is12Hours &&
prefixPositionStart === 'left' &&
this.renderPickView(
this.prefixs,
startPrefix,
this.onStartPrefixChange,
false,
'StartAmpm'
)}
{this.renderPickView(hours, startHour, this.onStartHourChange, loop, 'StartHour')}
{this.renderPickView(this.minutes, startMin, this.onStartMinChange, loop, 'StartMinute')}
{is12Hours &&
prefixPositionStart === 'right' &&
this.renderPickView(
this.prefixs,
startPrefix,
this.onStartPrefixChange,
false,
'StartAmpm'
)}
</StyledTimerPickerRow>
{!!symbol &&
this.renderPickView(
[{ value: symbol, label: symbol }],
symbol,
() => {},
false,
'symbol'
)}
{!singlePicker && (
<StyledTimerPickerRow>
{is12Hours &&
prefixPositionEnd === 'left' &&
this.renderPickView(
this.prefixs,
endPrefix,
this.onEndPrefixChange,
false,
'EndAmpm'
)}
{this.renderPickView(hours, endHour, this.onEndHourChange, loop, 'EndHour')}
{this.renderPickView(this.minutes, endMin, this.onEndMinChange, loop, 'EndMinute')}
{is12Hours &&
prefixPositionEnd === 'right' &&
this.renderPickView(
this.prefixs,
endPrefix,
this.onEndPrefixChange,
false,
'EndAmpm'
)}
</StyledTimerPickerRow>
)}
</StyledTimerPickerContainer>
);
}
}