@talend/react-components
Version:
Set of react components.
253 lines (249 loc) • 9.39 kB
JavaScript
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import { Component } from 'react';
import { isSameSecond } from 'date-fns/isSameSecond';
import PropTypes from 'prop-types';
import { FIELD_HOURS, FIELD_MINUTES, FIELD_SECONDS, HOUR_ERRORS, INPUT_ERRORS, MINUTES_ERRORS, SECONDS_ERRORS } from '../constants';
import { DateTimeContext } from '../Context';
import { check, checkHours, checkMinutes, checkSeconds, checkSupportedDateFormat, extractParts, extractPartsFromDateAndTime, extractPartsFromTextInput, getFullDateFormat } from '../date-extraction';
import { jsx as _jsx } from "react/jsx-runtime";
class ContextualManager extends Component {
constructor(props) {
super(props);
checkSupportedDateFormat(props.dateFormat);
this.inputErrorId = `${props.id}-input-error`;
this.hoursErrorId = `${props.id}-hours-error`;
this.minutesErrorId = `${props.id}-minutes-error`;
this.secondsErrorId = `${props.id}-seconds-error`;
this.initialState = extractParts(props.selectedDateTime, this.getDateOptions());
this.state = {
...this.initialState,
previousErrors: []
};
this.onInputFocus = this.onInputFocus.bind(this);
this.hasError = this.hasError.bind(this);
this.onReset = this.onReset.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onInputChange = this.onInputChange.bind(this);
this.onPickerChange = this.onPickerChange.bind(this);
}
componentDidUpdate(prevProps, prevState) {
const newSelectedDateTime = this.props.selectedDateTime;
const needDateTimeStateUpdate = newSelectedDateTime !== prevProps.selectedDateTime &&
// selectedDateTime props updated
newSelectedDateTime !== prevState.datetime &&
// not the same ref as state date time
!isSameSecond(newSelectedDateTime, prevState.datetime); // not the same value as state
if (prevProps.dateFormat !== this.props.dateFormat) {
checkSupportedDateFormat(this.props.dateFormat);
}
if (needDateTimeStateUpdate) {
const dateRelatedPartState = extractParts(newSelectedDateTime, this.getDateOptions());
this.setState(dateRelatedPartState);
}
}
onChange(event, origin) {
if (!this.props.onChange) {
return;
}
const {
errorMessage,
datetime,
textInput,
errors
} = this.state;
// we need to update the initial state once it has been changed
this.initialState = {
...this.state
};
this.props.onChange(event, {
errors,
errorMessage,
datetime,
textInput,
origin
});
}
onInputChange(event) {
const textInput = event.target.value;
const nextState = extractPartsFromTextInput(textInput, this.getDateOptions());
this.setState(oldState => ({
previousErrors: oldState.errors,
...nextState
}), () => {
if (!this.props.formMode) {
this.onChange(event, 'INPUT');
}
});
}
onPickerChange(event, {
date,
time,
field
}) {
const nextState = extractPartsFromDateAndTime(date, time, this.getDateOptions());
const isTimeUpdate = [FIELD_HOURS, FIELD_MINUTES, FIELD_SECONDS].includes(field);
const isTimeEmpty = !nextState.time.hours && !nextState.time.minutes && !nextState.time.seconds;
const isHybridMode = this.getDateOptions().hybridMode;
// we need to retrieve the input error from nextState to add them to the current one
// because, by changing the picker, we update the textInput so we need to update its errors
let nextErrors = this.state.errors
// remove old main input errors
.filter(error => !INPUT_ERRORS.includes(error.code))
// add new main input errors
.concat(nextState.errors.filter(error => INPUT_ERRORS.includes(error.code)));
if (isTimeUpdate) {
if (isHybridMode && isTimeEmpty) {
nextErrors = nextErrors.filter(error => !HOUR_ERRORS.includes(error.code) && !MINUTES_ERRORS.includes(error.code) && !SECONDS_ERRORS.includes(error.code));
} else {
// to avoid having errors on untouched time elements, we check only the updated part
let newError;
switch (field) {
case FIELD_HOURS:
newError = checkHours(time.hours, this.getDateOptions().hybridMode);
break;
case FIELD_MINUTES:
newError = checkMinutes(time.minutes, this.getDateOptions().hybridMode);
break;
case FIELD_SECONDS:
newError = checkSeconds(time.seconds, this.getDateOptions().hybridMode);
break;
default:
break;
}
// remove old error on updated time part
nextErrors = nextErrors.filter(error => field === FIELD_HOURS && !HOUR_ERRORS.includes(error.code) || field === FIELD_MINUTES && !MINUTES_ERRORS.includes(error.code) || field === FIELD_SECONDS && !SECONDS_ERRORS.includes(error.code));
// add the new error on updated time part
if (newError) {
nextErrors.push(newError);
}
}
}
this.setState({
previousErrors: this.state.errors,
...nextState,
errors: nextErrors
}, () => {
if (!this.props.formMode) {
this.onChange(event, 'PICKER');
}
});
}
onSubmit(event, origin) {
event.preventDefault();
// validation
// to avoid having error message change on invalid elements,
// we don't replace the error on those elements
let errors = check(this.state.date, this.state.time, this.getDateOptions());
errors = this.state.errors.filter(({
code
}) => !errors.find(error => error.code === code)).concat(errors);
this.setState({
errors,
errorMessage: errors[0] ? errors[0].message : ''
}, () => {
if (!errors.length) {
this.onChange(event, origin);
}
});
}
onInputFocus(event, focusedId) {
this.setState({
focusedInput: focusedId
});
}
onReset() {
// in form mode user has to explicitly validate the persist the selected date
// Otherwise, on picker close, the date is reset to the previous value
if (this.props.formMode) {
this.setState({
...this.initialState
});
}
}
getDateOptions() {
return {
dateFormat: this.props.dateFormat,
useTime: this.props.useTime,
useSeconds: this.props.useSeconds,
useUTC: this.props.useUTC,
required: this.props.required,
hybridMode: this.props.hybridMode
};
}
hasError(errorCodes) {
// no error management in component when not in formMode
if (!this.props.formMode) {
return false;
}
const errorCodesArray = Array.isArray(errorCodes) ? errorCodes : [errorCodes];
return !!this.state.errors.find(stateError => errorCodesArray.indexOf(stateError.code) > -1);
}
render() {
return /*#__PURE__*/_jsx(DateTimeContext.Provider, {
value: {
datetime: {
textInput: this.state.textInput,
date: this.state.date,
time: this.state.time
},
errorManagement: {
onInputFocus: this.onInputFocus,
focusedInput: this.state.focusedInput,
errors: this.state.errors,
hasError: this.hasError,
formMode: this.props.formMode,
inputErrorId: this.inputErrorId,
hoursErrorId: this.hoursErrorId,
minutesErrorId: this.minutesErrorId,
secondsErrorId: this.secondsErrorId
},
inputManagement: {
inputRef: ref => {
this.inputRef = ref;
},
onChange: this.onInputChange,
placeholder: getFullDateFormat(this.getDateOptions())
},
pickerManagement: {
onSubmit: this.onPickerChange,
useTime: this.props.useTime,
useSeconds: this.props.useSeconds,
useUTC: this.props.useUTC
},
formManagement: {
onReset: this.onReset,
onSubmit: this.onSubmit
}
},
children: this.props.children
});
}
}
_defineProperty(ContextualManager, "displayName", 'DateTime.Manager');
_defineProperty(ContextualManager, "propTypes", {
children: PropTypes.node,
dateFormat: PropTypes.string,
formMode: PropTypes.bool,
id: PropTypes.string.isRequired,
onChange: PropTypes.func,
hybridMode: PropTypes.bool,
required: PropTypes.bool,
selectedDateTime: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.number, PropTypes.string]),
useSeconds: PropTypes.bool,
useTime: PropTypes.bool,
useUTC: PropTypes.bool
});
_defineProperty(ContextualManager, "defaultProps", {
dateFormat: 'YYYY-MM-DD',
formMode: false,
hybridMode: false,
// default behaviour is to forbid empty values
required: true,
useSeconds: false,
useTime: false,
useUTC: false
});
export default ContextualManager;
//# sourceMappingURL=Manager.component.js.map