react-toolbox/components/time_picker/TimePickerDialog.js

153 lines
4.5 KiB
JavaScript
Raw Normal View History

import React, { Component } from 'react';
import PropTypes from 'prop-types';
2017-01-26 20:05:32 +03:00
import cn from 'classnames';
import time from '../utils/time';
import Clock from './Clock';
2015-09-06 01:12:29 +03:00
2016-05-31 11:23:05 +03:00
const factory = (Dialog) => {
class TimePickerDialog extends Component {
static propTypes = {
active: PropTypes.bool,
cancelLabel: PropTypes.string,
2016-05-31 11:23:05 +03:00
className: PropTypes.string,
format: PropTypes.oneOf(['24hr', 'ampm']),
name: PropTypes.string,
okLabel: PropTypes.string,
2016-05-31 11:23:05 +03:00
onDismiss: PropTypes.func,
2016-07-10 14:42:35 +03:00
onEscKeyDown: PropTypes.func,
onOverlayClick: PropTypes.func,
2016-05-31 11:23:05 +03:00
onSelect: PropTypes.func,
theme: PropTypes.shape({
am: PropTypes.string,
amFormat: PropTypes.string,
ampm: PropTypes.string,
button: PropTypes.string,
dialog: PropTypes.string,
header: PropTypes.string,
hours: PropTypes.string,
hoursDisplay: PropTypes.string,
minutes: PropTypes.string,
minutesDisplay: PropTypes.string,
pm: PropTypes.string,
pmFormat: PropTypes.string,
2017-01-26 20:05:32 +03:00
separator: PropTypes.string,
2016-05-31 11:23:05 +03:00
}),
2017-01-26 20:05:32 +03:00
value: PropTypes.instanceOf(Date),
2016-05-31 11:23:05 +03:00
};
2015-09-06 01:12:29 +03:00
2016-05-31 11:23:05 +03:00
static defaultProps = {
active: false,
cancelLabel: 'Cancel',
2016-05-31 11:23:05 +03:00
format: '24hr',
okLabel: 'Ok',
2017-01-26 20:05:32 +03:00
value: new Date(),
2016-05-31 11:23:05 +03:00
};
2015-09-06 01:12:29 +03:00
2016-05-31 11:23:05 +03:00
state = {
display: 'hours',
2017-01-26 20:05:32 +03:00
displayTime: new Date(this.props.value.getTime()),
2016-05-31 11:23:05 +03:00
};
2015-09-06 01:12:29 +03:00
2017-01-26 20:05:32 +03:00
componentWillReceiveProps(nextProps) {
2016-11-16 14:14:55 +03:00
if (nextProps.value.getTime() !== this.state.displayTime.getTime()) {
this.setState({ displayTime: new Date(nextProps.value.getTime()) });
}
}
2017-01-26 20:05:32 +03:00
componentDidUpdate(prevProps) {
2016-05-31 11:23:05 +03:00
if (!prevProps.active && this.props.active) {
2017-01-26 20:05:32 +03:00
setTimeout(this.clockNode.handleCalculateShape, 1000);
2016-05-31 11:23:05 +03:00
}
2015-11-10 23:39:47 +03:00
}
2015-10-22 02:31:17 +03:00
2016-05-31 11:23:05 +03:00
handleClockChange = (value) => {
2017-01-26 20:05:32 +03:00
this.setState({ displayTime: value });
2016-05-31 11:23:05 +03:00
};
2015-10-22 02:31:17 +03:00
2016-05-31 11:23:05 +03:00
handleSelect = (event) => {
this.props.onSelect(this.state.displayTime, event);
};
2015-10-22 02:31:17 +03:00
2016-05-31 11:23:05 +03:00
toggleTimeMode = () => {
2017-01-26 20:05:32 +03:00
this.setState({ displayTime: time.toggleTimeMode(this.state.displayTime) });
2016-05-31 11:23:05 +03:00
};
2015-09-06 01:12:29 +03:00
2016-05-31 11:23:05 +03:00
handleHandMoved = () => {
2017-01-26 20:05:32 +03:00
if (this.state.display === 'hours') this.setState({ display: 'minutes' });
2016-05-31 11:23:05 +03:00
};
switchDisplay = (event) => {
2017-01-26 20:05:32 +03:00
this.setState({ display: event.target.id });
2016-05-31 11:23:05 +03:00
};
2015-09-06 01:12:29 +03:00
2017-01-26 20:05:32 +03:00
actions = [{
label: this.props.cancelLabel,
className: this.props.theme.button,
onClick: this.props.onDismiss,
}, {
label: this.props.okLabel,
className: this.props.theme.button,
name: this.props.name,
onClick: this.handleSelect,
}];
formatHours() {
2016-05-31 11:23:05 +03:00
if (this.props.format === 'ampm') {
return this.state.displayTime.getHours() % 12 || 12;
}
2017-01-26 20:05:32 +03:00
return this.state.displayTime.getHours();
2015-09-06 01:12:29 +03:00
}
2017-01-26 20:05:32 +03:00
renderAMPMLabels() {
2016-05-31 11:23:05 +03:00
const { theme } = this.props;
2017-01-26 20:05:32 +03:00
if (this.props.format !== 'ampm') return undefined;
return (
<div className={theme.ampm}>
<span className={theme.am} onClick={this.toggleTimeMode}>AM</span>
<span className={theme.pm} onClick={this.toggleTimeMode}>PM</span>
</div>
);
2016-05-31 11:23:05 +03:00
}
2017-01-26 20:05:32 +03:00
render() {
2016-05-31 11:23:05 +03:00
const { theme } = this.props;
const display = `${this.state.display}Display`;
const format = `${time.getTimeMode(this.state.displayTime)}Format`;
2017-01-26 20:05:32 +03:00
const className = cn([theme.dialog, theme[display], theme[format]], this.props.className);
2015-10-11 22:17:12 +03:00
return (
2016-07-10 14:42:35 +03:00
<Dialog
actions={this.actions}
active={this.props.active}
className={className}
onEscKeyDown={this.props.onEscKeyDown}
onOverlayClick={this.props.onOverlayClick}
>
2016-05-31 11:23:05 +03:00
<header className={theme.header}>
2017-01-26 20:05:32 +03:00
<span id="hours" className={theme.hours} onClick={this.switchDisplay}>
{(`0${this.formatHours()}`).slice(-2)}
2016-05-31 11:23:05 +03:00
</span>
<span className={theme.separator}>:</span>
2017-01-26 20:05:32 +03:00
<span id="minutes" className={theme.minutes} onClick={this.switchDisplay}>
{(`0${this.state.displayTime.getMinutes()}`).slice(-2)}
2016-05-31 11:23:05 +03:00
</span>
{this.renderAMPMLabels()}
</header>
<Clock
2017-01-26 20:05:32 +03:00
ref={(node) => { this.clockNode = node; }}
2016-05-31 11:23:05 +03:00
display={this.state.display}
format={this.props.format}
onChange={this.handleClockChange}
onHandMoved={this.handleHandMoved}
theme={this.props.theme}
time={this.state.displayTime}
/>
</Dialog>
2015-10-11 22:17:12 +03:00
);
2015-09-06 01:12:29 +03:00
}
}
2015-09-06 01:12:29 +03:00
2016-05-31 11:23:05 +03:00
return TimePickerDialog;
};
2015-10-22 02:31:17 +03:00
2016-05-31 11:23:05 +03:00
export default factory;