UNPKG

informed

Version:

A lightweight framework and utility for building powerful forms in React applications

1,208 lines (1,111 loc) 40.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); var ObjectMap = require('./ObjectMap.js'); var debug$1 = require('./debug.js'); var proxy = require('./proxy.js'); var debug = debug$1.Debug('informed:utils' + '\t'); // https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript var uuidv4 = function uuidv4() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8; return v.toString(16); }); }; var getParentPath = function getParentPath(name) { // Example friends >>>> friends // Example father.name >>>> father // Example friends[0] >>>> friends // Example friends[0].father.name >>>> friends[0].father // Example friends[0].father.siblings[1].name >>>> friends[0].father.siblings[1] var parentArrayPath = name.replace(/(.*)[.[].*/, '$1'); return parentArrayPath; }; function debounceByName(func) { var _this = this; var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300; var timers = {}; return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var name = args[0]; clearTimeout(timers[name]); // console.log('CLEARING', name); timers[name] = setTimeout(function () { // console.log('APPLYING', name); func.apply(_this, args); }, timeout); }; } function debounce(func) { var _this2 = this; var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300; var timer; return function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } clearTimeout(timer); timer = setTimeout(function () { func.apply(_this2, args); }, timeout); }; } // Example debounce // function saveInput(){ // console.log('Saving data'); // } // const processChange = debounce(() => saveInput()); // Elon ----------- var Elon = /*#__PURE__*/function () { function Elon() { _rollupPluginBabelHelpers.classCallCheck(this, Elon); } _rollupPluginBabelHelpers.createClass(Elon, null, [{ key: "inspect", value: // Static functions function inspect(validators) { // Create validation funciton return function (value, values) { for (var i = 0; i < validators.length; i++) { // get validator var validator = validators[i]; // call validator var res = validator(value, values); // If we have error return it ( exit early ) if (res) return res; } }; } }]); return Elon; }(); // Is Child var isChild = function isChild(parent, child) { // console.log( // 'PARENT', // parent, // 'CHILD', // child, // 'RES', // child.slice(0, parent.length) === parent // ); // Example1 // parent = "friends[1]" // child = "friends[1].foo" // child.startsWith(`${parent}.`) // "friends[1].foo".startsWith("friends[1]") // ==> true // Example2 // parent = "friends[1].foo.friends[1]" // child = "friends[1].foo" // child.startsWith(`${parent}.`) // "friends[1].foo".startsWith("friends[1].foo.friends[1]") // ==> false return child.startsWith("".concat(parent, ".")) || child.startsWith("".concat(parent, "[")); }; var generateOnChange = function generateOnChange(_ref) { var fieldType = _ref.fieldType, setValue = _ref.setValue, multiple = _ref.multiple, ref = _ref.ref; var setter = function setter(e) { return setValue(e); }; if (fieldType === 'text' || fieldType === 'textArea' || fieldType === 'number') { setter = function setter(e) { setValue(e.target.value, e); }; } if (fieldType === 'select') { setter = function setter(e) { var selected = Array.from(ref.current).filter(function (option) { return option.selected; }).map(function (option) { return option.value; }); setValue(multiple ? selected : selected[0] || '', e); }; } if (fieldType === 'checkbox') { setter = function setter(e) { setValue(e.target.checked, e); }; } return function (e) { setter(e); }; }; var generateOnBlur = function generateOnBlur(_ref2) { var setTouched = _ref2.setTouched; return function (e) { setTouched(true, e); }; }; var generateOnFocus = function generateOnFocus(_ref3) { var setFocused = _ref3.setFocused; return function (e) { setFocused(true, e); }; }; var generateValue = function generateValue(_ref4) { var fieldType = _ref4.fieldType, maskedValue = _ref4.maskedValue, multiple = _ref4.multiple, value = _ref4.value; switch (fieldType) { case 'text': case 'number': return !maskedValue && maskedValue !== 0 ? '' : maskedValue; case 'textArea': return !maskedValue ? '' : maskedValue; case 'select': return value || (multiple ? [] : ''); case 'checkbox': return !!value; default: return value; } }; // https://stackoverflow.com/questions/52367849/remove-empty-null-values-from-nested-object-es6-clean-nested-objects var sanitize = function sanitize(obj) { if (!obj) return obj; Object.keys(obj).forEach(function (key) { return obj[key] && _rollupPluginBabelHelpers["typeof"](obj[key]) === 'object' && sanitize(obj[key]) || obj[key] === undefined && delete obj[key]; }); return obj; }; /* -------------------------- Error Utils ----------------------------- */ var yupToFormErrors = function yupToFormErrors(yupError) { var errors = {}; if (yupError.inner) { if (yupError.inner.length === 0) { // console.log(yupError.path); ObjectMap.ObjectMap.set(errors, yupError.path, yupError.message); return; } var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(yupError.inner), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var err = _step.value; if (!ObjectMap.ObjectMap.get(errors, err.path)) { // console.log(errors, err.path, err.message); ObjectMap.ObjectMap.set(errors, err.path, err.message); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } return errors; }; var validateYupSchema = function validateYupSchema(schema, values) { try { schema.validateSync(values, { abortEarly: false }); } catch (e) { var formErrors = yupToFormErrors(e); return formErrors; } }; var yupToFormError = function yupToFormError(yupError) { if (yupError.inner) { if (yupError.inner.length === 0) { return; } var err = yupError.inner[0]; return err.message; } }; var validateYupField = function validateYupField(schema, value) { try { schema.validateSync(value, { abortEarly: false }); } catch (e) { return yupToFormError(e); } }; var validateAjvSchema = function validateAjvSchema(validate, data) { validate(data); var errors = {}; if (validate.errors) { validate.errors.forEach(function (_ref5) { var message = _ref5.message, dataPath = _ref5.dataPath, keyword = _ref5.keyword, params = _ref5.params; var path = dataPath; // Special case for required if (keyword === 'required') { path = "".concat(path, ".").concat(params.missingProperty); } // Get rid of leading dot path = path.replace('.', ''); // console.log('PATH', path, message); // TODO get message from informed if present ObjectMap.ObjectMap.set(errors, path, message); }); } return errors; }; var validateRequired = function validateRequired(value, required, getErrorMessage, noFalsy) { // Normal required validation if (required && (value == null || value === '' || Array.isArray(value) && value.length == 0)) { return typeof required === 'string' ? required : getErrorMessage('required') || 'This field is required'; } // No falsey validation if (noFalsy && !value) { return typeof noFalsy === 'string' ? noFalsy : getErrorMessage('noFalsy') || 'This field is required'; } }; var validateMax = function validateMax(value, max, getErrorMessage) { if (max != null && value > max) { return getErrorMessage('maximum') || "This field should NOT be more than ".concat(max); } return undefined; }; var validateMin = function validateMin(value, min, getErrorMessage) { if (min != null && value < min) { return getErrorMessage('minimum') || "This field should NOT be less than ".concat(min); } return undefined; }; var validateMaxLength = function validateMaxLength(value, maxLength, getErrorMessage) { if (maxLength != null && (value === null || value === void 0 ? void 0 : value.length) > maxLength) { return getErrorMessage('maxLength') || "This field should NOT be more than ".concat(maxLength, " characters"); } return undefined; }; var validateMinLength = function validateMinLength(value, minLength, getErrorMessage) { if (minLength != null && (value === null || value === void 0 ? void 0 : value.length) < minLength) { return getErrorMessage('minLength') || "This field should NOT be shorter than ".concat(minLength, " characters"); } return undefined; }; var validatePattern = function validatePattern(value, pattern, getErrorMessage) { if (pattern != null && !new RegExp(pattern).test(value) && value) { return getErrorMessage('pattern') || "This field should match pattern \"".concat(pattern, "\";"); } return undefined; }; var generateValidationFunction = function generateValidationFunction(validationFuncRef, yupSchema, _ref6) { var required = _ref6.required, noFalsy = _ref6.noFalsy, minimum = _ref6.minimum, maximum = _ref6.maximum, minLength = _ref6.minLength, maxLength = _ref6.maxLength, pattern = _ref6.pattern, getErrorMessage = _ref6.getErrorMessage, validateModified = _ref6.validateModified, fieldApi = _ref6.fieldApi, formController = _ref6.formController, scope = _ref6.scope, name = _ref6.name; return function (val, values) { var error; if (validateModified && fieldApi.getModified() === undefined) { return; } if (required || noFalsy) { error = validateRequired(val, required, getErrorMessage, noFalsy); if (error !== undefined) return error; } if (minimum != null) { error = validateMin(val, minimum, getErrorMessage); if (error !== undefined) return error; } if (maximum != null) { error = validateMax(val, maximum, getErrorMessage); if (error !== undefined) return error; } if (minLength != null) { error = validateMinLength(val, minLength, getErrorMessage); if (error !== undefined) return error; } if (maxLength != null) { error = validateMaxLength(val, maxLength, getErrorMessage); if (error !== undefined) return error; } if (pattern) { error = validatePattern(val, pattern, getErrorMessage); if (error !== undefined) return error; } if (yupSchema) { error = validateYupField(yupSchema, val); if (error !== undefined) return error; } if (validationFuncRef.current) { error = validationFuncRef.current(val, values, { formState: formController.getFormState(), formApi: formController.getFormApi(), scope: scope, name: name }); if (error !== undefined) return error; } return error; }; }; /** -------------------------------------------------------------------------------------------- * Helper function for getFormatter * @param {*} formatter * @returns */ var formatterFromString = function formatterFromString(formatter) { return formatter.split('').map(function (_char) { if (_char === '#') { return /\d/; } if (_char === '*') { return /[\w]/; } return _char; }); }; /* -------------------------- Formatter ----------------------------- */ var getFormatter = function getFormatter(formatter, value, full) { // If mask is a string turn it into an array; if (typeof formatter === 'string') { return formatterFromString(formatter); } // If mask is a function use it to genreate current mask if (typeof formatter === 'function') { var frmtr = formatter(value, full); if (typeof frmtr === 'string') { return formatterFromString(frmtr); } return frmtr; } if (Array.isArray(formatter)) { return formatter; } // Should never make it here throw throw new Error('Formatter must be string, array, or function'); }; var matchingIndex = function matchingIndex(a, b) { var i = 0; var mi = -1; var matching = true; // a = "+1 " // b = "+12" while (matching && i < a.length) { if (a[i] == b[i]) { mi = i; } else { matching = false; } i = i + 1; } return mi; }; var informedParse = function informedParse(val, parser) { // Our parser is an object! so we must parse for each key // Example: // // formatter: { // a: formatter, // b: formatter // } if (_rollupPluginBabelHelpers["typeof"](parser) === 'object' && !Array.isArray(parser)) { var parsedVal = {}; Object.keys(val).forEach(function (key) { // parser['foo'] = val['foo'] // Only try to parse if we have parser for this key!!! if (parser[key]) { var value = parser[key](val[key]); parsedVal[key] = value; } else { parsedVal[key] = val[key]; } }); return parsedVal; } // Simply pass along if its a flat formatter return parser(val); }; var informedFormat = function informedFormat(val, frmtr, old) { var dir = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'ltr'; // Our formatter is an object! so we must format for each key // Example: // // formatter: { // a: formatter, // b: formatter // } if (_rollupPluginBabelHelpers["typeof"](frmtr) === 'object' && !Array.isArray(frmtr)) { var formattedVal = {}; var formattedOffset = {}; Object.keys(val).forEach(function (key) { // Only try to format if we have formatter for this key!!! if (frmtr[key]) { // console.log('Old', old); var _informedFormatter = informedFormatter(val[key], frmtr[key], old ? old[val] : undefined, val, dir), value = _informedFormatter.value, offset = _informedFormatter.offset; formattedVal[key] = value; formattedOffset[key] = offset; } else { formattedVal[key] = val[key]; formattedOffset[key] = 0; } }); return { value: formattedVal, offset: formattedOffset }; } // Simply pass along if its a flat formatter return informedFormatter(val, frmtr, old, val, dir); }; var informedFormatter = function informedFormatter(val, frmtr, old, full, dir) { // console.log('Formatting', val); debug('Formatting', val); debug('Full Value', full); // Null check if (val == null) { return { value: val, offset: 0 }; } var value = "".concat(val); // Generate formatter array var formatter = getFormatter(frmtr, value, full); // Start to fill in the array // Example: phone formatter // formatter =['+', '1', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/] // value examples: // "1231231234 ----> +1 123-123-1234 // "+" ----> + // "+1" ----> +1 // "+2" ----> +1 2 // "1" ----> +1 1 // "1234" ----> +1 123-4 // "123a" ----> +1 123 // ADD LOGS FOR TETING --------------------------- // console.log('New', value); // console.log('Old', old); // console.log('Formatter', formatter); // Determine prefix length and suffix start var prefixLength = formatter.findIndex(function (v) { return typeof v != 'string'; }); // If we have a suffix var suffixStart = null; if (typeof formatter[formatter.length - 1] === 'string') { suffixStart = formatter.length - _rollupPluginBabelHelpers.toConsumableArray(formatter).reverse().findIndex(function (v) { return typeof v != 'string'; }); } // Formatted value var formatted = []; // The characters from the current value var chars = value.split(''); // To track the value index during itteration var vIndex = 0; var start = 0; // If the value matches part of the prefix take it out // Example prefix = "+1 " value = ["+1 123-123-1234", "+12", "+2"] var matchIndex = matchingIndex(formatter.slice(0, prefixLength), chars.slice(0, prefixLength)); // console.log('Matching index', matchIndex); if (matchIndex > -1) { //vIndex = prefixLength; vIndex = matchIndex + 1; formatted = formatted.concat(formatter.slice(0, matchIndex + 1)); start = matchIndex + 1; } // Example prefix = "+1 " value=["1", "1234"] if (matchIndex < 0) { // Start past the prefix formatted = formatted.concat(formatter.slice(0, prefixLength)); start = prefixLength; } // Fill in the stuff for (var i = start; i < formatter.length; i++) { // Get current formatter location matcher var matcher = formatter[i]; // Chec to see if there is more value to look at if (vIndex != chars.length) { // Get the current value character var curChar = chars[vIndex]; // Special case for function if (typeof matcher === 'function') { formatted.push(matcher(curChar)); vIndex = vIndex + 1; } else { // If type is string normal compare otherwise regex compare // console.log('MATCHER', matcher); var match = typeof matcher === 'string' ? matcher === curChar : matcher.test(curChar); // If the current character of the value matches and matcher is a string // "1" === "1" if (match && typeof matcher === 'string') { formatted.push(matcher); //if( pastPrefix ){ vIndex = vIndex + 1; //} } // If the current character does not match and matcher is a stirng // "1" != "+" else if (!match && typeof matcher === 'string') { // Special check for 123a ---> dont want "+1 123-" // Special check for 1234 ---> DO want "+1 123-4" if (vIndex != chars.length) formatted.push(matcher); } // If the current character matches and the matcher is not a string // /\d/.test("2") else if (match && typeof matcher != 'string') { formatted.push(curChar); vIndex = vIndex + 1; } // If the current character does NOT match and the matecer is regex // /\d/.test("a") else if (!match && typeof matcher != 'string') { // Throw out this value vIndex = vIndex + 1; i = i - 1; } } } else { // console.log('WTF i', i, 'suffixStart', suffixStart); // If mattcher is a string and we are at suffix keep going if (typeof matcher === 'string' && suffixStart && i >= suffixStart) { formatted.push(matcher); } else { // Otherwise we want to break out break; } } } // ADD LOGS FOR TETING --------------------------- // console.log('FORMATTEDARR', formatted); // console.log('VALUE', value, value.length); var formattedString = formatted.join(''); // console.log('FORMATTED', formattedString, formattedString.length); // For the following cases the "|" represents the cursor position // // Case1: // oldValue = "+1 12|" ( length 5 ) // value = "+1 123|" ( length 6) // formattedString = "+1 123-" ( length 7 ) // offset = 1 ( we need to move cursur over by 1 ) // // Case2: // oldValue = "1,234|.25" ( length 8 ) // value = "1,23|.25" ( length 7 ) // formattedString = "123.25" ( length 6 ) // offset = 1 ( we need to move cursur over by -1 because a format character got removed ) var offset = value ? formattedString.length - value.length : 0; // ADD LOGS FOR TETING --------------------------- // console.log('OFFSET', offset); // Special case1: // Suffix is '%' // user typed backspace // 20%| // 20|% // ^ // suffixStart (2) // // New: 20 // Old: 20% // // New length is less than old length // And length of new is greater than or equal two suffix start var case1 = suffixStart && value && old && value.length < old.length && value.length >= suffixStart && dir != 'rtl'; // Special case2: // Suffix is '%' // user types 20| // we want cursor to be here // 20|% // Note: we DONT want to do this if we also added a new character // Example: 7000| BND --- user types zero "0" --> 70 000| BND // to solve we can just check to see if the suffix was already there :) var suffix = formatter.slice(suffixStart).join(''); // console.log('SUFFIX', suffix); var case2 = suffixStart && formatted.length > suffixStart && (!old || typeof old === 'string' && !old.includes(suffix)); // && dir != 'rtl'; if (case1 || case2) { offset = 0; // console.log('OFFSET OVERRIDE', offset, case1 ? 'case1' : 'case2'); // Special case if right to left then we actually want to offset by one if (dir == 'rtl') offset = 1; // Special case, we want to diable keeping suffix on backspace in react native if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative' && value && old && value.length < old.length) { // I'm in react-native formattedString = formattedString.slice(0, suffixStart); } } // ADD LOGS FOR TETING --------------------------- // console.log('OFFSET', offset); return { value: formattedString, offset: offset }; }; /* --------------------------------------- createIntlNumberFormatter --------------------------------------- */ var createIntlNumberFormatter = function createIntlNumberFormatter(locale) { var _toParts$find$value, _toParts$find, _toParts$find2; var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _ref7 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, formatToParts = _ref7.formatToParts; var numberFormatter = new Intl.NumberFormat(locale, opts); // TODO at some point this was used to find the decimal char.. not sure why I stopped using it but kept in case i see future issue. // const numberFormatterWithoutOpts = new Intl.NumberFormat(locale, opts); var toParts = function toParts(v) { return numberFormatter.formatToParts(v); }; // If user passed in custom function use that instead if (formatToParts) { toParts = function toParts(v) { return formatToParts(v, locale, opts); }; } var decimalChar = (_toParts$find$value = (_toParts$find = toParts(0.1).find(function (_ref8) { var type = _ref8.type; return type === 'decimal'; })) === null || _toParts$find === void 0 ? void 0 : _toParts$find.value) !== null && _toParts$find$value !== void 0 ? _toParts$find$value : '.'; // console.log('-1 number parts', numberFormatter.formatToParts(-1)); // Try to find minus sign var minusChar = (_toParts$find2 = toParts(-1).find(function (_ref9) { var type = _ref9.type; return type === 'minusSign'; })) === null || _toParts$find2 === void 0 ? void 0 : _toParts$find2.value; // special case if we did not find it then look one more time but for a literal ( accounting will lead to this case where "(" is neg symbol ) if (!minusChar) { var _toParts$find$value2, _toParts$find3; minusChar = (_toParts$find$value2 = (_toParts$find3 = toParts(-1).find(function (_ref10) { var type = _ref10.type; return type === 'literal'; })) === null || _toParts$find3 === void 0 ? void 0 : _toParts$find3.value) !== null && _toParts$find$value2 !== void 0 ? _toParts$find$value2 : '-'; } // function isRegexEqual(x, y) { // return ( // x instanceof RegExp && // y instanceof RegExp && // x.source === y.source && // x.global === y.global && // x.ignoreCase === y.ignoreCase && // x.multiline === y.multiline // ); // } // function findLastIndex(arr, predicate) { // let l = arr.length; // // eslint-disable-next-line no-plusplus // while (l--) { // if (predicate(arr[l])) return l; // } // return -1; // } // function insert(arr, index, value) { // const nextArr = [...arr]; // if (Array.isArray(value)) { // nextArr.splice(index, 0, ...value); // } else { // nextArr.splice(index, 0, value); // } // return nextArr; // } function stripNonNumeric(str) { return "".concat(str).replace(/\D/g, ''); } function toNumberString(str) { var decimalChar = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.'; // Special case if user types the decimal char if (str === decimalChar) { return ''; } // If its a number we always use dot notation if (typeof str === 'number') { return "".concat(str).split('.').map(function (splitStr) { return stripNonNumeric(splitStr); }).join('.'); } // Create a regex to replace all but the first occurrence of the decimalChar. // let regex = new RegExp(`(.*?\\${decimalChar}.*?)\\${decimalChar}(.*)`, 'g'); return "".concat(str) // .replace(regex, '$1$2') .split(decimalChar).map(function (splitStr) { return stripNonNumeric(splitStr); }).join('.'); } function toFloat(str) { var decimalChar = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.'; if (typeof str === 'number') { return str; } var _float = parseFloat(toNumberString(str, decimalChar)); // console.log('ISNAN', Number.isNaN(float)); return !Number.isNaN(_float) ? _float : undefined; } function mask(value, ogValue) { // console.log('--------------\n'); // value = -3000.25 // console.log('decChar', decimalChar); // console.log('minusChar', minusChar); // console.log('VAL', value); var isNegative = "".concat(value).includes(minusChar) || "".concat(value).includes('-'); // In case the value is a number from initial value we want to pass the OG value ( not the one we turned into a string in informedFormatter ) var _float2 = toNumberString(ogValue, decimalChar); // float = 3000.25 // console.log('float', float); // Special case if only decimal Char var isDecimalChar = false; if (_float2 == '.') { isDecimalChar = true; } var fraction = "".concat(_float2).split('.')[1]; // fraction = 25 // console.log('fraction', fraction); var number = isNegative ? -Number(_float2) : Number(_float2); // console.log('number', number); var numberParts = toParts(number); // Special case, if number parts does not contain a "decimal" than we want to throw out the decimal from the value // const hasDecimal = numberParts.find(part => part.type === 'decimal'); // number-parts = // 0: {type: 'minusSign', value: '-'} // 1: {type: 'currency', value: '$'} // 2: {type: 'integer', value: '3'} // 3: {type: 'group', value: ','} // 4: {type: 'integer', value: '000'} // 5: {type: 'decimal', value: '.'} // 6: {type: 'fraction', value: '25'} // console.log('number-parts', numberParts); // const hasFraction = numberParts.find(p => p.type === 'fraction'); // In the case user types "1." or "1.0" we need to add the fraction part // This only occurs if we dont have minimumFractionDigits to force the fraction // if (fraction != null && !hasFraction) { // numberParts.push( // { type: 'decimal', value: decimalChar }, // { type: 'fraction', value: fraction } // ); // } // console.log('number-parts after fraction check', numberParts); var maskArray = numberParts.reduce(function (pv, _ref11) { var type = _ref11.type, partValue = _ref11.value; // PV [] minusSign - // PV ['-'] currency $ // PV ['-', '$'] integer 3 // PV ['-', '$', /\d/] group , // PV ['-', '$', /\d/, ','] integer 000 // PV ['-', '$', /\d/, ',', /\d/, /\d/, /\d/] decimal . // PV ['-', '$', /\d/, ',', /\d/, /\d/, /\d/, '.'] fraction 25 // console.log('PV', pv, type, partValue); if (['decimal', 'fraction'].includes(type) && fraction == null) { return pv; } // // Special case where we have no fraction but need to pad // if (['fraction'].includes(type) && fraction == null) { // return [...pv, ...partValue.split('')]; // } if (['integer', 'fraction'].includes(type)) { return [].concat(_rollupPluginBabelHelpers.toConsumableArray(pv), _rollupPluginBabelHelpers.toConsumableArray(partValue.split('').filter(function (_, index) { return type === 'fraction' ? index < fraction.length : true; }).map(function () { return /\d/; }))); } if (type === 'currency' || type === 'minusSign') { return [].concat(_rollupPluginBabelHelpers.toConsumableArray(pv), _rollupPluginBabelHelpers.toConsumableArray(partValue.split(''))); } return [].concat(_rollupPluginBabelHelpers.toConsumableArray(pv), [partValue]); }, []); // console.log('PV', maskArray); // let lastDigitIndex = findLastIndex(maskArray, maskChar => { // return isRegexEqual(maskChar, /\d/); // }); // console.log('lastDigitIndex', lastDigitIndex); // if ( // maskArray.indexOf(decimalChar) === -1 && // `${value}`.indexOf(decimalChar) !== -1 && // hasDecimal // ) { // maskArray = insert(maskArray, lastDigitIndex + 1, [decimalChar]); // lastDigitIndex += 2; // we want to insert a new number after the decimal // } // const endOfMask = maskArray.slice(lastDigitIndex + 1).join(''); // maskArray = [...maskArray.slice(0, lastDigitIndex + 1), endOfMask]; if (isDecimalChar) { maskArray = maskArray.map(function (item) { return item == 'NaN' ? "0".concat(decimalChar) : item; }); } // console.log('maskArray', maskArray); return maskArray; } var parser = function parser(value) { if (value == null) { return undefined; } var isNegative = "".concat(value).includes(minusChar); // console.log('TOPARSE', value); return isNegative ? -toFloat(value, decimalChar) : toFloat(value, decimalChar); }; return { formatter: mask, parser: parser }; }; /* --------------------------------------- Schema Shit --------------------------------------- */ // Examples // field = "name" ---> properties.name // field = "brother.name" ---> properties.brother.properties.name // field = "brother.siblings[1].friend.name" ---> properties.brother.properties.siblings.items.properties.friend.properties.name var getSchemaPathFromJsonPath = function getSchemaPathFromJsonPath(jsonPath) { // Convert var schemaPath = jsonPath.replace(/\./g, '.properties.').replace(/\[\d+\]/g, '.items'); // Add first properties schemaPath = "properties.".concat(schemaPath); return schemaPath; }; var computeFieldFromProperty = function computeFieldFromProperty(propertyName, property, prefix) { var uiControl = property['ui:control'], inputProps = property['ui:props'], uiBefore = property['ui:before'], uiAfter = property['ui:after'], oneOf = property.oneOf, items = property.items, schemaEnum = property["enum"], label = property.title, minimum = property.minimum, maximum = property.maximum, minLength = property.minLength, maxLength = property.maxLength, pattern = property.pattern, required = property.required, type = property.type, subProperties = property.properties, allOf = property.allOf, propertyOrder = property.propertyOrder, errorMessage = property.errorMessage; // Set Id if not passed var id = uuidv4(); if (inputProps && inputProps.id) { id = inputProps.id; } var field = { // componentType: uiControl ?? (oneOf && 'select') ?? type, componentType: uiControl !== null && uiControl !== void 0 ? uiControl : type, name: prefix ? "".concat(prefix, ".").concat(propertyName) : propertyName, type: type, uiBefore: uiBefore, uiAfter: uiAfter, properties: type === 'object' ? subProperties : undefined, allOf: type === 'object' ? allOf : undefined, propertyOrder: type === 'object' ? propertyOrder : undefined, items: type === 'array' ? items : undefined, propertyName: propertyName, required: required, props: _rollupPluginBabelHelpers.objectSpread2({ label: label, id: id, minimum: minimum, maximum: maximum, minLength: minLength, maxLength: maxLength, pattern: pattern, errorMessage: errorMessage, required: required }, inputProps) }; // console.log('NAME', propertyName, inputProps); if (oneOf) { var options = property.oneOf.map(function (option) { var _option$uiProps = option['ui:props'], inputProps = _option$uiProps === void 0 ? {} : _option$uiProps; return _rollupPluginBabelHelpers.objectSpread2({ value: option["const"], label: option.title }, inputProps); }); field.props.options = options; } if (schemaEnum) { var _options = property["enum"].map(function (val) { return { value: val, label: val }; }); field.props.options = _options; } if (items && items.oneOf) { var _options2 = items.oneOf.map(function (option) { var _option$uiProps2 = option['ui:props'], inputProps = _option$uiProps2 === void 0 ? {} : _option$uiProps2; return _rollupPluginBabelHelpers.objectSpread2({ value: option["const"], label: option.title }, inputProps); }); field.props.options = _options2; } return field; }; var computeFieldsFromSchema = function computeFieldsFromSchema(schema, onlyValidateSchema) { if (!schema || onlyValidateSchema) { return { properties: [], conditions: [], components: [] }; } // Grab properties and items off of schema var _schema$properties = schema.properties, properties = _schema$properties === void 0 ? {} : _schema$properties, allOf = schema.allOf, _schema$propertyOrder = schema.propertyOrder, propertyOrder = _schema$propertyOrder === void 0 ? [] : _schema$propertyOrder; if (Object.keys(properties).length > 0) { // Attempt to generate fields from properties var fields = Object.keys(properties).sort(function (a, b) { var aIndex = propertyOrder.indexOf(a); var bIndex = propertyOrder.indexOf(b); return (aIndex > -1 ? aIndex : propertyOrder.length + 1) - (bIndex > -1 ? bIndex : propertyOrder.length + 1); }).map(function (propertyName) { return propertyName; }); var conditions = []; var components = []; // Check for all of ( we have conditionals ) if (allOf) { allOf.forEach(function (item) { if (item["if"]) { // Determine if the "then" properties are new or already in fields var newItem = _rollupPluginBabelHelpers.objectSpread2({}, item); newItem.then = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, item.then), {}, { properties: {} }); newItem.thenProps = {}; Object.keys(item.then.properties).forEach(function (name) { if (!fields.includes(name)) { // This is a completley new field! newItem.then.properties[name] = item.then.properties[name]; } else { // This field has been spotted above, and therefore is just new properties based on conditional newItem.thenProps[name] = item.then.properties[name]; } }); conditions.push(newItem); } else { components.push(item); } }); } return { properties: fields, conditions: conditions, components: components }; } return { properties: [], conditions: [], components: [] }; }; function checkCondition(condition, propertyValue) { // if (!isPlainObject(condition)) { // return false; // } return Object.entries(condition).every(function (_ref12) { var _ref13 = _rollupPluginBabelHelpers.slicedToArray(_ref12, 2), keyword = _ref13[0], value = _ref13[1]; // console.log('KEYWORD', keyword, value, propertyValue); switch (keyword) { case 'const': if (Array.isArray(propertyValue) && value) { return propertyValue.sort().toString() == value.sort().toString(); } else { return propertyValue === value; } case 'minimum': return propertyValue >= value; case 'exclusiveMinimum': return propertyValue > value; case 'maximum': return propertyValue <= value; case 'exclusiveMaximum': return propertyValue < value; case 'enum': if (Array.isArray(value) && !Array.isArray(propertyValue)) { return value.includes(propertyValue); } if (Array.isArray(value) && Array.isArray(propertyValue)) { return propertyValue.every(function (a) { return value.includes(a); }); } return false; case 'oneOf': if (Array.isArray(value) && !Array.isArray(propertyValue)) { return value.includes(propertyValue); } if (Array.isArray(value) && Array.isArray(propertyValue)) { return value.find(function (a) { return propertyValue.includes(a); }); } return false; case 'pattern': return new RegExp(value).test(propertyValue); // case 'properties': // // eslint-disable-next-line no-use-before-define // return checkProperties(value, values, propertyPath); case 'not': if (_rollupPluginBabelHelpers["typeof"](value) === 'object' && value["enum"]) { if (Array.isArray(value["enum"]) && !Array.isArray(propertyValue)) { return !value["enum"].includes(propertyValue); } if (Array.isArray(value["enum"]) && Array.isArray(propertyValue)) { return !propertyValue.every(function (a) { return value["enum"].includes(a); }); } } return propertyValue !== value; default: // not supported keywords return false return false; } }); } exports.unwrap = proxy.unwrap; exports.Elon = Elon; exports.checkCondition = checkCondition; exports.computeFieldFromProperty = computeFieldFromProperty; exports.computeFieldsFromSchema = computeFieldsFromSchema; exports.createIntlNumberFormatter = createIntlNumberFormatter; exports.debounce = debounce; exports.debounceByName = debounceByName; exports.generateOnBlur = generateOnBlur; exports.generateOnChange = generateOnChange; exports.generateOnFocus = generateOnFocus; exports.generateValidationFunction = generateValidationFunction; exports.generateValue = generateValue; exports.getParentPath = getParentPath; exports.getSchemaPathFromJsonPath = getSchemaPathFromJsonPath; exports.informedFormat = informedFormat; exports.informedFormatter = informedFormatter; exports.informedParse = informedParse; exports.isChild = isChild; exports.sanitize = sanitize; exports.uuidv4 = uuidv4; exports.validateAjvSchema = validateAjvSchema; exports.validateMax = validateMax; exports.validateMaxLength = validateMaxLength; exports.validateMin = validateMin; exports.validateMinLength = validateMinLength; exports.validateRequired = validateRequired; exports.validateYupField = validateYupField; exports.validateYupSchema = validateYupSchema; exports.yupToFormError = yupToFormError; exports.yupToFormErrors = yupToFormErrors;