@allpro/form-manager
Version:
Data Manager for React Forms, or for any form data
1,869 lines (1,584 loc) • 217 kB
JavaScript
import { useState } from 'react';
import PropTypes from 'prop-types';
function toInteger (dirtyNumber) {
if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
return NaN
}
var number = Number(dirtyNumber);
if (isNaN(number)) {
return number
}
return number < 0 ? Math.ceil(number) : Math.floor(number)
}
var MILLISECONDS_IN_MINUTE = 60000;
/**
* Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
* They usually appear for dates that denote time before the timezones were introduced
* (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
* and GMT+01:00:00 after that date)
*
* Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
* which would lead to incorrect calculations.
*
* This function returns the timezone offset in milliseconds that takes seconds in account.
*/
function getTimezoneOffsetInMilliseconds (dirtyDate) {
var date = new Date(dirtyDate.getTime());
var baseTimezoneOffset = date.getTimezoneOffset();
date.setSeconds(0, 0);
var millisecondsPartOfTimezoneOffset = date.getTime() % MILLISECONDS_IN_MINUTE;
return baseTimezoneOffset * MILLISECONDS_IN_MINUTE + millisecondsPartOfTimezoneOffset
}
var MILLISECONDS_IN_HOUR = 3600000;
var MILLISECONDS_IN_MINUTE$1 = 60000;
var DEFAULT_ADDITIONAL_DIGITS = 2;
var patterns = {
dateTimeDelimiter: /[T ]/,
timeZoneDelimiter: /[Z ]/i,
timezone: /([Z+-].*)$/
};
var dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
var timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
var timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
/**
* @name parseISO
* @category Common Helpers
* @summary Parse ISO string
*
* @description
* Parse the given string in ISO 8601 format and return an instance of Date.
*
* Function accepts complete ISO 8601 formats as well as partial implementations.
* ISO 8601: http://en.wikipedia.org/wiki/ISO_8601
*
* If the argument isn't a string, the function cannot parse the string or
* the values are invalid, it returns Invalid Date.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* - The previous `parse` implementation was renamed to `parseISO`.
*
* ```javascript
* // Before v2.0.0
* parse('2016-01-01')
*
* // v2.0.0 onward
* parseISO('2016-01-01')
* ```
*
* - `parseISO` now validates separate date and time values in ISO-8601 strings
* and returns `Invalid Date` if the date is invalid.
*
* ```javascript
* parseISO('2018-13-32')
* //=> Invalid Date
* ```
*
* - `parseISO` now doesn't fall back to `new Date` constructor
* if it fails to parse a string argument. Instead, it returns `Invalid Date`.
*
* @param {String} argument - the value to convert
* @param {Object} [options] - an object with options.
* @param {0|1|2} [options.additionalDigits=2] - the additional number of digits in the extended year format
* @returns {Date} the parsed date in the local time zone
* @throws {TypeError} 1 argument required
* @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
*
* @example
* // Convert string '2014-02-11T11:30:30' to date:
* var result = parseISO('2014-02-11T11:30:30')
* //=> Tue Feb 11 2014 11:30:30
*
* @example
* // Convert string '+02014101' to date,
* // if the additional number of digits in the extended year format is 1:
* var result = parseISO('+02014101', { additionalDigits: 1 })
* //=> Fri Apr 11 2014 00:00:00
*/
function parseISO(argument, dirtyOptions) {
if (arguments.length < 1) {
throw new TypeError(
'1 argument required, but only ' + arguments.length + ' present'
)
}
var options = dirtyOptions || {};
var additionalDigits =
options.additionalDigits == null
? DEFAULT_ADDITIONAL_DIGITS
: toInteger(options.additionalDigits);
if (
additionalDigits !== 2 &&
additionalDigits !== 1 &&
additionalDigits !== 0
) {
throw new RangeError('additionalDigits must be 0, 1 or 2')
}
if (
!(
typeof argument === 'string' ||
Object.prototype.toString.call(argument) === '[object String]'
)
) {
return new Date(NaN)
}
var dateStrings = splitDateString(argument);
var date;
if (dateStrings.date) {
var parseYearResult = parseYear(dateStrings.date, additionalDigits);
date = parseDate(parseYearResult.restDateString, parseYearResult.year);
}
if (isNaN(date) || !date) {
return new Date(NaN)
}
var timestamp = date.getTime();
var time = 0;
var offset;
if (dateStrings.time) {
time = parseTime(dateStrings.time);
if (isNaN(time) || time === null) {
return new Date(NaN)
}
}
if (dateStrings.timezone) {
offset = parseTimezone(dateStrings.timezone);
if (isNaN(offset)) {
return new Date(NaN)
}
} else {
var fullTime = timestamp + time;
var fullTimeDate = new Date(fullTime);
offset = getTimezoneOffsetInMilliseconds(fullTimeDate);
// Adjust time when it's coming from DST
var fullTimeDateNextDay = new Date(fullTime);
fullTimeDateNextDay.setDate(fullTimeDate.getDate() + 1);
var offsetDiff =
getTimezoneOffsetInMilliseconds(fullTimeDateNextDay) - offset;
if (offsetDiff > 0) {
offset += offsetDiff;
}
}
return new Date(timestamp + time + offset)
}
function splitDateString(dateString) {
var dateStrings = {};
var array = dateString.split(patterns.dateTimeDelimiter);
var timeString;
if (/:/.test(array[0])) {
dateStrings.date = null;
timeString = array[0];
} else {
dateStrings.date = array[0];
timeString = array[1];
if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
timeString = dateString.substr(dateStrings.date.length, dateString.length);
}
}
if (timeString) {
var token = patterns.timezone.exec(timeString);
if (token) {
dateStrings.time = timeString.replace(token[1], '');
dateStrings.timezone = token[1];
} else {
dateStrings.time = timeString;
}
}
return dateStrings
}
function parseYear(dateString, additionalDigits) {
var regex = new RegExp(
'^(?:(\\d{4}|[+-]\\d{' +
(4 + additionalDigits) +
'})|(\\d{2}|[+-]\\d{' +
(2 + additionalDigits) +
'})$)'
);
var captures = dateString.match(regex);
// Invalid ISO-formatted year
if (!captures) return { year: null }
var year = captures[1] && parseInt(captures[1]);
var century = captures[2] && parseInt(captures[2]);
return {
year: century == null ? year : century * 100,
restDateString: dateString.slice((captures[1] || captures[2]).length)
}
}
function parseDate(dateString, year) {
// Invalid ISO-formatted year
if (year === null) return null
var captures = dateString.match(dateRegex);
// Invalid ISO-formatted string
if (!captures) return null
var isWeekDate = !!captures[4];
var dayOfYear = parseDateUnit(captures[1]);
var month = parseDateUnit(captures[2]) - 1;
var day = parseDateUnit(captures[3]);
var week = parseDateUnit(captures[4]) - 1;
var dayOfWeek = parseDateUnit(captures[5]) - 1;
if (isWeekDate) {
if (!validateWeekDate(year, week, dayOfWeek)) {
return new Date(NaN)
}
return dayOfISOWeekYear(year, week, dayOfWeek)
} else {
var date = new Date(0);
if (
!validateDate(year, month, day) ||
!validateDayOfYearDate(year, dayOfYear)
) {
return new Date(NaN)
}
date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
return date
}
}
function parseDateUnit(value) {
return value ? parseInt(value) : 1
}
function parseTime(timeString) {
var captures = timeString.match(timeRegex);
if (!captures) return null // Invalid ISO-formatted time
var hours = parseTimeUnit(captures[1]);
var minutes = parseTimeUnit(captures[2]);
var seconds = parseTimeUnit(captures[3]);
if (!validateTime(hours, minutes, seconds)) {
return NaN
}
return (
(hours % 24) * MILLISECONDS_IN_HOUR +
minutes * MILLISECONDS_IN_MINUTE$1 +
seconds * 1000
)
}
function parseTimeUnit(value) {
return (value && parseFloat(value.replace(',', '.'))) || 0
}
function parseTimezone(timezoneString) {
if (timezoneString === 'Z') return 0
var captures = timezoneString.match(timezoneRegex);
if (!captures) return 0
var sign = captures[1] === '+' ? -1 : 1;
var hours = parseInt(captures[2]);
var minutes = (captures[3] && parseInt(captures[3])) || 0;
if (!validateTimezone(hours, minutes)) {
return NaN
}
return (
sign * (hours * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE$1)
)
}
function dayOfISOWeekYear(isoWeekYear, week, day) {
var date = new Date(0);
date.setUTCFullYear(isoWeekYear, 0, 4);
var fourthOfJanuaryDay = date.getUTCDay() || 7;
var diff = (week || 0) * 7 + (day || 0) + 1 - fourthOfJanuaryDay;
date.setUTCDate(date.getUTCDate() + diff);
return date
}
// Validation functions
// February is null to handle the leap year (using ||)
var daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function isLeapYearIndex(year) {
return year % 400 === 0 || (year % 4 === 0 && year % 100)
}
function validateDate(year, month, date) {
return !(
month < 0 ||
month > 11 ||
date < 1 ||
date > (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28))
)
}
function validateDayOfYearDate(year, dayOfYear) {
return !(dayOfYear < 1 || dayOfYear > (isLeapYearIndex(year) ? 366 : 365))
}
function validateWeekDate(_year, week, day) {
return !(week < 0 || week > 52 || day < 0 || day > 6)
}
function validateTime(hours, minutes, seconds) {
return !(
seconds < 0 ||
seconds >= 60 ||
minutes < 0 ||
minutes >= 60 ||
hours < 0 ||
hours >= 25
)
}
function validateTimezone(_hours, minutes) {
return !(minutes < 0 || minutes > 59)
}
/**
* @name toDate
* @category Common Helpers
* @summary Convert the given argument to an instance of Date.
*
* @description
* Convert the given argument to an instance of Date.
*
* If the argument is an instance of Date, the function returns its clone.
*
* If the argument is a number, it is treated as a timestamp.
*
* If the argument is none of the above, the function returns Invalid Date.
*
* **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
*
* @param {Date|Number} argument - the value to convert
* @returns {Date} the parsed date in the local time zone
* @throws {TypeError} 1 argument required
*
* @example
* // Clone the date:
* var result = toDate(new Date(2014, 1, 11, 11, 30, 30))
* //=> Tue Feb 11 2014 11:30:30
*
* @example
* // Convert the timestamp to date:
* var result = toDate(1392098430000)
* //=> Tue Feb 11 2014 11:30:30
*/
function toDate(argument) {
if (arguments.length < 1) {
throw new TypeError(
'1 argument required, but only ' + arguments.length + ' present'
)
}
var argStr = Object.prototype.toString.call(argument);
// Clone the date
if (
argument instanceof Date ||
(typeof argument === 'object' && argStr === '[object Date]')
) {
// Prevent the date to lose the milliseconds when passed to new Date() in IE10
return new Date(argument.getTime())
} else if (typeof argument === 'number' || argStr === '[object Number]') {
return new Date(argument)
} else {
if (
(typeof argument === 'string' || argStr === '[object String]') &&
typeof console !== 'undefined'
) {
console.warn(
"Starting with v2.0.0-beta.1 date-fns doesn't accept strings as arguments. Please use `parseISO` to parse strings. See: https://git.io/fjule"
);
console.warn(new Error().stack);
}
return new Date(NaN)
}
}
/**
* @name isDate
* @category Common Helpers
* @summary Is the given value a date?
*
* @description
* Returns true if the given value is an instance of Date. The function works for dates transferred across iframes.
*
* ### v2.0.0 breaking changes:
*
* - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
*
* @param {*} value - the value to check
* @returns {boolean} true if the given value is a date
* @throws {TypeError} 1 arguments required
*
* @example
* // For a valid date:
* var result = isDate(new Date())
* //=> true
*
* @example
* // For an invalid date:
* var result = isDate(new Date(NaN))
* //=> true
*
* @example
* // For some value:
* var result = isDate('2014-02-31')
* //=> false
*
* @example
* // For an object:
* var result = isDate({})
* //=> false
*/
function isDate(value) {
if (arguments.length < 1) {
throw new TypeError(
'1 argument required, but only ' + arguments.length + ' present'
)
}
return (
value instanceof Date ||
(typeof value === 'object' &&
Object.prototype.toString.call(value) === '[object Date]')
)
}
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var jsx = function () {
var REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7;
return function createRawReactElement(type, props, key, children) {
var defaultProps = type && type.defaultProps;
var childrenLength = arguments.length - 3;
if (!props && childrenLength !== 0) {
props = {};
}
if (props && defaultProps) {
for (var propName in defaultProps) {
if (props[propName] === void 0) {
props[propName] = defaultProps[propName];
}
}
} else if (!props) {
props = defaultProps || {};
}
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 3];
}
props.children = childArray;
}
return {
$$typeof: REACT_ELEMENT_TYPE,
type: type,
key: key === undefined ? null : '' + key,
ref: null,
props: props,
_owner: null
};
};
}();
var asyncIterator = function (iterable) {
if (typeof Symbol === "function") {
if (Symbol.asyncIterator) {
var method = iterable[Symbol.asyncIterator];
if (method != null) return method.call(iterable);
}
if (Symbol.iterator) {
return iterable[Symbol.iterator]();
}
}
throw new TypeError("Object is not async iterable");
};
var asyncGenerator = function () {
function AwaitValue(value) {
this.value = value;
}
function AsyncGenerator(gen) {
var front, back;
function send(key, arg) {
return new Promise(function (resolve, reject) {
var request = {
key: key,
arg: arg,
resolve: resolve,
reject: reject,
next: null
};
if (back) {
back = back.next = request;
} else {
front = back = request;
resume(key, arg);
}
});
}
function resume(key, arg) {
try {
var result = gen[key](arg);
var value = result.value;
if (value instanceof AwaitValue) {
Promise.resolve(value.value).then(function (arg) {
resume("next", arg);
}, function (arg) {
resume("throw", arg);
});
} else {
settle(result.done ? "return" : "normal", result.value);
}
} catch (err) {
settle("throw", err);
}
}
function settle(type, value) {
switch (type) {
case "return":
front.resolve({
value: value,
done: true
});
break;
case "throw":
front.reject(value);
break;
default:
front.resolve({
value: value,
done: false
});
break;
}
front = front.next;
if (front) {
resume(front.key, front.arg);
} else {
back = null;
}
}
this._invoke = send;
if (typeof gen.return !== "function") {
this.return = undefined;
}
}
if (typeof Symbol === "function" && Symbol.asyncIterator) {
AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
return this;
};
}
AsyncGenerator.prototype.next = function (arg) {
return this._invoke("next", arg);
};
AsyncGenerator.prototype.throw = function (arg) {
return this._invoke("throw", arg);
};
AsyncGenerator.prototype.return = function (arg) {
return this._invoke("return", arg);
};
return {
wrap: function (fn) {
return function () {
return new AsyncGenerator(fn.apply(this, arguments));
};
},
await: function (value) {
return new AwaitValue(value);
}
};
}();
var asyncGeneratorDelegate = function (inner, awaitWrap) {
var iter = {},
waiting = false;
function pump(key, value) {
waiting = true;
value = new Promise(function (resolve) {
resolve(inner[key](value));
});
return {
done: false,
value: awaitWrap(value)
};
}
if (typeof Symbol === "function" && Symbol.iterator) {
iter[Symbol.iterator] = function () {
return this;
};
}
iter.next = function (value) {
if (waiting) {
waiting = false;
return value;
}
return pump("next", value);
};
if (typeof inner.throw === "function") {
iter.throw = function (value) {
if (waiting) {
waiting = false;
throw value;
}
return pump("throw", value);
};
}
if (typeof inner.return === "function") {
iter.return = function (value) {
return pump("return", value);
};
}
return iter;
};
var asyncToGenerator = function (fn) {
return function () {
var gen = fn.apply(this, arguments);
return new Promise(function (resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(function (value) {
step("next", value);
}, function (err) {
step("throw", err);
});
}
}
return step("next");
});
};
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var defineEnumerableProperties = function (obj, descs) {
for (var key in descs) {
var desc = descs[key];
desc.configurable = desc.enumerable = true;
if ("value" in desc) desc.writable = true;
Object.defineProperty(obj, key, desc);
}
return obj;
};
var defaults = function (obj, defaults) {
var keys = Object.getOwnPropertyNames(defaults);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = Object.getOwnPropertyDescriptor(defaults, key);
if (value && value.configurable && obj[key] === undefined) {
Object.defineProperty(obj, key, value);
}
}
return obj;
};
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
var get = function get(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
};
var inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};
var _instanceof = function (left, right) {
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
return right[Symbol.hasInstance](left);
} else {
return left instanceof right;
}
};
var interopRequireDefault = function (obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
};
var interopRequireWildcard = function (obj) {
if (obj && obj.__esModule) {
return obj;
} else {
var newObj = {};
if (obj != null) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
};
var newArrowCheck = function (innerThis, boundThis) {
if (innerThis !== boundThis) {
throw new TypeError("Cannot instantiate an arrow function");
}
};
var objectDestructuringEmpty = function (obj) {
if (obj == null) throw new TypeError("Cannot destructure undefined");
};
var objectWithoutProperties = function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
};
var possibleConstructorReturn = function (self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};
var selfGlobal = typeof global === "undefined" ? self : global;
var set = function set(object, property, value, receiver) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent !== null) {
set(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
} else {
var setter = desc.set;
if (setter !== undefined) {
setter.call(receiver, value);
}
}
return value;
};
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
var slicedToArrayLoose = function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
var _arr = [];
for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
_arr.push(_step.value);
if (i && _arr.length === i) break;
}
return _arr;
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
var taggedTemplateLiteral = function (strings, raw) {
return Object.freeze(Object.defineProperties(strings, {
raw: {
value: Object.freeze(raw)
}
}));
};
var taggedTemplateLiteralLoose = function (strings, raw) {
strings.raw = raw;
return strings;
};
var temporalRef = function (val, name, undef) {
if (val === undef) {
throw new ReferenceError(name + " is not defined - temporal dead zone");
} else {
return val;
}
};
var temporalUndefined = {};
var toArray = function (arr) {
return Array.isArray(arr) ? arr : Array.from(arr);
};
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
var babelHelpers = /*#__PURE__*/Object.freeze({
jsx: jsx,
asyncIterator: asyncIterator,
asyncGenerator: asyncGenerator,
asyncGeneratorDelegate: asyncGeneratorDelegate,
asyncToGenerator: asyncToGenerator,
classCallCheck: classCallCheck,
createClass: createClass,
defineEnumerableProperties: defineEnumerableProperties,
defaults: defaults,
defineProperty: defineProperty,
get: get,
inherits: inherits,
interopRequireDefault: interopRequireDefault,
interopRequireWildcard: interopRequireWildcard,
newArrowCheck: newArrowCheck,
objectDestructuringEmpty: objectDestructuringEmpty,
objectWithoutProperties: objectWithoutProperties,
possibleConstructorReturn: possibleConstructorReturn,
selfGlobal: selfGlobal,
set: set,
slicedToArray: slicedToArray,
slicedToArrayLoose: slicedToArrayLoose,
taggedTemplateLiteral: taggedTemplateLiteral,
taggedTemplateLiteralLoose: taggedTemplateLiteralLoose,
temporalRef: temporalRef,
temporalUndefined: temporalUndefined,
toArray: toArray,
toConsumableArray: toConsumableArray,
typeof: _typeof,
extends: _extends,
instanceof: _instanceof
});
/**
* Helpers to avoid importing Lodash methods.
* Some ideas here taken from Lodash.
*/
var UNDEFINED = void 0;
var MAX_SAFE_INTEGER = 9007199254740991;
var protoToString = Object.prototype.toString;
var isUndefined = function isUndefined(v) {
return v === UNDEFINED;
};
var isNil = function isNil(v) {
return v === UNDEFINED || v === null;
};
function isType(v, type) {
if (isNil(v)) return false;
var t = typeof v === 'undefined' ? 'undefined' : _typeof(v);
if (t === type.toLowerCase()) return true;
return t === 'object' && protoToString.call(v) === '[object ' + type + ']';
}
var isArray = function isArray(v) {
return Array.isArray(v);
};
var isBoolean = function isBoolean(v) {
return v === true || v === false;
};
var isString = function isString(v) {
return isType(v, 'String');
};
var isRegExp = function isRegExp(v) {
return isType(v, 'RexExp');
};
var isObject = function isObject(v) {
return v != null && (typeof v === 'undefined' ? 'undefined' : _typeof(v)) === 'object';
};
var isFunction = function isFunction(v) {
return isType(v, 'Function');
};
var isNumber = function isNumber(v) {
return isType(v, 'Number');
};
var isInteger = function isInteger(v) {
return isNumber(v) && v % 1 === 0;
};
var isSafeInteger = function isSafeInteger(v) {
return isInteger(v) && v < MAX_SAFE_INTEGER;
};
var toString = function toString(v) {
return isNil(v) ? '' : typeof v === 'string' ? v : '' + v;
};
var toNumber = function toNumber(v) {
return isNumber(v) ? v : isBoolean(v) ? v ? 1 : 0 : v ? +v : 0;
};
var toInteger$1 = function toInteger(v) {
return isInteger(v) ? v : Math.floor(toNumber(v));
};
var trim = function trim(v) {
return isString(v) ? v.trim() : v;
};
var inRange = function inRange(v, v1, v2) {
return v >= v1 && v <= v2 || v <= v1 && v >= v2;
};
var omit = function omit(o, a) {
var keys = isArray(a) ? a : [a];
var obj = Object.assign({}, o);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var key = _step.value;
if (key) delete obj[key];
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return obj;
};
var uniq = function uniq(arr) {
return Array.from(new Set(arr));
};
var isPlainObject = function isPlainObject(v) {
if (!isObject(v) || protoToString.call(v) !== '[object Object]') {
return false;
}
if (Object.getPrototypeOf(v) === null) {
return true;
}
var proto = v;
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto);
}
return Object.getPrototypeOf(v) === proto;
};
var forOwn = function forOwn(o, fn) {
return Object.keys(o).forEach(function (key) {
return fn(o[key], key, o);
});
};
var isEmpty = function isEmpty(v) {
if (isNil(v)) return true;
if (isArray(v) || isString(v)) return !v.length();
if (isPlainObject(v)) return !Object.keys(v).length;
if (isType(v, 'Map') || isType(v, 'Set')) return !v.size;
return false;
};
// export const defaults = (o, d) => o
// export const defaultsDeep = (o, d) => o
var clone = function clone(v) {
return !v // Exit early for performance
? v : isPlainObject(v) ? Object.assign({}, v) : isArray(v) ? v.slice(v) : v;
};
function recursiveClone(branch) {
// Exit early for performance
if (!branch) return branch;
if (isPlainObject(branch)) {
var obj = {};
for (var key in branch) {
obj[key] = recursiveClone(branch[key]);
}
return obj;
}
if (isArray(branch)) {
var len = branch.length;
var arr = new Array(len);
for (var i = 0; i < len; i++) {
arr[i] = recursiveClone(branch[i]);
}
return arr;
}
// Return any other object or simple value unchanged
return branch;
}
var cloneDeep = function cloneDeep(obj) {
return recursiveClone(obj);
};
function mergeBranch(target, source) {
for (var key in source) {
var targetVal = target[key];
var sourceVal = source[key];
if (isPlainObject(targetVal) && isPlainObject(sourceVal)) {
mergeBranch(targetVal, sourceVal);
} else if (!isUndefined(sourceVal)) {
target[key] = sourceVal;
}
}
}
var merge = function merge(target) {
for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
sources[_key - 1] = arguments[_key];
}
if (isPlainObject(target)) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = sources[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var source = _step2.value;
if (isPlainObject(source)) {
mergeBranch(target, source);
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
return target;
};
function setDefaults(source, defaults, deep) {
if (!isPlainObject(source) || !isPlainObject(defaults)) return;
forOwn(defaults, function (val, key) {
var srcVal = source[key];
var defVal = defaults[key];
if (isUndefined(srcVal)) {
source[key] = isPlainObject(defVal) || isArray(defVal) ? cloneDeep(defVal) : defVal;
} else if (deep && isPlainObject(srcVal) && isPlainObject(defVal)) {
setDefaults(srcVal, defVal, true);
}
});
}
var defaults$1 = function defaults(srcObj) {
for (var _len2 = arguments.length, defObjs = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
defObjs[_key2 - 1] = arguments[_key2];
}
defObjs.forEach(function (defs) {
return setDefaults(srcObj, defs);
});
};
var defaultsDeep = function defaultsDeep(srcObj) {
for (var _len3 = arguments.length, defObjs = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
defObjs[_key3 - 1] = arguments[_key3];
}
defObjs.forEach(function (defs) {
return setDefaults(srcObj, defs, true);
});
};
var isEqual = function isEqual(v1, v2) {
var simpleValue = function simpleValue(val) {
// Undefined and Null are equal to "" for data comparison.
if (isNil(val)) return '';
// Stringify Array and Hash values for simple comparison; rarely needed.
if (isPlainObject(val) || isArray(val)) return JSON.stringify(val);
// Convert data objects to number for comparison
if (isDate(val)) return val.getTime();
return val;
};
return simpleValue(v1) === simpleValue(v2);
};
// Match timestamps with no date portion, like: "08:30" or "14:00:00"
var reTimeOnly = /^[\d]{2}:[\d]{2}[\d:]*$/;
var fixTimestamp = function fixTimestamp(date) {
return isString(date) && reTimeOnly.test(date) ? '1970-01-01T' + date : date;
};
/**
* PUBLIC UTILITY to create Date object, AND handle time-only strings
*
* @public
* @param {(string|number|Object)} date
* @returns {Date|*}
*/
var parseDate$1 = function parseDate(date) {
return isDate(date) ? date : isString(date) ? parseISO(fixTimestamp(date)) : toDate(date);
};
/**
* Helper methods used by FormManager; exported as an object of methods
*/
function itemToArray(item) {
// Avoid creating an array with just an empty string or other falsey value
if (!item) return [];
// ARRAY already - ASSUME has no nested arrays
if (isArray(item)) return item;
// HASH value; like a field-errors object
if (isPlainObject(item)) {
var arrItems = []; // init, may change
forOwn(item, function (value) {
if (value && value.length) {
if (isArray(value)) {
arrItems = arrItems.concat(value);
} else {
arrItems.push(value);
}
}
});
return arrItems;
}
// STRING or OTHER item
return [item];
}
/**
* Change all empty-string and undefined values to Null.
* Mutate the original object - caller should clone first if necessary.
*
* @param {Object} data
*/
var emptyValuesToNull = function emptyValuesToNull(data) {
forOwn(data, function (value, key) {
if (value === '' || value === undefined) {
data[key] = null;
}
});
};
/**
* Convert a fieldName into an array of keys - may only be one key.
* NOT exported - helper for get/setObjectValue methods
*
* @param {string} path
*/
function pathToKeysArray(path) {
// Dots delimit an 'object path'
return isArray(path) ? path : path.split('.');
}
/**
*
* @param {Object} hash Object to modify
* @param {(string|Array)} path String-path like 'data/who/gender'
* @param {Object} [opts] Configuration options
* @returns {*} Value at path or undefined if not found
*/
function getObjectValue(hash, path) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
if (!hash || !isPlainObject(hash)) return undefined;
var branch = hash;
// If a path was passed, trace the path inside state.form
if (path && path !== '/') {
// Slash(es) in the path indicate that we should recurse downward
var keys = pathToKeysArray(path);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var key = _step.value;
// If branch is not an object, then cannot recurse; abort
if (!isPlainObject(branch)) return undefined;
branch = branch[key];
// If requested key not found, abort
if (isUndefined(branch)) return undefined;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
return opts.cloneDeep ? cloneDeep(branch) : opts.clone ? clone(branch) : branch;
}
/**
*
* @param {Object} hash Object to modify
* @param {(string|Array)} path String-path like 'data/who/gender'
* @param {*} value Value - could be anything!
* @param {Object} [opts] Configuration
* @returns {boolean} True if value set; false if value unchanged
*/
function setObjectValue(hash, path, value) {
var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
if (!hash || !isPlainObject(hash)) return undefined;
var getValue = function getValue(val) {
return opts.cloneDeep ? cloneDeep(val) : opts.clone ? clone(val) : val;
};
// If a path was passed, recurse into the object
if (path && path !== '/') {
var keys = pathToKeysArray(path);
var lastIdx = keys.length - 1;
var lastKey = keys[lastIdx];
var branch = hash;
// Recurse into data hash for name-paths like 'who/location/address1'
for (var idx = 0; idx < lastIdx; idx++) {
var key = keys[idx];
var branchValue = branch[key];
// Create a branch (hash) here if it doesn't exist yet
// OVERWRITE any non-object value because path specifies it!
if (!isPlainObject(branchValue)) {
branch[key] = {};
}
// Update branch for next loop
branch = branch[key];
}
var oldValue = branch[lastKey];
// Check whether value has changed - ignore objects, assume changed
if (!isObject(value) && value === oldValue) {
return false; // Value was NOT updated
}
// If passed value is undefined, then DELETE the specified path
if (value === undefined) {
delete branch[lastKey]; // OK if key does not exist
return !isUndefined(oldValue); // True IF a value existed before
}
// Write the passed value at end of the path (last branch)
// Ignore any existing value - we do not merge data here.
if (opts.merge && isPlainObject(branch[lastKey]) && isPlainObject(value)) {
merge(branch[lastKey], getValue(value));
}
// Set value at path specified; clone value to break byRef
else {
branch[lastKey] = getValue(value);
}
return true; // Value was updated
} else if (isPlainObject(path)) {
// The path is an object (key/value pairs) to merge into hash-root
merge(hash, getValue(path));
return true; // Values were updated
} else {
console.warn('FormManager: No path specified to set value: "' + value + '"');
return false; // Value was NOT updated
}
}
/**
* FormManager sub-component to handle form-field data
*
* @param {Object} formManager FormManager instance object
* @param {Object} components Hash of FormManager sub-components
* @param {Object} components.config FormManagerConfig instance object
* @param {Object} components.state FormManagerState instance object
* @returns {Object} Config API for this instance
* @constructor
*/
function Data(formManager, components) {
// Auto-instantiate so 'new' keyword is NOT required
// (It's best practice to not require 'new' as it's an internal design)
if (!(this instanceof Data)) {
return new Data(formManager, components);
}
// NOTE: Cannot extract 'validation' here because NOT YET in 'components'!
var internal = components.internal,
config = components.config,
state = components.state;
// Extract helper methods for brevity
var fireEventCallback = internal.fireEventCallback,
triggerComponentUpdate = internal.triggerComponentUpdate;
var withFieldDefaults = config.withFieldDefaults,
aliasToRealName = config.aliasToRealName;
// Create local aliases for config objects
var formatters = config.get('formatters');
var converters = config.get('converters');
// DATA CACHES - both server and form versions of data
var stateOfValues = {};
var stateOfData = {};
var stateOfInitialData = {};
var dirtyFields = new Set();
return {
// Methods used internally by FormManager components
init: init,
get: getData, // GETTER for stateOfData
set: setData, // SETTER for stateOfData
getValue: getValue, // GETTER for one field-value
getValues: getValues, // GETTER for all field-values
setValue: setValue, // SETTER for one field-value
setValues: setValues, // SETTER for multiple field-values
cleanValue: cleanValue, // GETTER/PROCESSOR for one field
// Methods exposed in FormManager API
publicAPI: {
isDirty: isDirty, // Has ANY value in data changed?
isClean: isClean, // Has NO values in data changed?
getChanges: getChanges, // Return hash containing only changed data
getData: getData, // GETTER for stateOfData
getFieldData: getFieldData, // GETTER for one field-data
setData: setData, // SETTER for stateOfData
setFieldData: setFieldData, // SETTER for one field-data
getValue: getValue, // GETTER for one field-value
getValues: getValues, // GETTER for all field-values
setValue: setValue, // SETTER for one field-value
setValues: setValues, // SETTER for multiple field-values
cleanField: cleanField, // SETTER for one field
// ALIASES
data: getData,
value: getValue,
values: getValue,
changes: getChanges,
cleanFieldValue: cleanField
}
/**
* Initialize form data, state and errors using only the config-options
*
* @param {(undefined|Object)} [initialData]
* @param {(undefined|Object)} [data]
*/
};function init(initialData, data) {
stateOfData = {}; // In case called by form.reset()
if (initialData) setData(initialData);
if (data) setData(data);
}
/**
* PUBLIC GETTER for a specific field value.
*
* @public
* @param {string} name Field-name or alias-name
* @param {Object} [opts] Options
*/
function getValue(name) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var fieldName = aliasToRealName(name);
var fieldConfig = config.getField(fieldName) || {};
var value = stateOfValues[fieldName];
// Init or refresh the cached field-value in stateOfValues
if (opts.refresh || isUndefined(value)) {
setFormValueFromData(fieldName, undefined, { clean: true });
return stateOfValues[fieldName];
}
// Clean field-value - NOT cached!
return opts.clean ? cleanValue(value, fieldConfig) : value;
}
/**
* PUBLIC GETTER for ALL field values.
*
* @public
*/
function getValues() {
return cloneDeep(stateOfValues);
}
/**
* PUBLIC SETTER for a specific field value.
*
* @public
* @param {string} name Field-name or alias-name
* @param {*} value New value
* @param {Object} [opts] Options
* @returns {Object} All SETTERS return instance for chaining
*/
function setValue(name, value) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var fieldName = aliasToRealName(name);
var fieldConfig = config.getField(fieldName);
var setOpts = { clone: true };
var fieldValue = processFieldValue(value, fieldConfig, opts);
var dataValue = processDataValue(fieldValue, fieldConfig);
// Update the stateOfValues cache
stateOfValues[fieldName] = clone(fieldValue);
// Non-data fields are cached in state
if (fieldConfig && fieldConfig.isData === false) {
state.set(fieldName, dataValue, setOpts);
}
// Anything else is a data field, even if no field-config found
// because not all fields require a field configuration.
else {
setObjectValue(stateOfData, fieldName, dataValue, setOpts);
setIsDirty(fieldName, dataValue);
}
// Get methods from Validation component
var _components$validatio = components.validation,
isValidationEvent = _components$validatio.isValidationEvent,
validate = _components$validatio.validate;
var event = opts.event;
var validationEvent = opts.validate ? 'validate' : event;
var needsValidation = isValidationEvent(fieldName, validationEvent);
var validationPromise = null;
var onChangeForm = config.get('onChange');
var onChangeField = (config.getField(name) || {}).onChange;
// When triggered by a field-event, validate BEFORE firing callbacks
if (needsValidation) {
// A validation event MAY trigger validation & callback.
// Validation MAY run, depending on event-type.
// Validation is async so always returns a promise.
validationPromise = validate(name, dataValue, validationEvent, { update: true }).then(function () {
// If field value was changed, then fire events
// noinspection JSIncompatibleTypesComparison
if (event === 'change') {
fireEventCallback(onChangeField, value, name);
fireEventCallback(onChangeForm, value, name);
}
});
} else {
// noinspection JSIncompatibleTypesComparison
if (event === 'change') {
// Just fire form-level onChange, if one exists
fireEventCallback(onChangeForm, value, name);
}
}
// Note: opts.update default == true; must pass false to prevent update
if (opts.update !== false) {
triggerComponentUpdate();
}
return validationPromise || formManager;
}
/**
* PUBLIC SETTER for a specific field value.
*
* @public
* @param {Object} data Hash of new values keyed by fieldname or alias
* @param {Object} [opts] Options
* @returns {Object} All SETTERS return instance for chaining
*/
function setValues(data) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var update = opts.update;
var setOpts = _extends({}, opts, { update: false });
var validationPromises = [];
forOwn(data, function (value, name) {
var retVal = setValue(name, value, setOpts);
if (retVal.then) validationPromises.push(retVal);
});
// Trigger an immediate, synchronous render
triggerComponentUpdate();
if (validationPromises.length) {
var promise = Promise.all(validationPromises);
if (update) promise.then(triggerComponentUpdate);
return promise;
}
return formManager;
}
/**
* INTERNAL HELPER to parse a field-value from data-value
*
* @param {string} fieldName
* @param {*} [newDataValue]
* @param {Object} [opts] Options; defaults: { clean: false}
*/
function setFormValueFromData(fieldName, newDataValue) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var fieldConfig = config.getField(fieldName);
var value = !isUndefined(newDataValue) ? newDataValue : getFieldData(fieldName);
value = processFieldValue(value, fieldConfig, opts);
stateOfValues[fieldName] = clone(value);
}
/**
* INTERNAL HELPER to clean a field value
*
* @param {*} value
* @param {Object} fldCfg
* @returns {*}
*/
function cleanValue(value, fldCfg) {
if (!value) return value;
var val = value;
// The formatter may change the data-type, like number -> string
var reformat = withFieldDefaults(fldCfg, 'cleaning.reformat');
if (reformat) val = formatValue(val, reformat);
// Only string values can be trimmed
if (isString(value)) {
var trimOuter = withFieldDefaults(fldCfg, 'cleaning.trim');
var trimInner = withFieldDefaults(fldCfg, 'cleaning.trimInner');
if (trimOuter) val = val.trim();
if (trimInner) val = val.replace(/\s+/g, ' ');
}
return val;
}
function cleanField(name) {
var fieldName = aliasToRealName(name);
var fieldConfig = config.getField(fieldName);
// Field may NOT have a configuration, or could be a 'state' value
if (fieldConfig) {
var curValue = getValue(fieldName);
var newValue = cleanValue(curValue, fieldConfig);
if (newValue !== curValue) {
// Pass 'change' event so will fire event with new value
setValue(fieldName, newValue, { event: 'change' });
}
}
return formManager;
}
/**
* PUBLIC GETTER
*
* @param {string} name
* @returns {*} Data value for one-field
*/
function getFieldData(name) {
var fieldName = aliasToRealName(name);
var fieldConfig = config.getField(fieldName) || {};
return fieldConfig.isData === false ? state.get(fieldName) : getObjectValue(stateOfData, fieldName);
}
/**
* @returns {Object} All data
*/
function getData() {
return cloneDeep(stateOfData);
}
/**
* INTERNAL HELPER to convert, format and clean a FIELD-VALUE
*
* @param {*} value
* @param {(Object|undefined)} fieldConfig
* @param {Object} [opts]
* @returns {*}
*/
function processFieldValue(value, fieldConfig) {
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var val = value;
// Field may NOT have a configuration...
if (fieldConfig) {
// NOTE: A state-value is processed the same as a field-value
val = convertDataType(val, fieldConfig.valueType);
val = formatValue(val, fieldConfig.valueFormat);
val = und