material-ui-arabic-datepicker
Version:
React components, that implements material design date and time pickers for material-ui v1 including a customized Datepicker with arabic header, months and weekdays and English numbers, modfied implementation from materail-ui-pickers
308 lines (275 loc) • 7.69 kB
JSX
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import withStyles from '@material-ui/core/styles/withStyles';
import Fade from '@material-ui/core/Fade';
import PickerToolbar from '../_shared/PickerToolbar';
import ToolbarButton from '../_shared/ToolbarButton';
import HourView from './HourView';
import MinutesView from './MinutesView';
import SecondsView from './SecondsView';
import { convertToMeridiem } from '../_helpers/time-utils';
import withUtils from '../_shared/WithUtils';
export class TimePicker extends Component {
static propTypes = {
date: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
children: PropTypes.node,
utils: PropTypes.object.isRequired,
ampm: PropTypes.bool,
fadeTimeout: PropTypes.number.isRequired,
seconds: PropTypes.bool,
}
static defaultProps = {
children: null,
ampm: true,
seconds: false,
}
state = {
isHourViewShown: true,
isMinuteViewShown: false,
meridiemMode: this.props.utils.getHours(this.props.date) >= 12 ? 'pm' : 'am',
}
setMeridiemMode = mode => () => {
this.setState(
{ meridiemMode: mode },
() => this.handleChange({
time: this.props.date,
isFinish: false,
openMinutes: false,
openSeconds: false,
}),
);
}
handleChange = ({
time, isFinish, openMinutes, openSeconds,
}) => {
const withMeridiem = convertToMeridiem(
time,
this.state.meridiemMode,
this.props.ampm,
this.props.utils,
);
if (isFinish) {
if (!openMinutes && !openSeconds) {
this.props.onChange(withMeridiem, isFinish);
return;
}
if (openMinutes) {
this.openMinutesView();
}
if (openSeconds) {
this.openSecondsView();
}
}
this.props.onChange(withMeridiem, false);
}
handleHourChange = (time, isFinish) => {
this.handleChange({
time,
isFinish,
openMinutes: true,
openSeconds: false,
});
}
handleMinutesChange = (time, isFinish) => {
this.handleChange({
time,
isFinish,
openMinutes: false,
openSeconds: this.props.seconds,
});
}
handleSecondsChange = (time, isFinish) => {
this.handleChange({
time,
isFinish,
openMinutes: false,
openSeconds: false,
});
}
openSecondsView = () => {
this.setState({ isHourViewShown: false, isMinuteViewShown: false });
}
openMinutesView = () => {
this.setState({ isHourViewShown: false, isMinuteViewShown: true });
}
openHourView = () => {
this.setState({ isHourViewShown: true, isMinuteViewShown: false });
}
render() {
const {
classes, theme, date, utils, ampm, fadeTimeout, seconds,
} = this.props;
const { isHourViewShown, isMinuteViewShown, meridiemMode } = this.state;
const rtl = theme.direction === 'rtl';
const hourMinuteClassName = rtl
? classes.hourMinuteLabelReverse
: classes.hourMinuteLabel;
return (
<Fragment>
<PickerToolbar
className={classnames(
classes.toolbar,
{ [classes.toolbarLeftPadding]: ampm },
)}
>
<div className={hourMinuteClassName}>
<ToolbarButton
variant="display3"
onClick={this.openHourView}
selected={isHourViewShown}
label={utils.getHourText(date, ampm)}
/>
<ToolbarButton
variant="display3"
label=":"
selected={false}
className={classes.separator}
/>
<ToolbarButton
variant="display3"
onClick={this.openMinutesView}
selected={isMinuteViewShown}
label={utils.getMinuteText(date)}
/>
{
seconds &&
<Fragment>
<ToolbarButton
variant="display3"
label=":"
selected={false}
className={classes.separator}
/>
<ToolbarButton
variant="display3"
onClick={this.openSecondsView}
selected={!isHourViewShown && !isMinuteViewShown}
label={utils.getSecondText(date)}
/>
</Fragment>
}
</div>
{
ampm &&
<div className={seconds ? classes.ampmSelectionWithSeconds : classes.ampmSelection}>
<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'am'}
variant="subheading"
label={utils.getMeridiemText('am')}
onClick={this.setMeridiemMode('am')}
/>
<ToolbarButton
className={classes.ampmLabel}
selected={meridiemMode === 'pm'}
variant="subheading"
label={utils.getMeridiemText('pm')}
onClick={this.setMeridiemMode('pm')}
/>
</div>
}
</PickerToolbar>
{this.props.children}
<div className={classes.viewContainer}>
<Fade
timeout={fadeTimeout}
in={isHourViewShown}
mountOnEnter
unmountOnExit
>
<div className={classes.viewRoot}>
<HourView
date={date}
meridiemMode={meridiemMode}
onChange={this.handleHourChange}
utils={utils}
ampm={ampm}
/>
</div>
</Fade>
<Fade
timeout={fadeTimeout}
in={isMinuteViewShown}
mountOnEnter
unmountOnExit
>
<div className={classes.viewRoot}>
<MinutesView
date={date}
onChange={this.handleMinutesChange}
utils={utils}
/>
</div>
</Fade>
<Fade
timeout={fadeTimeout}
in={!isHourViewShown && !isMinuteViewShown}
mountOnEnter
unmountOnExit
>
<div className={classes.viewRoot}>
<SecondsView
date={date}
onChange={this.handleSecondsChange}
utils={utils}
/>
</div>
</Fade>
</div>
</Fragment>
);
}
}
const styles = () => ({
viewContainer: {
position: 'relative',
minHeight: 300,
minWidth: 260,
},
viewRoot: {
position: 'absolute',
left: 0,
right: 0,
},
toolbar: {
flexDirection: 'row',
alignItems: 'center',
},
toolbarLeftPadding: {
paddingLeft: 50,
},
separator: {
margin: '0 4px 0 2px',
cursor: 'default',
},
ampmSelection: {
marginLeft: 20,
marginRight: -20,
},
ampmSelectionWithSeconds: {
marginLeft: 15,
marginRight: 10,
},
ampmLabel: {
fontSize: 18,
},
hourMinuteLabel: {
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'flex-end',
},
hourMinuteLabelReverse: {
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'flex-end',
flexDirection: 'row-reverse',
},
});
export default withStyles(
styles,
{ withTheme: true, name: 'MuiPickersTimePicker' },
)(withUtils()(TimePicker));