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
164 lines (137 loc) • 3.91 kB
JSX
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import withStyles from '@material-ui/core/styles/withStyles';
import ClockPointer from './ClockPointer';
import * as clockType from '../constants/clock-types';
import { getMinutes, getHours } from '../_helpers/time-utils';
export class Clock extends Component {
static propTypes = {
type: PropTypes.oneOf(Object.keys(clockType).map(key => clockType[key])).isRequired,
classes: PropTypes.object.isRequired,
value: PropTypes.number.isRequired,
onChange: PropTypes.func.isRequired,
children: PropTypes.arrayOf(PropTypes.node).isRequired,
ampm: PropTypes.bool,
}
static defaultProps = {
ampm: false,
}
setTime(e, isFinish = false) {
let { offsetX, offsetY } = e;
if (typeof offsetX === 'undefined') {
const rect = e.target.getBoundingClientRect();
offsetX = e.changedTouches[0].clientX - rect.left;
offsetY = e.changedTouches[0].clientY - rect.top;
}
const value = this.props.type === clockType.SECONDS || this.props.type === clockType.MINUTES
? getMinutes(offsetX, offsetY)
: getHours(offsetX, offsetY, this.props.ampm);
this.props.onChange(value, isFinish);
}
handleTouchMove = (e) => {
this.isMoving = true;
this.setTime(e);
}
handleTouchEnd = (e) => {
if (this.isMoving) {
this.setTime(e, true);
this.isMoving = false;
}
}
handleMove = (e) => {
e.preventDefault();
e.stopPropagation();
// MouseEvent.which is deprecated, but MouseEvent.buttons is not supported in Safari
const isButtonPressed = typeof e.buttons === 'undefined'
? e.nativeEvent.which === 1
: e.buttons === 1;
if (isButtonPressed) {
this.setTime(e.nativeEvent, false);
}
};
handleMouseUp = (e) => {
if (this.isMoving) {
this.isMoving = false;
}
this.setTime(e.nativeEvent, true);
}
hasSelected = () => {
const { type, value } = this.props;
if (type === clockType.HOURS) {
return true;
}
return value % 5 === 0;
}
render() {
const {
classes, value, children, type, ampm,
} = this.props;
const max = type === clockType.HOURS ? 12 : 60;
const isPointerInner = !ampm && type === clockType.HOURS && (value < 1 || value > 12);
return (
<div className={classes.container}>
<div
className={classes.clock}
>
<div
role="menu"
tabIndex={-1}
className={classes.squareMask}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
onMouseUp={this.handleMouseUp}
onMouseMove={this.handleMove}
/>
<div className={classes.pin} />
<ClockPointer
max={max}
value={value}
isInner={isPointerInner}
hasSelected={this.hasSelected()}
/>
{ children }
</div>
</div>
);
}
}
const styles = theme => ({
container: {
display: 'flex',
justifyContent: 'center',
alignItems: 'flex-end',
margin: [[theme.spacing.unit * 4, 0, theme.spacing.unit]],
},
clock: {
backgroundColor: 'rgba(0,0,0,.07)',
borderRadius: '50%',
height: 260,
width: 260,
position: 'relative',
pointerEvents: 'none',
zIndex: 1,
},
squareMask: {
width: '100%',
height: '100%',
position: 'absolute',
pointerEvents: 'auto',
outline: 'none',
touchActions: 'none',
userSelect: 'none',
'&:active': {
cursor: 'move',
},
},
pin: {
width: 6,
height: 6,
borderRadius: '50%',
backgroundColor: theme.palette.primary.main,
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
},
});
export default withStyles(styles, { name: 'MuiPickersClock' })(Clock);