UNPKG

@spaced-out/ui-design-system

Version:
361 lines (348 loc) 13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.wrangleMoment = exports.makeKey = exports.isValid = exports.isStartOfRange = exports.isStartDateEndDateSame = exports.isSameOrBefore = exports.isSameOrAfter = exports.isSame = exports.isEndOfRange = exports.isBetween = exports.isBefore = exports.isAfter = exports.inDateRange = exports.getValidDates = exports.getTranslation = exports.getTimezones = exports.getSubtractedDate = exports.getMonths = exports.getMonthEndDate = exports.getFormattedDate = exports.getDaysInMonth = exports.getDateRangePickerErrors = exports.getAvailableMonths = exports.getAddedDate = exports.generateAvailableYears = exports.formatIsoDate = exports.checkRangeValidity = exports.WEEKDAYS = exports.NAVIGATION_ACTION = exports.MARKERS = void 0; var _parseISO = _interopRequireDefault(require("date-fns/parseISO")); var _invariant = _interopRequireDefault(require("invariant")); var _lodash = require("lodash"); var _moment = _interopRequireDefault(require("moment")); var _timezones = require("./timezones"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } // $FlowFixMe - strict types for date-fns // $FlowFixMe[untyped-import] const makeKey = value => { try { if (value && typeof value === 'string') { return value.replace(/\(s\)/gi, '_s') // Replace (s) with _s (case-insensitive) .replace(/[^\w\s']/g, '') // Remove special chars except apostrophes .replace(/\s+/g, '_') // Spaces → underscores .replace(/_+/g, '_') // Collapse multiple ____ into _ .replace(/^_|_$/g, ''); // Trim leading/trailing _ } return value; } catch { return value; } }; exports.makeKey = makeKey; const NAVIGATION_ACTION = exports.NAVIGATION_ACTION = Object.freeze({ NEXT: 'next', PREV: 'prev' }); const MARKERS = exports.MARKERS = Object.freeze({ DATE_RANGE_START: 'FIRST', DATE_RANGE_END: 'SECOND' }); const WEEKDAYS = exports.WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']; const getMonths = t => [{ key: '0', label: getTranslation(t, 'Jan') }, { key: '1', label: getTranslation(t, 'Feb') }, { key: '2', label: getTranslation(t, 'Mar') }, { key: '3', label: getTranslation(t, 'Apr') }, { key: '4', label: getTranslation(t, 'May') }, { key: '5', label: getTranslation(t, 'Jun') }, { key: '6', label: getTranslation(t, 'Jul') }, { key: '7', label: getTranslation(t, 'Aug') }, { key: '8', label: getTranslation(t, 'Sep') }, { key: '9', label: getTranslation(t, 'Oct') }, { key: '10', label: getTranslation(t, 'Nov') }, { key: '11', label: getTranslation(t, 'Dec') }]; exports.getMonths = getMonths; const getDateRangePickerErrors = t => ({ MIN_MAX_INVALID: { type: 'MIN_MAX_INVALID', description: getTranslation(t, 'Given minDate and maxDate are invalid.') }, START_DATE_EARLY: { type: 'START_DATE_EARLY', description: getTranslation(t, 'Given startDate can not come before minDate.') }, START_DATE_LATE: { type: 'START_DATE_LATE', description: getTranslation(t, 'Given startDate can not come after endDate.') }, END_DATE_LATE: { type: 'END_DATE_LATE', description: getTranslation(t, 'Given endDate can not come after maxDate.') } }); exports.getDateRangePickerErrors = getDateRangePickerErrors; const checkRangeValidity = (rangeStart, rangeEnd, errorBody, onError) => { const isRangeStartValid = isValid(rangeStart); const isRangeEndValid = isRangeStartValid && isValid(rangeEnd); const isRangeValid = isRangeEndValid && isSameOrBefore(rangeStart, rangeEnd); (0, _invariant.default)(isRangeValid, JSON.stringify(errorBody)); if (!isRangeValid) { onError?.(errorBody); } return isRangeValid; }; exports.checkRangeValidity = checkRangeValidity; const wrangleMoment = date => { if (date instanceof Date) { return date; } else if (!date) { return new Date(); } return date instanceof _moment.default ? date.toDate() : (0, _parseISO.default)(date); }; exports.wrangleMoment = wrangleMoment; const formatIsoDate = function (date) { let format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'YYYY-MM-DD'; return _moment.default.utc(date).format(format); }; exports.formatIsoDate = formatIsoDate; const isStartOfRange = (_ref, date) => { let { startDate } = _ref; return Boolean(startDate) && _moment.default.utc(date).isSame(_moment.default.utc(startDate), 'd'); }; exports.isStartOfRange = isStartOfRange; const isEndOfRange = (_ref2, date) => { let { endDate } = _ref2; return Boolean(endDate) && _moment.default.utc(date).isSame(_moment.default.utc(endDate), 'd'); }; exports.isEndOfRange = isEndOfRange; const inDateRange = (_ref3, date) => { let { startDate, endDate } = _ref3; if (startDate && endDate) { const momentDay = _moment.default.utc(date); const momentStartDate = _moment.default.utc(startDate); const momentEndDate = _moment.default.utc(endDate); return isBetween(momentDay, momentStartDate, momentEndDate); } return false; }; exports.inDateRange = inDateRange; const isStartDateEndDateSame = _ref4 => { let { startDate, endDate } = _ref4; if (startDate && endDate) { return _moment.default.utc(startDate).isSame(_moment.default.utc(endDate), 'd'); } return false; }; exports.isStartDateEndDateSame = isStartDateEndDateSame; const getMonthAndYear = date => { const momentDate = date ? _moment.default.utc(date) : _moment.default.utc(); return [momentDate.month(), momentDate.year()]; }; const getDaysInMonth = date => { const startWeek = _moment.default.utc(date).startOf('month').startOf('week'); const endWeek = _moment.default.utc(date).endOf('month').endOf('week'); const days = [], current = startWeek; while (isBefore(current, endWeek)) { days.push(current.clone().format('YYYY-MM-DD')); current.add(1, 'd'); } const daysInChunks = (0, _lodash.chunk)(days, 7); // if total rows in calendar are 5 add one more week to the calendar if (daysInChunks.length === 5) { const nextWeek = getAddedDate(endWeek, WEEKDAYS.length, 'd'); const extraDays = []; while (isSameOrBefore(current, nextWeek)) { extraDays.push(current.clone().format('YYYY-MM-DD')); current.add(1, 'd'); } daysInChunks.push(extraDays); } return daysInChunks; }; exports.getDaysInMonth = getDaysInMonth; const getAddedDate = (date, addCount, timeUnit) => formatIsoDate(_moment.default.utc(date).add(addCount, timeUnit)); exports.getAddedDate = getAddedDate; const getSubtractedDate = (date, subtractCount, timeUnit) => formatIsoDate(_moment.default.utc(date).subtract(subtractCount, timeUnit)); exports.getSubtractedDate = getSubtractedDate; const getMonthEndDate = date => formatIsoDate(_moment.default.utc(date).endOf('M')); exports.getMonthEndDate = getMonthEndDate; const getTimezones = t => Object.keys(_timezones.TIMEZONES).reduce((menuOptions, key) => { menuOptions.push({ key, label: getTranslation(t, _timezones.TIMEZONES[key]) }); return menuOptions; }, []); exports.getTimezones = getTimezones; const generateAvailableYears = _ref5 => { let { marker, minDate, maxDate, rangeStartMonth, rangeEndMonth } = _ref5; const rangeStartYear = _moment.default.utc(rangeStartMonth).year(); const rangeEndYear = _moment.default.utc(rangeEndMonth).year(); const isWithinRange = year => marker === MARKERS.DATE_RANGE_START ? year <= rangeEndYear : year >= rangeStartYear; return (0, _lodash.range)(_moment.default.utc(minDate).year(), _moment.default.utc(maxDate).year() + 1).filter(year => isWithinRange(year)).map(year => ({ key: year.toString(), label: year.toString() })); }; exports.generateAvailableYears = generateAvailableYears; const getAvailableMonths = _ref6 => { let { marker, minDate, maxDate, rangeStartMonth, rangeEndMonth, t } = _ref6; const [rangeStartMonthKey, rangeStartYear] = getMonthAndYear(rangeStartMonth); const [rangeEndMonthKey, rangeEndYear] = getMonthAndYear(rangeEndMonth); const [minDateMonth, minDateYear] = getMonthAndYear(minDate); const [maxDateMonth, maxDateYear] = getMonthAndYear(maxDate); const MONTHS = getMonths(t); return MONTHS.filter(month => { const isSameYear = rangeStartYear === rangeEndYear; const isFirstAndMinDateYearSame = rangeStartYear === minDateYear; const isSecondAndMaxDateYearSame = rangeEndYear === maxDateYear; if (marker === MARKERS.DATE_RANGE_START) { if (isSameYear && month.key >= rangeEndMonthKey) { return false; } else if (isFirstAndMinDateYearSame && month.key < minDateMonth) { return false; } else { return true; } } else { if (isSameYear && month.key <= rangeStartMonthKey) { return false; } else if (isSecondAndMaxDateYearSame && month.key > maxDateMonth) { return false; } else { return true; } } }); }; exports.getAvailableMonths = getAvailableMonths; const getValidDates = _ref7 => { let { selectedDateRange, minDate, maxDate, today, onError, t } = _ref7; const { startDate, endDate } = selectedDateRange; const validMaxDate = maxDate && !(0, _lodash.isEmpty)(maxDate) ? maxDate : today; const validMinDate = minDate && !(0, _lodash.isEmpty)(minDate) ? minDate : getSubtractedDate(today, 8, 'y'); const isRangeValid = (min, max, errorMessage) => checkRangeValidity(min, max, errorMessage, onError); // minDate should be after maxDate const isMinMaxRangeInvalid = !isRangeValid(validMinDate, validMaxDate, getDateRangePickerErrors(t).MIN_MAX_INVALID); // if startDate is defined and then it should be after minDate const isStartDateInvalid = isMinMaxRangeInvalid || (0, _lodash.isEmpty)(startDate) || !isRangeValid(validMinDate, startDate, getDateRangePickerErrors(t).START_DATE_EARLY); if (isMinMaxRangeInvalid || isStartDateInvalid) { return { validDateRange: { startDate: null, endDate: null }, validMinDate, validMaxDate }; } // if endDate is defined then it should be before maxDate const isEndDateInvalid = (0, _lodash.isEmpty)(endDate) || !isRangeValid(endDate, validMaxDate, getDateRangePickerErrors(t).END_DATE_LATE); // startDate should be before endDate const isStartEndRangeInvalid = isEndDateInvalid || !isRangeValid(startDate, endDate, getDateRangePickerErrors(t).START_DATE_LATE); if (isEndDateInvalid || isStartEndRangeInvalid) { return { validDateRange: { startDate, endDate: null }, validMinDate, validMaxDate }; } return { validDateRange: { startDate: (0, _lodash.isEmpty)(startDate) ? null : startDate, endDate: (0, _lodash.isEmpty)(endDate) ? null : endDate }, validMinDate, validMaxDate }; }; // If date1 is same as date2 w.r.t the unit passed exports.getValidDates = getValidDates; const isSame = (date1, date2, unit) => _moment.default.utc(date1).isSame(_moment.default.utc(date2), unit); // If date1 is before date2 exports.isSame = isSame; const isBefore = (date1, date2) => _moment.default.utc(date1).isBefore(_moment.default.utc(date2)); // If date1 is after date2 w.r.t the unit passed exports.isBefore = isBefore; const isAfter = (date1, date2) => _moment.default.utc(date1).isAfter(_moment.default.utc(date2)); // If date1 is same or before date2 w.r.t the unit passed exports.isAfter = isAfter; const isSameOrBefore = (date1, date2, unit) => _moment.default.utc(date1).isSameOrBefore(_moment.default.utc(date2), unit); // If date1 is same or after date2 w.r.t the unit passed exports.isSameOrBefore = isSameOrBefore; const isSameOrAfter = (date1, date2, unit) => _moment.default.utc(date1).isSameOrAfter(_moment.default.utc(date2), unit); // If date is between startRange and endRange exports.isSameOrAfter = isSameOrAfter; const isBetween = (date, startRange, endRange) => _moment.default.utc(date).isBetween(_moment.default.utc(startRange), _moment.default.utc(endRange), null, '[]'); // If the date results in a date that exists in the calendar exports.isBetween = isBetween; const isValid = date => _moment.default.utc(date).isValid(); exports.isValid = isValid; const getFormattedDate = (marker, dateRange, locale) => { const { startDate, endDate } = dateRange; // set locale if provided if (locale) { _moment.default.locale(locale); } switch (marker) { case MARKERS.DATE_RANGE_START: return startDate ? _moment.default.utc(startDate).format('MMM DD, YYYY') : 'MMM DD, YYYY'; default: return endDate ? _moment.default.utc(endDate).format('MMM DD, YYYY') : 'MMM DD, YYYY'; } }; exports.getFormattedDate = getFormattedDate; const getTranslation = (t, labelToTranslate) => t ? t(makeKey(labelToTranslate), labelToTranslate) : labelToTranslate; exports.getTranslation = getTranslation;