@eccenca/gui-elements
Version:
Collection of low-level GUI elements like Buttons, Icons or Alerts. Also includes core styles for those elements.
179 lines (155 loc) • 5.03 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import Datetime from 'react-datetime';
import _ from 'lodash';
import moment from 'moment';
import TextField from '../TextField/TextField';
import ScrollingHOC from '../../hocs/ScrollingHOC';
const DateField = props => {
const {
// outer props
label,
value,
onChange,
className,
// inner props
placeholder,
disabled,
inputClassName,
// rest outer props
...otherProps
} = props;
delete otherProps.initialFormat;
delete otherProps.dateFormat;
delete otherProps.timeFormat;
delete otherProps.name;
delete otherProps.scrollElementIntoView;
delete otherProps.scrollIntoView;
// construct the date/time for moment
const getFormats = () => {
const { dateFormat, timeFormat } = props;
// set format output
const fullFormat = [];
let date = false;
let time = false;
if (dateFormat) {
date = _.isString(dateFormat) ? dateFormat : 'YYYY-MM-DD';
fullFormat.push(date);
}
if (timeFormat) {
time = _.isString(timeFormat) ? timeFormat : 'HH:mm:ss';
fullFormat.push(time);
}
if (_.isEmpty(fullFormat)) {
throw new Error(
'Datefield: Please define dateFormat, timeFormat or both.'
);
}
return {
date,
time,
full: fullFormat.join(' '),
};
};
const convertToMoment = (value, format) => {
if (moment.isMoment(value)) {
return value;
}
return moment(value, format, true);
};
const extendedOnChange = ({ onChange, value }) => {
const format = getFormats().full;
const newValue = convertToMoment(value, format);
const oldValue = convertToMoment(props.value, format);
// only return value if value is a new one
if (!oldValue.isSame(newValue) && _.isFunction(onChange)) {
onChange({
value: newValue,
rawValue: newValue,
isValid: newValue.isValid(),
name: props.name,
});
}
};
if (!moment.isMoment(value)) {
console.warn(
// eslint-disable-next-line max-len
'Datefield: Please provide the value as a Moment Object, otherwise it could result in false value conversions'
);
extendedOnChange({ onChange, value });
}
const textFieldOnChange = ({ rawValue }) => {
if (
rawValue !== props.value
&& _.isFunction(props.onChange)
) {
extendedOnChange({
onChange: props.onChange,
value: rawValue,
});
}
};
const renderInput = props => {
return (
<TextField
{...props}
stretch={props.stretch}
error={props.error}
onChange={textFieldOnChange}
/>
);
};
const inputProps = {
label: label || placeholder,
disabled,
className: className || inputClassName,
};
const formats = getFormats();
// try to convert value to moment object
const inputValue = convertToMoment(value, formats.full);
return (
<Datetime
value={
inputValue.isValid()
? inputValue
: inputValue.creationData().input
}
onChange={newValue => {
extendedOnChange({ onChange, value: newValue });
}}
dateFormat={formats.date}
timeFormat={formats.time}
strictParsing
inputProps={inputProps}
renderInput={renderInput}
{...otherProps}
/>
);
};
DateField.propTypes = {
label: PropTypes.string, // input label as string
value: PropTypes.oneOfType([
PropTypes.string, // date value as string
PropTypes.object, // can be a moment object as well
]),
onChange: PropTypes.func.isRequired, // on change function
timeFormat: PropTypes.oneOfType([
PropTypes.string, // time format as string
PropTypes.bool, // time select can be disabled
]),
dateFormat: PropTypes.oneOfType([
PropTypes.string, // date format as string
PropTypes.bool, // date select can be disabled
]),
placeholder: PropTypes.string, // text shown on empty input element
disabled: PropTypes.bool, // prevent change of input element
inputClassName: PropTypes.string, // class name of input element
input: PropTypes.bool, // show/hide input element
closeOnSelect: PropTypes.bool, // auto close picker after date select
};
DateField.defaultProps = {
timeFormat: false,
dateFormat: 'YYYY-MM-DD',
};
DateField.displayName = 'DateField';
export default ScrollingHOC(DateField);