UNPKG

@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
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);