@formio/js 5.0.0-dev.5646.8734cf4 → 5.0.0-dev.5650.f58394c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/formio.form.js +23 -22
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.full.js +23 -22
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.js +1 -1
- package/dist/formio.min.js +1 -1
- package/dist/formio.utils.js +3 -3
- package/dist/formio.utils.min.js +1 -1
- package/lib/cjs/Webform.js +8 -1
- package/lib/cjs/components/datagrid/fixtures/index.d.ts +1 -2
- package/lib/cjs/components/datagrid/fixtures/index.js +1 -3
- package/lib/cjs/utils/conditionOperators/IsEmptyValue.js +3 -4
- package/lib/cjs/utils/conditionOperators/IsEqualTo.js +3 -3
- package/lib/cjs/utils/utils.d.ts +10 -0
- package/lib/cjs/utils/utils.js +7 -59
- package/lib/mjs/Webform.js +7 -1
- package/lib/mjs/components/datagrid/fixtures/index.d.ts +1 -2
- package/lib/mjs/components/datagrid/fixtures/index.js +1 -2
- package/lib/mjs/utils/conditionOperators/IsEmptyValue.js +3 -3
- package/lib/mjs/utils/conditionOperators/IsEqualTo.js +1 -1
- package/lib/mjs/utils/utils.d.ts +10 -0
- package/lib/mjs/utils/utils.js +7 -58
- package/package.json +2 -2
- package/lib/cjs/components/datagrid/fixtures/comp9.d.ts +0 -81
- package/lib/cjs/components/datagrid/fixtures/comp9.js +0 -87
- package/lib/mjs/components/datagrid/fixtures/comp9.d.ts +0 -81
- package/lib/mjs/components/datagrid/fixtures/comp9.js +0 -85
package/dist/formio.form.js
CHANGED
|
@@ -354,7 +354,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
|
|
|
354
354
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
355
355
|
|
|
356
356
|
"use strict";
|
|
357
|
-
eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n__exportStar(__webpack_require__(/*! ./modules */ \"./node_modules/@formio/core/lib/modules/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./utils */ \"./node_modules/@formio/core/lib/utils/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./process/validation */ \"./node_modules/@formio/core/lib/process/validation/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./process
|
|
357
|
+
eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n__exportStar(__webpack_require__(/*! ./modules */ \"./node_modules/@formio/core/lib/modules/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./utils */ \"./node_modules/@formio/core/lib/utils/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./process/validation */ \"./node_modules/@formio/core/lib/process/validation/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./process */ \"./node_modules/@formio/core/lib/process/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./sdk */ \"./node_modules/@formio/core/lib/sdk/index.js\"), exports);\n__exportStar(__webpack_require__(/*! ./types */ \"./node_modules/@formio/core/lib/types/index.js\"), exports);\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/index.js?");
|
|
358
358
|
|
|
359
359
|
/***/ }),
|
|
360
360
|
|
|
@@ -552,7 +552,7 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
|
|
|
552
552
|
/***/ (function(__unused_webpack_module, exports) {
|
|
553
553
|
|
|
554
554
|
"use strict";
|
|
555
|
-
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.EN_ERRORS = void 0;\nexports.EN_ERRORS = {\n unsavedRowsError: 'Please save all rows before proceeding.',\n invalidRowsError: 'Please correct invalid rows before proceeding.',\n invalidRowError: 'Invalid row. Please correct it or delete.',\n invalidOption: '{{field}} is an invalid value.',\n invalidDay: '{{field}} is not a valid day.',\n required: '{{field}} is required',\n unique: '{{field}} must be unique',\n array: '{{field}} must be an array',\n array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase\n nonarray: '{{field}} must not be an array',\n select: '{{field}} contains an invalid selection',\n pattern: '{{field}} does not match the pattern {{pattern}}',\n minLength: '{{field}} must have at least {{length}} characters.',\n maxLength: '{{field}} must have no more than {{length}} characters.',\n minWords: '{{field}} must have at least {{length}} words.',\n maxWords: '{{field}} must have no more than {{length}} words.',\n min: '{{field}} cannot be less than {{min}}.',\n max: '{{field}} cannot be greater than {{max}}.',\n maxDate: '{{field}} should not contain date after {{- maxDate}}',\n minDate: '{{field}} should not contain date before {{- minDate}}',\n maxYear: '{{field}} should not contain year greater than {{maxYear}}',\n minSelectedCount: 'You must select at least {{minCount}} items',\n maxSelectedCount: 'You may only select up to {{maxCount}} items',\n minYear: '{{field}} should not contain year less than {{minYear}}',\n invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase\n invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase\n invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase\n invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase\n invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase\n invalidValueProperty: 'Invalid Value Property',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n time: '{{field}} is not a valid time.',\n invalidDate: '{{field}} is not a valid date',\n number: '{{field}} is not a valid number.'\n};\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/i18n/en.js?");
|
|
555
|
+
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.EN_ERRORS = void 0;\nexports.EN_ERRORS = {\n unsavedRowsError: 'Please save all rows before proceeding.',\n invalidRowsError: 'Please correct invalid rows before proceeding.',\n invalidRowError: 'Invalid row. Please correct it or delete.',\n invalidOption: '{{field}} is an invalid value.',\n invalidDay: '{{field}} is not a valid day.',\n required: '{{field}} is required',\n unique: '{{field}} must be unique',\n array: '{{field}} must be an array',\n array_nonempty: '{{field}} must be a non-empty array', // eslint-disable-line camelcase\n nonarray: '{{field}} must not be an array',\n select: '{{field}} contains an invalid selection',\n pattern: '{{field}} does not match the pattern {{pattern}}',\n minLength: '{{field}} must have at least {{length}} characters.',\n maxLength: '{{field}} must have no more than {{length}} characters.',\n minWords: '{{field}} must have at least {{length}} words.',\n maxWords: '{{field}} must have no more than {{length}} words.',\n min: '{{field}} cannot be less than {{min}}.',\n max: '{{field}} cannot be greater than {{max}}.',\n maxDate: '{{field}} should not contain date after {{- maxDate}}',\n minDate: '{{field}} should not contain date before {{- minDate}}',\n maxYear: '{{field}} should not contain year greater than {{maxYear}}',\n minSelectedCount: 'You must select at least {{minCount}} items',\n maxSelectedCount: 'You may only select up to {{maxCount}} items',\n minYear: '{{field}} should not contain year less than {{minYear}}',\n invalid_email: '{{field}} must be a valid email.', // eslint-disable-line camelcase\n invalid_url: '{{field}} must be a valid url.', // eslint-disable-line camelcase\n invalid_regex: '{{field}} does not match the pattern {{regex}}.', // eslint-disable-line camelcase\n invalid_date: '{{field}} is not a valid date.', // eslint-disable-line camelcase\n invalid_day: '{{field}} is not a valid day.', // eslint-disable-line camelcase\n invalidValueProperty: 'Invalid Value Property',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n captchaTokenValidation: 'ReCAPTCHA: Token validation error',\n captchaTokenNotSpecified: 'ReCAPTCHA: Token is not specified in submission',\n captchaFailure: 'ReCaptcha: Response token not found',\n time: '{{field}} is not a valid time.',\n invalidDate: '{{field}} is not a valid date',\n number: '{{field}} is not a valid number.'\n};\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/i18n/en.js?");
|
|
556
556
|
|
|
557
557
|
/***/ }),
|
|
558
558
|
|
|
@@ -574,7 +574,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
|
|
|
574
574
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
575
575
|
|
|
576
576
|
"use strict";
|
|
577
|
-
eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.validateProcessInfo = exports.validateServerProcessInfo = exports.validateCustomProcessInfo = exports.validateAllProcessSync = exports.validateAllProcess = exports.validateServerProcessSync = exports.validateServerProcess = exports.validateCustomProcessSync = exports.validateCustomProcess = exports.validateProcessSync = exports.validateProcess = exports.shouldValidateServer = exports.shouldValidateCustom = exports.shouldValidateAll = exports.shouldSkipValidation = exports.shouldSkipValidationSimple = exports.shouldSkipValidationCustom = exports._shouldSkipValidation = exports.isForcedHidden = exports.isValueHidden = exports.isInputComponent = exports.validationRules = void 0;\nconst rules_1 = __webpack_require__(/*! ./rules */ \"./node_modules/@formio/core/lib/process/validation/rules/index.js\");\nconst find_1 = __importDefault(__webpack_require__(/*! lodash/find */ \"./node_modules/lodash/find.js\"));\nconst get_1 = __importDefault(__webpack_require__(/*! lodash/get */ \"./node_modules/lodash/get.js\"));\nconst pick_1 = __importDefault(__webpack_require__(/*! lodash/pick */ \"./node_modules/lodash/pick.js\"));\nconst formUtil_1 = __webpack_require__(/*! ../../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst error_1 = __webpack_require__(/*! ../../utils/error */ \"./node_modules/@formio/core/lib/utils/error.js\");\nconst conditions_1 = __webpack_require__(/*! ../conditions */ \"./node_modules/@formio/core/lib/process/conditions/index.js\");\n// Cleans up validation errors to remove unnessesary parts\n// and make them transferable to ivm.\nconst cleanupValidationError = (error) => (Object.assign(Object.assign({}, error), { context: (0, pick_1.default)(error.context, [\n 'component',\n 'path',\n 'index',\n 'value',\n 'field',\n 'hasLabel',\n 'processor',\n 'setting',\n 'pattern',\n 'length',\n 'min',\n 'max',\n 'maxDate',\n 'minDate',\n 'maxYear',\n 'minYear',\n 'minCount',\n 'maxCount',\n 'regex'\n ]) }));\nfunction validationRules(context, rules, skipValidation) {\n if (skipValidation && skipValidation(context)) {\n return [];\n }\n const validationRules = [];\n return rules.reduce((acc, rule) => {\n var _a;\n if (context.component.multiple &&\n Array.isArray(context.value) &&\n ((_a = context.value) === null || _a === void 0 ? void 0 : _a.length) === 0 &&\n !rule.fullValue) {\n return acc;\n }\n if (rule.shouldProcess && rule.shouldProcess(context)) {\n acc.push(rule);\n }\n return acc;\n }, validationRules);\n}\nexports.validationRules = validationRules;\nfunction isInputComponent(context) {\n const { component } = context;\n return !component.hasOwnProperty('input') || component.input;\n}\nexports.isInputComponent = isInputComponent;\nfunction isValueHidden(context) {\n const { component, config } = context;\n if (component.protected) {\n return false;\n }\n if ((component.hasOwnProperty('persistent') && !component.persistent) ||\n (component.persistent === 'client-only')) {\n return true;\n }\n return false;\n}\nexports.isValueHidden = isValueHidden;\nfunction isForcedHidden(context, isConditionallyHidden) {\n const { component } = context;\n if (isConditionallyHidden(context)) {\n return true;\n }\n if (component.hasOwnProperty('hidden')) {\n return !!component.hidden;\n }\n return false;\n}\nexports.isForcedHidden = isForcedHidden;\nconst _shouldSkipValidation = (context, isConditionallyHidden) => {\n const { component, scope, path } = context;\n if ((scope === null || scope === void 0 ? void 0 : scope.conditionals) &&\n (0, find_1.default)(scope.conditionals, {\n path: (0, formUtil_1.getComponentPath)(component, path),\n conditionallyHidden: true\n })) {\n return true;\n }\n const { validateWhenHidden = false } = component || {};\n const rules = [\n // Skip validation if component is readOnly\n // () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !isInputComponent(context),\n // Check to see if we are editing and if so, check component persistence.\n () => isValueHidden(context),\n // Force valid if component is hidden.\n () => isForcedHidden(context, isConditionallyHidden) && !validateWhenHidden,\n ];\n return rules.some(pred => pred());\n};\nexports._shouldSkipValidation = _shouldSkipValidation;\nconst shouldSkipValidationCustom = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isCustomConditionallyHidden);\n};\nexports.shouldSkipValidationCustom = shouldSkipValidationCustom;\nconst shouldSkipValidationSimple = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isSimpleConditionallyHidden);\n};\nexports.shouldSkipValidationSimple = shouldSkipValidationSimple;\nconst shouldSkipValidation = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isConditionallyHidden);\n};\nexports.shouldSkipValidation = shouldSkipValidation;\nfunction shouldValidateAll(context) {\n return validationRules(context, rules_1.rules, exports.shouldSkipValidation).length > 0;\n}\nexports.shouldValidateAll = shouldValidateAll;\nfunction shouldValidateCustom(context) {\n const { component } = context;\n if (component.customConditional) {\n return true;\n }\n return !(0, exports.shouldSkipValidationCustom)(context);\n}\nexports.shouldValidateCustom = shouldValidateCustom;\nfunction shouldValidateServer(context) {\n const { component } = context;\n if (component.customConditional) {\n return false;\n }\n if ((0, exports.shouldSkipValidationSimple)(context)) {\n return false;\n }\n return shouldValidateAll(context);\n}\nexports.shouldValidateServer = shouldValidateServer;\nfunction handleError(error, context) {\n const { scope, component } = context;\n const absolutePath = (0, formUtil_1.getComponentAbsolutePath)(component);\n if (error) {\n const cleanedError = cleanupValidationError(error);\n cleanedError.context.path = absolutePath;\n if (!(0, find_1.default)(scope.errors, { errorKeyOrMessage: cleanedError.errorKeyOrMessage, context: {\n path: absolutePath\n } })) {\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n scope.errors.push(cleanedError);\n scope.validated.push({ path: absolutePath, error: cleanedError });\n }\n }\n}\nconst validateProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n const { component, data, row, path, instance, scope, rules, skipValidation } = context;\n let { value } = context;\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n if (!rules || !rules.length) {\n return;\n }\n if (component.multiple && Array.isArray(value) && value.length > 0) {\n const fullValueRules = rules.filter(rule => rule.fullValue);\n const otherRules = rules.filter(rule => !rule.fullValue);\n for (let i = 0; i < value.length; i++) {\n const amendedPath = `${path}[${i}]`;\n let amendedValue = (0, get_1.default)(data, amendedPath);\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data)) {\n return;\n }\n const rulesToExecute = validationRules(context, otherRules, skipValidation);\n if (!rulesToExecute.length) {\n continue;\n }\n if (component.truncateMultipleSpaces && amendedValue && typeof amendedValue === 'string') {\n amendedValue = amendedValue.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value: amendedValue, index: i, path: amendedPath })), context);\n }\n }\n }\n for (const rule of fullValueRules) {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n return;\n }\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data, row)) {\n return;\n }\n const rulesToExecute = validationRules(context, rules, skipValidation);\n if (!rulesToExecute.length) {\n return;\n }\n if (component.truncateMultipleSpaces && value && typeof value === 'string') {\n value = value.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n try {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n catch (err) {\n console.error(\"Validator error:\", (0, error_1.getErrorMessage)(err));\n }\n }\n return;\n});\nexports.validateProcess = validateProcess;\nconst validateProcessSync = (context) => {\n const { component, data, row, path, instance, scope, rules, skipValidation } = context;\n let { value } = context;\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n if (!rules || !rules.length) {\n return;\n }\n if (component.multiple && Array.isArray(value) && value.length > 0) {\n const fullValueRules = rules.filter(rule => rule.fullValue);\n const otherRules = rules.filter(rule => !rule.fullValue);\n for (let i = 0; i < value.length; i++) {\n const amendedPath = `${path}[${i}]`;\n let amendedValue = (0, get_1.default)(data, amendedPath);\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data)) {\n return;\n }\n const rulesToExecute = validationRules(context, otherRules, skipValidation);\n if (!rulesToExecute.length) {\n continue;\n }\n if (component.truncateMultipleSpaces && amendedValue && typeof amendedValue === 'string') {\n amendedValue = amendedValue.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value: amendedValue, index: i, path: amendedPath })), context);\n }\n }\n }\n for (const rule of fullValueRules) {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n return;\n }\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data, row)) {\n return;\n }\n const rulesToExecute = validationRules(context, rules, skipValidation);\n if (!rulesToExecute.length) {\n return;\n }\n if (component.truncateMultipleSpaces && value && typeof value === 'string') {\n value = value.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n try {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n catch (err) {\n console.error(\"Validator error:\", (0, error_1.getErrorMessage)(err));\n }\n }\n return;\n};\nexports.validateProcessSync = validateProcessSync;\nconst validateCustomProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.evaluationRules;\n context.skipValidation = exports.shouldSkipValidationCustom;\n return (0, exports.validateProcess)(context);\n});\nexports.validateCustomProcess = validateCustomProcess;\nconst validateCustomProcessSync = (context) => {\n context.rules = context.rules || rules_1.evaluationRules;\n context.skipValidation = exports.shouldSkipValidationCustom;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateCustomProcessSync = validateCustomProcessSync;\nconst validateServerProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.serverRules;\n context.skipValidation = exports.shouldSkipValidationSimple;\n return (0, exports.validateProcess)(context);\n});\nexports.validateServerProcess = validateServerProcess;\nconst validateServerProcessSync = (context) => {\n context.rules = context.rules || rules_1.serverRules;\n context.skipValidation = exports.shouldSkipValidationSimple;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateServerProcessSync = validateServerProcessSync;\nconst validateAllProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.rules;\n context.skipValidation = exports.shouldSkipValidation;\n return (0, exports.validateProcess)(context);\n});\nexports.validateAllProcess = validateAllProcess;\nconst validateAllProcessSync = (context) => {\n context.rules = context.rules || rules_1.rules;\n context.skipValidation = exports.shouldSkipValidation;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateAllProcessSync = validateAllProcessSync;\nexports.validateCustomProcessInfo = {\n name: 'validateCustom',\n process: exports.validateCustomProcess,\n processSync: exports.validateCustomProcessSync,\n shouldProcess: shouldValidateCustom,\n};\nexports.validateServerProcessInfo = {\n name: 'validateServer',\n process: exports.validateServerProcess,\n processSync: exports.validateServerProcessSync,\n shouldProcess: shouldValidateServer,\n};\nexports.validateProcessInfo = {\n name: 'validate',\n process: exports.validateAllProcess,\n processSync: exports.validateAllProcessSync,\n shouldProcess: shouldValidateAll,\n};\n__exportStar(__webpack_require__(/*! ./util */ \"./node_modules/@formio/core/lib/process/validation/util.js\"), exports);\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/index.js?");
|
|
577
|
+
eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.validateProcessInfo = exports.validateServerProcessInfo = exports.validateCustomProcessInfo = exports.validateAllProcessSync = exports.validateAllProcess = exports.validateServerProcessSync = exports.validateServerProcess = exports.validateCustomProcessSync = exports.validateCustomProcess = exports.validateProcessSync = exports.validateProcess = exports.shouldValidateServer = exports.shouldValidateCustom = exports.shouldValidateAll = exports.shouldSkipValidation = exports.shouldSkipValidationSimple = exports.shouldSkipValidationCustom = exports._shouldSkipValidation = exports.isForcedHidden = exports.isValueHidden = exports.isInputComponent = exports.validationRules = void 0;\nconst rules_1 = __webpack_require__(/*! ./rules */ \"./node_modules/@formio/core/lib/process/validation/rules/index.js\");\nconst find_1 = __importDefault(__webpack_require__(/*! lodash/find */ \"./node_modules/lodash/find.js\"));\nconst get_1 = __importDefault(__webpack_require__(/*! lodash/get */ \"./node_modules/lodash/get.js\"));\nconst set_1 = __importDefault(__webpack_require__(/*! lodash/set */ \"./node_modules/lodash/set.js\"));\nconst pick_1 = __importDefault(__webpack_require__(/*! lodash/pick */ \"./node_modules/lodash/pick.js\"));\nconst formUtil_1 = __webpack_require__(/*! ../../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst error_1 = __webpack_require__(/*! ../../utils/error */ \"./node_modules/@formio/core/lib/utils/error.js\");\nconst conditions_1 = __webpack_require__(/*! ../conditions */ \"./node_modules/@formio/core/lib/process/conditions/index.js\");\n// Cleans up validation errors to remove unnessesary parts\n// and make them transferable to ivm.\nconst cleanupValidationError = (error) => (Object.assign(Object.assign({}, error), { context: (0, pick_1.default)(error.context, [\n 'component',\n 'path',\n 'index',\n 'value',\n 'field',\n 'hasLabel',\n 'processor',\n 'setting',\n 'pattern',\n 'length',\n 'min',\n 'max',\n 'maxDate',\n 'minDate',\n 'maxYear',\n 'minYear',\n 'minCount',\n 'maxCount',\n 'regex'\n ]) }));\nfunction validationRules(context, rules, skipValidation) {\n if (skipValidation && skipValidation(context)) {\n return [];\n }\n const validationRules = [];\n return rules.reduce((acc, rule) => {\n var _a;\n if (context.component.multiple &&\n Array.isArray(context.value) &&\n ((_a = context.value) === null || _a === void 0 ? void 0 : _a.length) === 0 &&\n !rule.fullValue) {\n return acc;\n }\n if (rule.shouldProcess && rule.shouldProcess(context)) {\n acc.push(rule);\n }\n return acc;\n }, validationRules);\n}\nexports.validationRules = validationRules;\nfunction isInputComponent(context) {\n const { component } = context;\n return !component.hasOwnProperty('input') || component.input;\n}\nexports.isInputComponent = isInputComponent;\nfunction isValueHidden(context) {\n const { component, config } = context;\n if (component.protected) {\n return false;\n }\n if ((component.hasOwnProperty('persistent') && !component.persistent) ||\n (component.persistent === 'client-only')) {\n return true;\n }\n return false;\n}\nexports.isValueHidden = isValueHidden;\nfunction isForcedHidden(context, isConditionallyHidden) {\n const { component } = context;\n if (isConditionallyHidden(context)) {\n return true;\n }\n if (component.hasOwnProperty('hidden')) {\n return !!component.hidden;\n }\n return false;\n}\nexports.isForcedHidden = isForcedHidden;\nconst _shouldSkipValidation = (context, isConditionallyHidden) => {\n const { component, scope, path } = context;\n if ((scope === null || scope === void 0 ? void 0 : scope.conditionals) &&\n (0, find_1.default)(scope.conditionals, {\n path: (0, formUtil_1.getComponentPath)(component, path),\n conditionallyHidden: true\n })) {\n return true;\n }\n const { validateWhenHidden = false } = component || {};\n const rules = [\n // Skip validation if component is readOnly\n // () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !isInputComponent(context),\n // Check to see if we are editing and if so, check component persistence.\n () => isValueHidden(context),\n // Force valid if component is hidden.\n () => isForcedHidden(context, isConditionallyHidden) && !validateWhenHidden,\n ];\n return rules.some(pred => pred());\n};\nexports._shouldSkipValidation = _shouldSkipValidation;\nconst shouldSkipValidationCustom = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isCustomConditionallyHidden);\n};\nexports.shouldSkipValidationCustom = shouldSkipValidationCustom;\nconst shouldSkipValidationSimple = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isSimpleConditionallyHidden);\n};\nexports.shouldSkipValidationSimple = shouldSkipValidationSimple;\nconst shouldSkipValidation = (context) => {\n return (0, exports._shouldSkipValidation)(context, conditions_1.isConditionallyHidden);\n};\nexports.shouldSkipValidation = shouldSkipValidation;\nfunction shouldValidateAll(context) {\n return validationRules(context, rules_1.rules, exports.shouldSkipValidation).length > 0;\n}\nexports.shouldValidateAll = shouldValidateAll;\nfunction shouldValidateCustom(context) {\n const { component } = context;\n if (component.customConditional) {\n return true;\n }\n return !(0, exports.shouldSkipValidationCustom)(context);\n}\nexports.shouldValidateCustom = shouldValidateCustom;\nfunction shouldValidateServer(context) {\n const { component } = context;\n if (component.customConditional) {\n return false;\n }\n if ((0, exports.shouldSkipValidationSimple)(context)) {\n return false;\n }\n return shouldValidateAll(context);\n}\nexports.shouldValidateServer = shouldValidateServer;\nfunction handleError(error, context) {\n const { scope, component } = context;\n const absolutePath = (0, formUtil_1.getComponentAbsolutePath)(component);\n if (error) {\n const cleanedError = cleanupValidationError(error);\n cleanedError.context.path = absolutePath;\n if (!(0, find_1.default)(scope.errors, { errorKeyOrMessage: cleanedError.errorKeyOrMessage, context: {\n path: absolutePath\n } })) {\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n scope.errors.push(cleanedError);\n scope.validated.push({ path: absolutePath, error: cleanedError });\n }\n }\n}\nconst validateProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n const { component, data, row, path, instance, scope, rules, skipValidation, value } = context;\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n if (!rules || !rules.length) {\n return;\n }\n if (component.multiple && Array.isArray(value) && value.length > 0) {\n const fullValueRules = rules.filter(rule => rule.fullValue);\n const otherRules = rules.filter(rule => !rule.fullValue);\n for (let i = 0; i < value.length; i++) {\n const amendedPath = `${path}[${i}]`;\n let amendedValue = (0, get_1.default)(data, amendedPath);\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data)) {\n return;\n }\n const rulesToExecute = validationRules(context, otherRules, skipValidation);\n if (!rulesToExecute.length) {\n continue;\n }\n if (component.truncateMultipleSpaces && amendedValue && typeof amendedValue === 'string') {\n amendedValue = amendedValue.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value: amendedValue, index: i, path: amendedPath })), context);\n }\n }\n }\n for (const rule of fullValueRules) {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n return;\n }\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data, row)) {\n return;\n }\n const rulesToExecute = validationRules(context, rules, skipValidation);\n if (!rulesToExecute.length) {\n return;\n }\n if (component.truncateMultipleSpaces && value && typeof value === 'string') {\n (0, set_1.default)(data, path, value.trim().replace(/\\s{2,}/g, ' '));\n }\n for (const rule of rulesToExecute) {\n try {\n if (rule && rule.process) {\n handleError(yield rule.process(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n catch (err) {\n console.error(\"Validator error:\", (0, error_1.getErrorMessage)(err));\n }\n }\n return;\n});\nexports.validateProcess = validateProcess;\nconst validateProcessSync = (context) => {\n const { component, data, row, path, instance, scope, rules, skipValidation } = context;\n let { value } = context;\n if (!scope.validated)\n scope.validated = [];\n if (!scope.errors)\n scope.errors = [];\n if (!rules || !rules.length) {\n return;\n }\n if (component.multiple && Array.isArray(value) && value.length > 0) {\n const fullValueRules = rules.filter(rule => rule.fullValue);\n const otherRules = rules.filter(rule => !rule.fullValue);\n for (let i = 0; i < value.length; i++) {\n const amendedPath = `${path}[${i}]`;\n let amendedValue = (0, get_1.default)(data, amendedPath);\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data)) {\n return;\n }\n const rulesToExecute = validationRules(context, otherRules, skipValidation);\n if (!rulesToExecute.length) {\n continue;\n }\n if (component.truncateMultipleSpaces && amendedValue && typeof amendedValue === 'string') {\n amendedValue = amendedValue.trim().replace(/\\s{2,}/g, ' ');\n }\n for (const rule of rulesToExecute) {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value: amendedValue, index: i, path: amendedPath })), context);\n }\n }\n }\n for (const rule of fullValueRules) {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n return;\n }\n if (instance === null || instance === void 0 ? void 0 : instance.shouldSkipValidation(data, row)) {\n return;\n }\n const rulesToExecute = validationRules(context, rules, skipValidation);\n if (!rulesToExecute.length) {\n return;\n }\n if (component.truncateMultipleSpaces && value && typeof value === 'string') {\n (0, set_1.default)(data, path, value.trim().replace(/\\s{2,}/g, ' '));\n }\n for (const rule of rulesToExecute) {\n try {\n if (rule && rule.processSync) {\n handleError(rule.processSync(Object.assign(Object.assign({}, context), { value })), context);\n }\n }\n catch (err) {\n console.error(\"Validator error:\", (0, error_1.getErrorMessage)(err));\n }\n }\n return;\n};\nexports.validateProcessSync = validateProcessSync;\nconst validateCustomProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.evaluationRules;\n context.skipValidation = exports.shouldSkipValidationCustom;\n return (0, exports.validateProcess)(context);\n});\nexports.validateCustomProcess = validateCustomProcess;\nconst validateCustomProcessSync = (context) => {\n context.rules = context.rules || rules_1.evaluationRules;\n context.skipValidation = exports.shouldSkipValidationCustom;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateCustomProcessSync = validateCustomProcessSync;\nconst validateServerProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.serverRules;\n context.skipValidation = exports.shouldSkipValidationSimple;\n return (0, exports.validateProcess)(context);\n});\nexports.validateServerProcess = validateServerProcess;\nconst validateServerProcessSync = (context) => {\n context.rules = context.rules || rules_1.serverRules;\n context.skipValidation = exports.shouldSkipValidationSimple;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateServerProcessSync = validateServerProcessSync;\nconst validateAllProcess = (context) => __awaiter(void 0, void 0, void 0, function* () {\n context.rules = context.rules || rules_1.rules;\n context.skipValidation = exports.shouldSkipValidation;\n return (0, exports.validateProcess)(context);\n});\nexports.validateAllProcess = validateAllProcess;\nconst validateAllProcessSync = (context) => {\n context.rules = context.rules || rules_1.rules;\n context.skipValidation = exports.shouldSkipValidation;\n return (0, exports.validateProcessSync)(context);\n};\nexports.validateAllProcessSync = validateAllProcessSync;\nexports.validateCustomProcessInfo = {\n name: 'validateCustom',\n process: exports.validateCustomProcess,\n processSync: exports.validateCustomProcessSync,\n shouldProcess: shouldValidateCustom,\n};\nexports.validateServerProcessInfo = {\n name: 'validateServer',\n process: exports.validateServerProcess,\n processSync: exports.validateServerProcessSync,\n shouldProcess: shouldValidateServer,\n};\nexports.validateProcessInfo = {\n name: 'validate',\n process: exports.validateAllProcess,\n processSync: exports.validateAllProcessSync,\n shouldProcess: shouldValidateAll,\n};\n__exportStar(__webpack_require__(/*! ./util */ \"./node_modules/@formio/core/lib/process/validation/util.js\"), exports);\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/index.js?");
|
|
578
578
|
|
|
579
579
|
/***/ }),
|
|
580
580
|
|
|
@@ -607,7 +607,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
|
|
|
607
607
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
608
608
|
|
|
609
609
|
"use strict";
|
|
610
|
-
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.databaseRules = void 0;\nconst validateUnique_1 = __webpack_require__(/*! ./validateUnique */ \"./node_modules/@formio/core/lib/process/validation/rules/validateUnique.js\");\nconst validateResourceSelectValue_1 = __webpack_require__(/*! ./validateResourceSelectValue */ \"./node_modules/@formio/core/lib/process/validation/rules/validateResourceSelectValue.js\");\n// These are the validations that require a database connection.\nexports.databaseRules = [\n validateUnique_1.validateUniqueInfo,\n validateResourceSelectValue_1.validateResourceSelectValueInfo\n];\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/rules/databaseRules.js?");
|
|
610
|
+
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.databaseRules = void 0;\nconst validateUnique_1 = __webpack_require__(/*! ./validateUnique */ \"./node_modules/@formio/core/lib/process/validation/rules/validateUnique.js\");\nconst validateCaptcha_1 = __webpack_require__(/*! ./validateCaptcha */ \"./node_modules/@formio/core/lib/process/validation/rules/validateCaptcha.js\");\nconst validateResourceSelectValue_1 = __webpack_require__(/*! ./validateResourceSelectValue */ \"./node_modules/@formio/core/lib/process/validation/rules/validateResourceSelectValue.js\");\n// These are the validations that require a database connection.\nexports.databaseRules = [\n validateUnique_1.validateUniqueInfo,\n validateCaptcha_1.validateCaptchaInfo,\n validateResourceSelectValue_1.validateResourceSelectValueInfo\n];\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/rules/databaseRules.js?");
|
|
611
611
|
|
|
612
612
|
/***/ }),
|
|
613
613
|
|
|
@@ -644,6 +644,17 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
|
|
|
644
644
|
|
|
645
645
|
/***/ }),
|
|
646
646
|
|
|
647
|
+
/***/ "./node_modules/@formio/core/lib/process/validation/rules/validateCaptcha.js":
|
|
648
|
+
/*!***********************************************************************************!*\
|
|
649
|
+
!*** ./node_modules/@formio/core/lib/process/validation/rules/validateCaptcha.js ***!
|
|
650
|
+
\***********************************************************************************/
|
|
651
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
652
|
+
|
|
653
|
+
"use strict";
|
|
654
|
+
eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.validateCaptchaInfo = exports.validateCaptcha = exports.shouldValidate = void 0;\nconst FieldError_1 = __webpack_require__(/*! ../../../error/FieldError */ \"./node_modules/@formio/core/lib/error/FieldError.js\");\nconst error_1 = __webpack_require__(/*! ../../../error */ \"./node_modules/@formio/core/lib/error/index.js\");\nconst shouldValidate = (context) => {\n const { component } = context;\n if (component.type === 'recaptcha') {\n return true;\n }\n return false;\n};\nexports.shouldValidate = shouldValidate;\nconst validateCaptcha = (context) => __awaiter(void 0, void 0, void 0, function* () {\n var _a;\n const { value, config, component } = context;\n if (!(0, exports.shouldValidate)(context)) {\n return null;\n }\n if (!config || !config.database) {\n throw new error_1.ProcessorError(\"Can't test for recaptcha success without a database config object\", context, 'validate:validateCaptcha');\n }\n try {\n if (!value || !value.token) {\n return new FieldError_1.FieldError('captchaTokenNotSpecified', context, 'catpcha');\n }\n if (!value.success) {\n return new FieldError_1.FieldError('captchaTokenValidation', context, 'captcha');\n }\n const captchaResult = yield ((_a = config.database) === null || _a === void 0 ? void 0 : _a.validateCaptcha(value.token));\n return (captchaResult === true) ? null : new FieldError_1.FieldError('captchaFailure', context, 'captcha');\n }\n catch (err) {\n throw new error_1.ProcessorError(err.message || err, context, 'validate:validateCaptcha');\n }\n});\nexports.validateCaptcha = validateCaptcha;\nexports.validateCaptchaInfo = {\n name: 'validateCaptcha',\n process: exports.validateCaptcha,\n shouldProcess: exports.shouldValidate,\n};\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/rules/validateCaptcha.js?");
|
|
655
|
+
|
|
656
|
+
/***/ }),
|
|
657
|
+
|
|
647
658
|
/***/ "./node_modules/@formio/core/lib/process/validation/rules/validateCustom.js":
|
|
648
659
|
/*!**********************************************************************************!*\
|
|
649
660
|
!*** ./node_modules/@formio/core/lib/process/validation/rules/validateCustom.js ***!
|
|
@@ -882,7 +893,7 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
|
|
|
882
893
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
883
894
|
|
|
884
895
|
"use strict";
|
|
885
|
-
eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.validateRequiredInfo = exports.validateRequiredSync = exports.validateRequired = exports.shouldValidate = void 0;\nconst error_1 = __webpack_require__(/*! ../../../error */ \"./node_modules/@formio/core/lib/error/index.js\");\nconst util_1 = __webpack_require__(/*! ../util */ \"./node_modules/@formio/core/lib/process/validation/util.js\");\nconst formUtil_1 = __webpack_require__(/*! ../../../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst isAddressComponent = (component) => {\n return component.type === 'address';\n};\nconst isDayComponent = (component) => {\n return component.type === 'day';\n};\nconst isAddressComponentDataObject = (value) => {\n return value !== null && typeof value === 'object' && value.mode && value.address && typeof value.address === 'object';\n};\n// Checkboxes and selectboxes consider false to be falsy, whereas other components with\n// settable values (e.g. radio, select, datamap, container, etc.) consider it truthy\nconst isComponentThatCannotHaveFalseValue = (component) => {\n return component.type === 'checkbox' || component.type === 'selectboxes';\n};\nconst valueIsPresent = (value, considerFalseTruthy, isNestedDatatype) => {\n // Evaluate for 3 out of 6 falsy values (\"\", null, undefined), don't check for 0\n // and only check for false under certain conditions\n if (value === null || value === undefined || value === \"\" || (!considerFalseTruthy && value === false)) {\n return false;\n }\n // Evaluate for empty object\n else if ((0, util_1.isEmptyObject)(value)) {\n return false;\n }\n // Evaluate for empty array\n else if (Array.isArray(value) && value.length === 0) {\n return false;\n }\n // Recursively evaluate\n else if (typeof value === 'object' && !isNestedDatatype) {\n return Object.values(value).some((val) => valueIsPresent(val, considerFalseTruthy));\n }\n
|
|
896
|
+
eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.validateRequiredInfo = exports.validateRequiredSync = exports.validateRequired = exports.shouldValidate = void 0;\nconst error_1 = __webpack_require__(/*! ../../../error */ \"./node_modules/@formio/core/lib/error/index.js\");\nconst util_1 = __webpack_require__(/*! ../util */ \"./node_modules/@formio/core/lib/process/validation/util.js\");\nconst formUtil_1 = __webpack_require__(/*! ../../../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst isAddressComponent = (component) => {\n return component.type === 'address';\n};\nconst isDayComponent = (component) => {\n return component.type === 'day';\n};\nconst isAddressComponentDataObject = (value) => {\n return value !== null && typeof value === 'object' && value.mode && value.address && typeof value.address === 'object';\n};\n// Checkboxes and selectboxes consider false to be falsy, whereas other components with\n// settable values (e.g. radio, select, datamap, container, etc.) consider it truthy\nconst isComponentThatCannotHaveFalseValue = (component) => {\n return component.type === 'checkbox' || component.type === 'selectboxes';\n};\nconst valueIsPresent = (value, considerFalseTruthy, isNestedDatatype) => {\n // Evaluate for 3 out of 6 falsy values (\"\", null, undefined), don't check for 0\n // and only check for false under certain conditions\n if (value === null || value === undefined || value === \"\" || (!considerFalseTruthy && value === false)) {\n return false;\n }\n // Evaluate for empty object\n else if ((0, util_1.isEmptyObject)(value)) {\n return false;\n }\n // Evaluate for empty array\n else if (Array.isArray(value) && value.length === 0) {\n return false;\n }\n // Recursively evaluate\n else if (typeof value === 'object' && !isNestedDatatype) {\n return Object.values(value).some((val) => valueIsPresent(val, considerFalseTruthy));\n }\n return true;\n};\nconst shouldValidate = (context) => {\n var _a;\n const { component } = context;\n if (((_a = component.validate) === null || _a === void 0 ? void 0 : _a.required) && !component.hidden) {\n return true;\n }\n return false;\n};\nexports.shouldValidate = shouldValidate;\nconst validateRequired = (context) => __awaiter(void 0, void 0, void 0, function* () {\n return (0, exports.validateRequiredSync)(context);\n});\nexports.validateRequired = validateRequired;\nconst validateRequiredSync = (context) => {\n const error = new error_1.FieldError('required', Object.assign(Object.assign({}, context), { setting: true }));\n const { component, value } = context;\n if (!(0, exports.shouldValidate)(context)) {\n return null;\n }\n if (isAddressComponent(component) && isAddressComponentDataObject(value)) {\n return (0, util_1.isEmptyObject)(value.address) ? error : Object.values(value.address).every((val) => !!val) ? null : error;\n }\n else if (isDayComponent(component) && value === '00/00/0000') {\n return error;\n }\n else if (isComponentThatCannotHaveFalseValue(component)) {\n return !valueIsPresent(value, false, (0, formUtil_1.isComponentNestedDataType)(component)) ? error : null;\n }\n return !valueIsPresent(value, true, (0, formUtil_1.isComponentNestedDataType)(component)) ? error : null;\n};\nexports.validateRequiredSync = validateRequiredSync;\nexports.validateRequiredInfo = {\n name: 'validateRequired',\n process: exports.validateRequired,\n processSync: exports.validateRequiredSync,\n shouldProcess: exports.shouldValidate,\n};\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/rules/validateRequired.js?");
|
|
886
897
|
|
|
887
898
|
/***/ }),
|
|
888
899
|
|
|
@@ -970,7 +981,7 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
|
|
|
970
981
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
971
982
|
|
|
972
983
|
"use strict";
|
|
973
|
-
eval("\
|
|
984
|
+
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.interpolateErrors = exports.isObject = exports.isPromise = exports.toBoolean = exports.getComponentErrorField = exports.isEmptyObject = exports.isComponentProtected = exports.isComponentPersistent = void 0;\nconst utils_1 = __webpack_require__(/*! ../../utils */ \"./node_modules/@formio/core/lib/utils/index.js\");\nconst i18n_1 = __webpack_require__(/*! ./i18n */ \"./node_modules/@formio/core/lib/process/validation/i18n/index.js\");\nfunction isComponentPersistent(component) {\n return component.persistent ? component.persistent : true;\n}\nexports.isComponentPersistent = isComponentPersistent;\nfunction isComponentProtected(component) {\n return component.protected ? component.protected : false;\n}\nexports.isComponentProtected = isComponentProtected;\nfunction isEmptyObject(obj) {\n return !!obj && Object.keys(obj).length === 0 && obj.constructor === Object;\n}\nexports.isEmptyObject = isEmptyObject;\nfunction getComponentErrorField(component, context) {\n const toInterpolate = component.errorLabel || component.label || component.placeholder || component.key;\n return utils_1.Evaluator.interpolate(toInterpolate, context);\n}\nexports.getComponentErrorField = getComponentErrorField;\nfunction toBoolean(value) {\n switch (typeof value) {\n case 'string':\n if (value === 'true' || value === '1') {\n return true;\n }\n else if (value === 'false' || value === '0') {\n return false;\n }\n else {\n throw `Cannot coerce string ${value} to boolean}`;\n }\n case 'boolean':\n return value;\n default:\n return !!value;\n }\n}\nexports.toBoolean = toBoolean;\nfunction isPromise(value) {\n return (value &&\n value.then &&\n typeof value.then === 'function' &&\n Object.prototype.toString.call(value) === '[object Promise]');\n}\nexports.isPromise = isPromise;\nfunction isObject(obj) {\n return typeof obj != null && (typeof obj === 'object' || typeof obj === 'function');\n}\nexports.isObject = isObject;\n/**\n * Interpolates @formio/core errors so that they are compatible with the renderer\n * @param {FieldError[]} errors\n * @param firstPass\n * @returns {[]}\n */\nconst interpolateErrors = (errors, lang = 'en') => {\n return errors.map((error) => {\n const { errorKeyOrMessage, context } = error;\n const i18n = i18n_1.VALIDATION_ERRORS[lang] || {};\n const toInterpolate = i18n[errorKeyOrMessage] ? i18n[errorKeyOrMessage] : errorKeyOrMessage;\n const paths = [];\n context.path.split('.').forEach((part) => {\n const match = part.match(/\\[([0-9]+)\\]$/);\n if (match) {\n paths.push(part.substring(0, match.index));\n paths.push(parseInt(match[1]));\n }\n else {\n paths.push(part);\n }\n });\n return {\n message: (0, utils_1.unescapeHTML)(utils_1.Evaluator.interpolateString(toInterpolate, context)),\n level: error.level,\n path: paths,\n context: {\n validator: error.ruleName,\n hasLabel: context.hasLabel,\n key: context.component.key,\n label: context.component.label || context.component.placeholder || context.component.key,\n path: context.path,\n value: context.value,\n setting: context.setting,\n index: context.index || 0\n }\n };\n });\n};\nexports.interpolateErrors = interpolateErrors;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/process/validation/util.js?");
|
|
974
985
|
|
|
975
986
|
/***/ }),
|
|
976
987
|
|
|
@@ -1784,7 +1795,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
1784
1795
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
1785
1796
|
|
|
1786
1797
|
"use strict";
|
|
1787
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./node_modules/@formio/core/lib/utils/operators/ConditionOperator.js\"));\nconst lodash_1 = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nclass IsEmptyValue extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEmpty';\n }\n static get displayedName() {\n return 'Is Empty';\n }\n static get requireValue() {\n return false;\n }\n execute({ value, instance, conditionComponentPath }) {\n
|
|
1798
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./node_modules/@formio/core/lib/utils/operators/ConditionOperator.js\"));\nconst lodash_1 = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nclass IsEmptyValue extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEmpty';\n }\n static get displayedName() {\n return 'Is Empty';\n }\n static get requireValue() {\n return false;\n }\n execute({ value, instance, conditionComponentPath }) {\n const isEmptyValue = (0, lodash_1.isEmpty)(value);\n if (instance && instance.root) {\n const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);\n return conditionTriggerComponent ? conditionTriggerComponent.isEmpty() : isEmptyValue;\n }\n return isEmptyValue;\n }\n getResult(options) {\n return this.execute(options);\n }\n}\nexports[\"default\"] = IsEmptyValue;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/utils/operators/IsEmptyValue.js?");
|
|
1788
1799
|
|
|
1789
1800
|
/***/ }),
|
|
1790
1801
|
|
|
@@ -4616,16 +4627,6 @@ eval("/* module decorator */ module = __webpack_require__.nmd(module);\nvar root
|
|
|
4616
4627
|
|
|
4617
4628
|
/***/ }),
|
|
4618
4629
|
|
|
4619
|
-
/***/ "./node_modules/lodash/isEmpty.js":
|
|
4620
|
-
/*!****************************************!*\
|
|
4621
|
-
!*** ./node_modules/lodash/isEmpty.js ***!
|
|
4622
|
-
\****************************************/
|
|
4623
|
-
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
|
4624
|
-
|
|
4625
|
-
eval("var baseKeys = __webpack_require__(/*! ./_baseKeys */ \"./node_modules/lodash/_baseKeys.js\"),\n getTag = __webpack_require__(/*! ./_getTag */ \"./node_modules/lodash/_getTag.js\"),\n isArguments = __webpack_require__(/*! ./isArguments */ \"./node_modules/lodash/isArguments.js\"),\n isArray = __webpack_require__(/*! ./isArray */ \"./node_modules/lodash/isArray.js\"),\n isArrayLike = __webpack_require__(/*! ./isArrayLike */ \"./node_modules/lodash/isArrayLike.js\"),\n isBuffer = __webpack_require__(/*! ./isBuffer */ \"./node_modules/lodash/isBuffer.js\"),\n isPrototype = __webpack_require__(/*! ./_isPrototype */ \"./node_modules/lodash/_isPrototype.js\"),\n isTypedArray = __webpack_require__(/*! ./isTypedArray */ \"./node_modules/lodash/isTypedArray.js\");\n\n/** `Object#toString` result references. */\nvar mapTag = '[object Map]',\n setTag = '[object Set]';\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Checks if `value` is an empty object, collection, map, or set.\n *\n * Objects are considered empty if they have no own enumerable string keyed\n * properties.\n *\n * Array-like values such as `arguments` objects, arrays, buffers, strings, or\n * jQuery-like collections are considered empty if they have a `length` of `0`.\n * Similarly, maps and sets are considered empty if they have a `size` of `0`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n * @example\n *\n * _.isEmpty(null);\n * // => true\n *\n * _.isEmpty(true);\n * // => true\n *\n * _.isEmpty(1);\n * // => true\n *\n * _.isEmpty([1, 2, 3]);\n * // => false\n *\n * _.isEmpty({ 'a': 1 });\n * // => false\n */\nfunction isEmpty(value) {\n if (value == null) {\n return true;\n }\n if (isArrayLike(value) &&\n (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||\n isBuffer(value) || isTypedArray(value) || isArguments(value))) {\n return !value.length;\n }\n var tag = getTag(value);\n if (tag == mapTag || tag == setTag) {\n return !value.size;\n }\n if (isPrototype(value)) {\n return !baseKeys(value).length;\n }\n for (var key in value) {\n if (hasOwnProperty.call(value, key)) {\n return false;\n }\n }\n return true;\n}\n\nmodule.exports = isEmpty;\n\n\n//# sourceURL=webpack://Formio/./node_modules/lodash/isEmpty.js?");
|
|
4626
|
-
|
|
4627
|
-
/***/ }),
|
|
4628
|
-
|
|
4629
4630
|
/***/ "./node_modules/lodash/isFunction.js":
|
|
4630
4631
|
/*!*******************************************!*\
|
|
4631
4632
|
!*** ./node_modules/lodash/isFunction.js ***!
|
|
@@ -4995,7 +4996,7 @@ eval("\n\nfunction hash(str) {\n var hash = 5381,\n i = str.length;\n\n
|
|
|
4995
4996
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
4996
4997
|
|
|
4997
4998
|
"use strict";
|
|
4998
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.Formio = exports.FormioPathType = void 0;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst fastCloneDeep_1 = __webpack_require__(/*! ../utils/fastCloneDeep */ \"./node_modules/@formio/core/lib/utils/fastCloneDeep.js\");\nconst lodash_1 = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nconst formUtil_1 = __webpack_require__(/*! ../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst jwtDecode_1 = __webpack_require__(/*! ../utils/jwtDecode */ \"./node_modules/@formio/core/lib/utils/jwtDecode.js\");\nconst eventemitter3_1 = __importDefault(__webpack_require__(/*! eventemitter3 */ \"./node_modules/eventemitter3/index.js\"));\nconst browser_cookies_1 = __importDefault(__webpack_require__(/*! browser-cookies */ \"./node_modules/browser-cookies/src/browser-cookies.js\"));\nconst { fetch, Headers } = (0, fetch_ponyfill_1.default)();\nconst Plugins_1 = __importDefault(__webpack_require__(/*! ./Plugins */ \"./node_modules/@formio/core/lib/sdk/Plugins.js\"));\n/**\n * The different path types for a project.\n */\nvar FormioPathType;\n(function (FormioPathType) {\n FormioPathType[\"Subdirectories\"] = \"Subdirectories\";\n FormioPathType[\"Subdomains\"] = \"Subdomains\";\n})(FormioPathType || (exports.FormioPathType = FormioPathType = {}));\n/**\n * The Formio interface class. This is a minimalistic API library that allows you to work with the Form.io API's within JavaScript.\n *\n * ## Usage\n * Creating an instance of Formio is simple, and takes only a path (URL String). The path can be different, depending on the desired output.\n * The Formio instance can also access higher level operations, depending on how granular of a path you start with.\n *\n * ```ts\n * var formio = new Formio(<endpoint>, [options]);\n * ```\n *\n * Where **endpoint** is any valid API endpoint within Form.io. These URL's can provide a number of different methods depending on the granularity of the endpoint. This allows you to use the same interface but have access to different methods depending on how granular the endpoint url is.\n * **options** is defined within the {link Formio.constructor} documentation.\n *\n * Here is an example of how this library can be used to load a form JSON from the Form.io API's\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n */\nclass Formio {\n /* eslint-disable max-statements */\n /**\n * @constructor\n * @param {string} path - A project, form, and submission API Url.\n * @param {FormioOptions} options - Available options to configure the Javascript API.\n */\n constructor(path, options = {}) {\n this.path = path;\n this.options = options;\n /**\n * The base API url of the Form.io Platform. Example: https://api.form.io\n */\n this.base = '';\n /**\n * The Projects Endpoint derived from the provided source.\n *\n * @example https://api.form.io/project\n */\n this.projectsUrl = '';\n /**\n * A specific project endpoint derived from the provided source.\n *\n * @example https://examples.form.io\n */\n this.projectUrl = '';\n /**\n * The Project ID found within the provided source.\n */\n this.projectId = '';\n /**\n * A specific Role URL provided the source.\n *\n * @example https://examples.form.io/role/2342343234234234\n */\n this.roleUrl = '';\n /**\n * The roles endpoint derived from the provided source.\n *\n * @example https://examples.form.io/role\n */\n this.rolesUrl = '';\n /**\n * The roleID derieved from the provided source.\n */\n this.roleId = '';\n /**\n * A specific form url derived from the provided source.\n *\n * @example https://examples.form.io/example\n */\n this.formUrl = '';\n /**\n * The forms url derived from the provided source.\n *\n * @example https://example.form.io/form\n */\n this.formsUrl = '';\n /**\n * The Form ID derived from the provided source.\n */\n this.formId = '';\n /**\n * The submissions URL derived from the provided source.\n *\n * @example https://examples.form.io/example/submission\n */\n this.submissionsUrl = '';\n /**\n * A specific submissions URL derived from a provided source.\n *\n * @example https://examples.form.io/example/submission/223423423423\n */\n this.submissionUrl = '';\n /**\n * The submission ID provided a submission url.\n */\n this.submissionId = '';\n /**\n * The actions url provided a form url as the source.\n *\n * @example https://examples.form.io/example/action\n */\n this.actionsUrl = '';\n /**\n * The Action ID derived from a provided Action url.\n */\n this.actionId = '';\n /**\n * A specific action api endoint.\n */\n this.actionUrl = '';\n this.vsUrl = '';\n this.vId = '';\n this.vUrl = '';\n /**\n * The query string derived from the provided src url.\n */\n this.query = '';\n /**\n * If this is a non-project url, such is the case for Open Source API.\n */\n this.noProject = false;\n // Ensure we have an instance of Formio.\n if (!(this instanceof Formio)) {\n return new Formio(path);\n }\n if (options.useSessionToken) {\n Formio.useSessionToken(options);\n }\n if (options.hasOwnProperty('base') && options.base) {\n this.base = options.base;\n }\n else if (Formio.baseUrl) {\n this.base = Formio.baseUrl;\n }\n else if (window && window.location) {\n const match = window.location.href.match(/http[s]?:\\/\\/api./);\n this.base = match ? match[0] : window.location.origin;\n }\n if (!path) {\n // Allow user to create new projects if this was instantiated without\n // a url\n this.projectUrl = Formio.projectUrl || `${this.base}/project`;\n this.projectsUrl = `${this.base}/project`;\n this.projectId = '';\n this.query = '';\n return;\n }\n if (options.hasOwnProperty('project') && options.project) {\n this.projectUrl = options.project;\n }\n const project = this.projectUrl || Formio.projectUrl;\n const projectRegEx = /(^|\\/)(project)($|\\/[^/]+)/;\n const isProjectUrl = (path.search(projectRegEx) !== -1);\n // The baseURL is the same as the projectUrl, and does not contain \"/project/MONGO_ID\" in\n // its domain. This is almost certainly against the Open Source server.\n if (project && this.base === project && !isProjectUrl) {\n this.noProject = true;\n this.projectUrl = this.base;\n }\n // Normalize to an absolute path.\n if ((path.indexOf('http') !== 0) && (path.indexOf('//') !== 0)) {\n path = this.base + path;\n }\n const hostparts = this.getUrlParts(path);\n let hostName = '';\n let parts = [];\n if (hostparts) {\n hostName = hostparts[1] + hostparts[2];\n path = hostparts.length > 3 ? hostparts[3] : '';\n const queryparts = path.split('?');\n if (queryparts.length > 1) {\n path = queryparts[0];\n this.query = `?${queryparts[1]}`;\n }\n }\n // Register a specific path.\n const registerPath = (name, base) => {\n this[`${name}sUrl`] = `${base}/${name}`;\n const regex = new RegExp(`/${name}/([^/]+)`);\n if (path && path.search(regex) !== -1) {\n parts = path.match(regex);\n this[`${name}Url`] = parts ? (base + parts[0]) : '';\n this[`${name}Id`] = (parts.length > 1) ? parts[1] : '';\n base += parts[0];\n }\n return base;\n };\n // Register an array of items.\n const registerItems = (items, base, staticBase) => {\n for (const i in items) {\n if (items.hasOwnProperty(i)) {\n const item = items[i];\n if (Array.isArray(item)) {\n registerItems(item, base, true);\n }\n else {\n const newBase = registerPath(item, base);\n base = staticBase ? base : newBase;\n }\n }\n }\n };\n if (!this.projectUrl || (this.projectUrl === this.base)) {\n // If a project uses Subdirectories path type, we need to specify a projectUrl\n if (!this.projectUrl && !isProjectUrl && Formio.pathType === 'Subdirectories') {\n const regex = `^${hostName.replace(/\\//g, '\\\\/')}.[^/]+`;\n const match = project.match(new RegExp(regex));\n this.projectUrl = match ? match[0] : hostName;\n }\n else {\n this.projectUrl = hostName;\n }\n }\n // Check if we have a specified path type.\n let isNotSubdomainType = false;\n if (Formio.pathType) {\n isNotSubdomainType = Formio.pathType !== 'Subdomains';\n }\n if (!this.noProject) {\n // Determine the projectUrl and projectId\n if (isProjectUrl) {\n // Get project id as project/:projectId.\n registerItems(['project'], hostName);\n path = path.replace(projectRegEx, '');\n }\n else if (hostName === this.base) {\n // Get project id as first part of path (subdirectory).\n if (hostparts && hostparts.length > 3 && path.split('/').length > 1) {\n const isFile = path.match(/.json/);\n const pathParts = path.split('/');\n if (isFile) {\n this.projectUrl = hostName;\n }\n else {\n pathParts.shift(); // Throw away the first /.\n const projectId = pathParts.shift();\n if (projectId) {\n this.projectId = projectId;\n path = `/${pathParts.join('/')}`;\n this.projectUrl = `${hostName}/${this.projectId}`;\n }\n }\n }\n }\n else {\n // Get project id from subdomain.\n if (hostparts && hostparts.length > 2 && (hostparts[2].split('.').length > 2 || hostName.includes('localhost')) && !isNotSubdomainType) {\n this.projectUrl = hostName;\n this.projectId = hostparts[2].split('.')[0];\n }\n }\n this.projectsUrl = this.projectsUrl || `${this.base}/project`;\n }\n // Configure Role urls and role ids.\n registerItems(['role'], this.projectUrl);\n // Configure Form urls and form ids.\n if (/(^|\\/)(form)($|\\/)/.test(path)) {\n registerItems(['form', ['submission', 'action', 'v']], this.projectUrl);\n }\n else {\n const subRegEx = new RegExp('/(submission|action|v)($|/.*)');\n const subs = path.match(subRegEx);\n if ((subs && (subs.length > 1))) {\n this.pathType = subs[1];\n }\n path = path.replace(subRegEx, '');\n path = path.replace(/\\/$/, '');\n this.formsUrl = `${this.projectUrl}/form`;\n this.formUrl = path ? this.projectUrl + path : '';\n this.formId = path.replace(/^\\/+|\\/+$/g, '');\n const items = ['submission', 'action', 'v'];\n for (const i in items) {\n if (items.hasOwnProperty(i)) {\n const item = items[i];\n this[`${item}sUrl`] = `${this.projectUrl + path}/${item}`;\n if ((this.pathType === item) && subs && (subs.length > 2) && subs[2]) {\n this[`${item}Id`] = subs[2].replace(/^\\/+|\\/+$/g, '');\n this[`${item}Url`] = this.projectUrl + path + subs[0];\n }\n }\n }\n }\n // Set the app url if it is not set.\n if (!Formio.projectUrlSet) {\n Formio.projectUrl = this.projectUrl;\n }\n }\n /* eslint-enable max-statements */\n /**\n * Deletes a remote resource of any provided type.\n *\n * @param {string} type - The type of resource to delete. \"submission\", \"form\", etc.\n * @param {object} options - The options passed to {@link Formio.request}\n * @return {Promise<Response>}\n */\n delete(type, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n if (!this[_id]) {\n return Promise.reject('Nothing to delete');\n }\n Formio.cache = {};\n return this.makeRequest(type, this[_url], 'delete', null, opts);\n }\n /**\n * Returns the index (array of records) for any provided type.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} query - A query object to pass to the request.\n * @param {object} query.params - A map (key-value pairs) of URL query parameters to add to the url.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n index(type, query, opts) {\n const _url = `${type}Url`;\n query = query || '';\n if (query && (0, lodash_1.isObject)(query)) {\n query = `?${Formio.serialize(query.params)}`;\n }\n return this.makeRequest(type, this[_url] + query, 'get', null, opts);\n }\n /**\n * Save a document record using \"upsert\". If the document does not exist, it will be created, if the _id is provided,\n * it will be updated.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} data - The resource data object.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n save(type, data, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n const method = (this[_id] || data._id) ? 'put' : 'post';\n let reqUrl = this[_id] ? this[_url] : this[`${type}sUrl`];\n if (!this[_id] && data._id && (method === 'put') && !reqUrl.includes(data._id)) {\n reqUrl += `/${data._id}`;\n }\n Formio.cache = {};\n return this.makeRequest(type, reqUrl + this.query, method, data, opts);\n }\n /**\n * @summary Load (GET) a document record.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} query - A query object to pass to the request.\n * @param {object} query.params - A map (key-value pairs) of URL query parameters to add to the url.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n load(type, query, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n if (query && (0, lodash_1.isObject)(query)) {\n query = Formio.serialize(query.params);\n }\n if (query) {\n query = this.query ? (`${this.query}&${query}`) : (`?${query}`);\n }\n else {\n query = this.query;\n }\n if (!this[_id]) {\n return Promise.reject(`Missing ${_id}`);\n }\n let url = this[_url] + query;\n if (type === 'form' && !isNaN(parseInt(this.vId))) {\n url += url.indexOf('?') === -1 ? '?' : '&';\n url += `formRevision=${this.vId}`;\n }\n return this.makeRequest(type, url, 'get', null, opts);\n }\n /**\n * @summary Call {@link Formio.makeRequest} for this Formio instance.\n *\n * @param {string} type - The request resource type. \"submission\", \"form\", etc.\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>}\n */\n makeRequest(type, url, method, data, opts) {\n return Formio.makeRequest(this, type, url, method, data, opts);\n }\n /**\n * @summary Loads a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadProject().then((project) => {\n * console.log(project);\n * });\n * ```\n *\n * @param {object} query - Query parameters to pass to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadProject(query, opts) {\n return this.load('project', query, opts);\n }\n /**\n * Saves or Updates a project.\n *\n * ### Create a new project\n * ```ts\n * const formio = new Formio();\n * formio.saveProject({\n * title: 'My Project',\n * path: 'myproject',\n * name: 'myproject'\n * });\n * ```\n *\n * ### Update an existing project\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadProject().then((project) => {\n * project.title = 'Title changed';\n * formio.saveProject(project).then(() => {\n * console.log('Done saving project!');\n * });\n * });\n * ```\n *\n * @param {object} data - The project JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveProject(data, opts) {\n return this.save('project', data, opts);\n }\n /**\n * Deletes a project\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.deleteProject();\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n deleteProject(opts) {\n return this.delete('project', opts);\n }\n /**\n * Loads a list of all projects.\n *\n * ```ts\n * Formio.loadProjects().then((projects) => {\n * console.log(projects);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {*}\n */\n static loadProjects(query, opts) {\n query = query || '';\n if ((0, lodash_1.isObject)(query)) {\n query = `?${Formio.serialize(query.params)}`;\n }\n return Formio.makeStaticRequest(`${Formio.baseUrl}/project${query}`, 'GET', null, opts);\n }\n /**\n * Loads a role within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/role/234234234234');\n * formio.loadRole().then((role) => {\n * console.log(role);\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadRole(opts) {\n return this.load('role', null, opts);\n }\n /**\n * Create a new or Update an existing role within a project.\n *\n * ### Create new Role example\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.saveRole({\n * title: 'Employee',\n * description: 'A person who belongs to a company.'\n * }).then((role) => {\n * console.log(role);\n * });\n * ```\n *\n * ### Update existing role example\n * ```ts\n * const formio = new Formio('https://examples.form.io/role/234234234234234');\n * formio.loadRole().then((role) => {\n * role.title = 'Manager';\n * formio.saveRole(role).then(() => {\n * console.log('DONE');\n * });\n * });\n * ```\n *\n * @param {object} role - The Role JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveRole(data, opts) {\n return this.save('role', data, opts);\n }\n /**\n * Deletes a role within a project.\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteRole(opts) {\n return this.delete('role', opts);\n }\n /**\n * Load all roles within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadRoles().then((roles) => {\n * console.log(roles);\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadRoles(opts) {\n return this.index('roles', null, opts);\n }\n /**\n * Loads a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n loadForm(query, opts) {\n return this.load('form', query, opts)\n .then((currentForm) => {\n // Check to see if there isn't a number in vId.\n if (!currentForm.revisions || isNaN(parseInt(this.vId))) {\n return currentForm;\n }\n // If a submission already exists but form is marked to load current version of form.\n if (currentForm.revisions === 'current' && this.submissionId) {\n return currentForm;\n }\n // eslint-disable-next-line eqeqeq\n if (currentForm._vid == this.vId || currentForm.revisionId === this.vId) {\n return currentForm;\n }\n // If they specified a revision form, load the revised form components.\n if (query && (0, lodash_1.isObject)(query)) {\n query = Formio.serialize(query.params);\n }\n if (query) {\n query = this.query ? (`${this.query}&${query}`) : (`?${query}`);\n }\n else {\n query = this.query;\n }\n return this.makeRequest('form', this.vUrl + query, 'get', null, opts)\n .then((revisionForm) => {\n currentForm._vid = revisionForm._vid;\n currentForm.components = revisionForm.components;\n currentForm.settings = revisionForm.settings;\n currentForm.revisionId = revisionForm.revisionId;\n // Using object.assign so we don't cross polinate multiple form loads.\n return Object.assign({}, currentForm);\n })\n // If we couldn't load the revision, just return the original form.\n .catch(() => Object.assign({}, currentForm));\n });\n }\n /**\n * Create or Update a specific form.\n *\n * ### Create form example\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.saveForm({\n * title: 'Employee',\n * type: 'resource',\n * path: 'employee',\n * name: 'employee',\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name'\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name'\n * }\n * ]\n * });\n * ```\n *\n * ### Update a form example\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * form.title = 'Changed Title';\n * formio.saveForm(form).then(() => {\n * console.log('DONE!!!');\n * });\n * });\n * ```\n *\n * @param {object} data - The Form JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveForm(data, opts) {\n return this.save('form', data, opts);\n }\n /**\n * Deletes a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.deleteForm().then(() => {\n * console.log('Deleted!');\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteForm(opts) {\n return this.delete('form', opts);\n }\n /**\n * Loads all forms within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadForms().then((forms) => {\n * console.log(forms);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadForms(query, opts) {\n return this.index('forms', query, opts);\n }\n /**\n * Loads a specific submissionn.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/23423423423423423');\n * formio.loadSubmission().then((submission) => {\n * console.log(submission);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n loadSubmission(query, opts) {\n return this.load('submission', query, opts)\n .then((submission) => {\n this.vId = submission._frid || submission._fvid;\n this.vUrl = `${this.formUrl}/v/${this.vId}`;\n return submission;\n });\n }\n /**\n * Creates a new or Updates an existing submission.\n *\n * ### Create a new submission\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.saveSubmission({\n * data: {\n * firstName: 'Joe',\n * lastName: 'Smith'\n * }\n * }).then((submission) => {\n * // This will now be the complete submission object saved on the server.\n * console.log(submission);\n * });\n * ```\n *\n * ### Update an existing submission\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/23423423423423423');\n * formio.loadSubmission().then((submission) => {\n * submission.data.lastName = 'Thompson';\n * formio.saveSubmission(submission).then(() => {\n * console.log('DONE');\n * });\n * });\n * ```\n *\n * @param {object} data - The submission JSON object.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveSubmission(data, opts) {\n if (!isNaN(parseInt(this.vId)) && !data._fvid) {\n data._fvid = this.vId;\n }\n return this.save('submission', data, opts);\n }\n /**\n * Deletes a submission.\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteSubmission(opts) {\n return this.delete('submission', opts);\n }\n /**\n * Loads all submissions within a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadSubmissions({\n * params: {\n * limit: 25,\n * 'data.lastName__regex': 'smith'\n * }\n * }).then((submissions) => {\n * // Should print out 25 submissions where the last name contains \"smith\".\n * console.log(submissions);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadSubmissions(query, opts) {\n return this.index('submissions', query, opts);\n }\n /**\n * Loads a form action.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.loadAction().then((action) => {\n * console.log(action);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadAction(query, opts) {\n return this.load('action', query, opts);\n }\n /**\n * Create a new or update an existing action.\n *\n * ### Create a new action for a form.\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.saveAction({\n * data: {\n * name: 'webhook',\n * title: 'Webhook Action',\n * method: ['create', 'update', 'delete'],\n * handler: ['after'],\n * condition: {},\n * settings: {\n * url: 'https://example.com',\n * headers: [{}],\n * block: false,\n * forwardHeaders: false\n * }\n * }\n * }).then((action) => {\n * console.log(action);\n * });\n * ```\n *\n * ### Update an action\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.loadAction().then((action) => {\n * action.title = 'Updated title';\n * formio.saveAction(action).then(() => {\n * console.log('Done!');\n * });\n * });\n * ```\n *\n * @param {object} data - The action JSON\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveAction(data, opts) {\n return this.save('action', data, opts);\n }\n /**\n * Delete an action\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.deleteAction().then(() => {\n * console.log('Action was deleted.');\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteAction(opts) {\n return this.delete('action', opts);\n }\n /**\n * Loads all actions within a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadActions().then((actions) => {\n * console.log(actions);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadActions(query, opts) {\n return this.index('actions', query, opts);\n }\n /**\n * Returns a list of available actions\n *\n * @return {Promise<Response>}\n */\n availableActions() {\n return this.makeRequest('availableActions', `${this.formUrl}/actions`);\n }\n /**\n * Returns the action information for a specific action, such as \"save\".\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/actions/save');\n * formio.actionInfo().then((info) => {\n * console.log(info);\n * });\n * ```\n *\n * @param {string} name - The name of the action you would like to get information for. i.e. \"save\", \"webhook\", etc.\n * @return {Promise<Response>}\n */\n actionInfo(name) {\n return this.makeRequest('actionInfo', `${this.formUrl}/actions/${name}`);\n }\n /**\n * Determine if a string ID is a valid MongoID.\n *\n * @param {string} id - The id that should be tested if it is avalid id.\n * @return {boolean} - true if it is a valid MongoId, false otherwise.\n */\n isObjectId(id) {\n const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');\n return checkForHexRegExp.test(id);\n }\n /**\n * Get the project ID of project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.getProjectId().then((projectId) => {\n * console.log(projectId);\n * };\n * ```\n *\n * @return {Promise<string>}\n */\n getProjectId() {\n if (!this.projectId) {\n return Promise.resolve('');\n }\n if (this.isObjectId(this.projectId)) {\n return Promise.resolve(this.projectId);\n }\n else {\n return this.loadProject().then((project) => {\n return project._id;\n });\n }\n }\n /**\n * Get the ID of a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.getFormId().then((formId) => {\n * console.log(formId);\n * });\n * ```\n *\n * @return {Promise<string>}\n */\n getFormId() {\n if (!this.formId) {\n return Promise.resolve('');\n }\n if (this.isObjectId(this.formId)) {\n return Promise.resolve(this.formId);\n }\n else {\n return this.loadForm().then((form) => {\n return form._id;\n });\n }\n }\n /**\n * Instance method for {@link Formio.currentUser}\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n currentUser(options) {\n return Formio.currentUser(this, options);\n }\n /**\n * Instance method for {@link Formio.accessInfo}\n *\n * @return {Promise<Response>}\n */\n accessInfo() {\n return Formio.accessInfo(this);\n }\n /**\n * Sets OAuth Logout URL.\n *\n * @param {string} uri - Logout URL.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string}\n */\n oauthLogoutURI(uri, options) {\n return Formio.oauthLogoutURI(uri, Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Returns the JWT token for this instance.\n *\n * @param {object} options - The following options are provided.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string} - The JWT token for this user.\n */\n getToken(options) {\n return Formio.getToken(Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Sets the JWT token for this instance.\n *\n * @param {string} token - The JWT token to set.\n * @param {object} options - The following options are provided.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string} - The JWT token that was set.\n */\n setToken(token, options) {\n return Formio.setToken(token, Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Returns a temporary authentication token for single purpose token generation.\n *\n * @param {number|string} expire - The amount of seconds to wait before this temp token expires.\n * @param {string} allowed - The allowed path string inn the format GET:/path\n * @param {object} options - The options passed to {@link Formio#getToken}\n */\n getTempToken(expire, allowed, options) {\n const token = Formio.getToken(options);\n if (!token) {\n return Promise.reject('You must be authenticated to generate a temporary auth token.');\n }\n const authUrl = Formio.authUrl || this.projectUrl;\n return this.makeRequest('tempToken', `${authUrl}/token`, 'GET', null, {\n ignoreCache: true,\n header: new Headers({\n 'x-expire': expire,\n 'x-allow': allowed\n })\n });\n }\n /**\n * Get a PDF download url for a submission, which will generate a new PDF of the submission. This method will first\n * fetch a temporary download token, and then append this to the download url for this form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/324234234234234');\n * formio.getDownloadUrl().then((url) => {\n * console.log(url);\n * });\n * ```\n *\n * @param {object} [form] - The form JSON to fetch a download url for.\n * @return {Promise<string>} - The download url.\n */\n getDownloadUrl(form) {\n if (!this.submissionId) {\n return Promise.resolve('');\n }\n if (!form) {\n // Make sure to load the form first.\n return this.loadForm().then((_form) => {\n if (!_form) {\n return '';\n }\n return this.getDownloadUrl(_form);\n });\n }\n let apiUrl = `/project/${form.project}`;\n apiUrl += `/form/${form._id}`;\n apiUrl += `/submission/${this.submissionId}`;\n const postfix = form.submissionRevisions && form.settings.changeLog ? '/download/changelog' : '/download';\n apiUrl += postfix;\n let download = this.base + apiUrl;\n return new Promise((resolve, reject) => {\n this.getTempToken(3600, `GET:${apiUrl}`).then((tempToken) => {\n download += `?token=${tempToken.key}`;\n resolve(download);\n }, () => {\n resolve(download);\n }).catch(reject);\n });\n }\n /**\n * Returns the user permissions to a form and submission.\n *\n * @param user - The user or current user if undefined. For anonymous, use \"null\"\n * @param form - The form or current form if undefined. For no form check, use \"null\"\n * @param submission - The submisison or \"index\" if undefined.\n *\n * @return {{create: boolean, read: boolean, edit: boolean, delete: boolean}}\n */\n userPermissions(user, form, submission) {\n return Promise.all([\n (form !== undefined) ? Promise.resolve(form) : this.loadForm(),\n (user !== undefined) ? Promise.resolve(user) : this.currentUser(),\n (submission !== undefined || !this.submissionId) ? Promise.resolve(submission) : this.loadSubmission(),\n this.accessInfo()\n ]).then((results) => {\n const form = results.shift();\n const user = results.shift() || { _id: false, roles: [] };\n const submission = results.shift();\n const access = results.shift();\n const permMap = {\n create: 'create',\n read: 'read',\n update: 'edit',\n delete: 'delete'\n };\n const perms = {\n user: user,\n form: form,\n access: access,\n create: false,\n read: false,\n edit: false,\n delete: false\n };\n for (const roleName in access.roles) {\n if (access.roles.hasOwnProperty(roleName)) {\n const role = access.roles[roleName];\n if (role.default && (user._id === false)) {\n // User is anonymous. Add the anonymous role.\n user.roles.push(role._id);\n }\n else if (role.admin && user.roles.indexOf(role._id) !== -1) {\n perms.create = true;\n perms.read = true;\n perms.delete = true;\n perms.edit = true;\n return perms;\n }\n }\n }\n if (form && form.submissionAccess) {\n for (let i = 0; i < form.submissionAccess.length; i++) {\n const permission = form.submissionAccess[i];\n const [perm, scope] = permission.type.split('_');\n if (['create', 'read', 'update', 'delete'].includes(perm)) {\n if ((0, lodash_1.intersection)(permission.roles, user.roles).length) {\n perms[permMap[perm]] = (scope === 'all') || (!submission || (user._id === submission.owner));\n }\n }\n }\n }\n // check for Group Permissions\n if (submission) {\n // we would anyway need to loop through components for create permission, so we'll do that for all of them\n (0, formUtil_1.eachComponent)(form.components, (component, path) => {\n if (component && component.defaultPermission) {\n const value = (0, lodash_1.get)(submission.data, path);\n // make it work for single-select Group and multi-select Group\n const groups = Array.isArray(value) ? value : [value];\n groups.forEach(group => {\n if (group && group._id && // group id is present\n user.roles.indexOf(group._id) > -1 // user has group id in his roles\n ) {\n if (component.defaultPermission === 'read') {\n perms[permMap.read] = true;\n }\n if (component.defaultPermission === 'create') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n }\n if (component.defaultPermission === 'write') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n perms[permMap.update] = true;\n }\n if (component.defaultPermission === 'admin') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n perms[permMap.update] = true;\n perms[permMap.delete] = true;\n }\n }\n });\n }\n });\n }\n return perms;\n });\n }\n /**\n * `Determine if the current user can submit a form.\n * @return {*}\n */\n canSubmit() {\n return this.userPermissions().then((perms) => {\n // If there is user and they cannot create, then check anonymous user permissions.\n if (!perms.create && Formio.getUser()) {\n return this.userPermissions(null).then((anonPerms) => {\n if (anonPerms.create) {\n Formio.setUser(null);\n return true;\n }\n return false;\n });\n }\n return perms.create;\n });\n }\n getUrlParts(url) {\n return Formio.getUrlParts(url, this);\n }\n static getUrlParts(url, formio) {\n const base = (formio && formio.base) ? formio.base : Formio.baseUrl;\n let regex = '^(http[s]?:\\\\/\\\\/)';\n if (base && url.indexOf(base) === 0) {\n regex += `(${base.replace(/^http[s]?:\\/\\//, '')})`;\n }\n else {\n regex += '([^/]+)';\n }\n regex += '($|\\\\/.*)';\n return url.match(new RegExp(regex));\n }\n static serialize(obj, _interpolate) {\n const str = [];\n const interpolate = (item) => {\n return _interpolate ? _interpolate(item) : item;\n };\n for (const p in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, p)) {\n str.push(`${encodeURIComponent(p)}=${encodeURIComponent(interpolate(obj[p]))}`);\n }\n }\n return str.join('&');\n }\n static getRequestArgs(formio, type, url, method, data, opts) {\n method = (method || 'GET').toUpperCase();\n if (!opts || !(0, lodash_1.isObject)(opts)) {\n opts = {};\n }\n const requestArgs = {\n url,\n method,\n data: data || null,\n opts\n };\n if (type) {\n requestArgs.type = type;\n }\n if (formio) {\n requestArgs.formio = formio;\n }\n return requestArgs;\n }\n static makeStaticRequest(url, method, data, opts) {\n const requestArgs = Formio.getRequestArgs(null, '', url, method, data, opts);\n const request = Plugins_1.default.pluginWait('preRequest', requestArgs)\n .then(() => Plugins_1.default.pluginGet('staticRequest', requestArgs)\n .then((result) => {\n if ((0, lodash_1.isNil)(result)) {\n return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts);\n }\n return result;\n }));\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', request, requestArgs);\n }\n /**\n * Make an API request and wrap that request with the Form.io Request plugin system. This is very similar to the\n * {Formio.request} method with a difference being that it will pass the request through the Form.io request plugin.\n *\n * @param {Formio} formio - An instance of the Formio class.\n * @param {string} type - The request resource type. \"submission\", \"form\", etc.\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>}\n */\n static makeRequest(formio, type, url, method, data, opts) {\n if (!formio) {\n return Formio.makeStaticRequest(url, method, data, opts);\n }\n const requestArgs = Formio.getRequestArgs(formio, type, url, method, data, opts);\n requestArgs.opts = requestArgs.opts || {};\n requestArgs.opts.formio = formio;\n //for Formio requests default Accept and Content-type headers\n if (!requestArgs.opts.headers) {\n requestArgs.opts.headers = {};\n }\n requestArgs.opts.headers = (0, lodash_1.defaults)(requestArgs.opts.headers, {\n 'Accept': 'application/json',\n 'Content-type': 'application/json'\n });\n const request = Plugins_1.default.pluginWait('preRequest', requestArgs)\n .then(() => Plugins_1.default.pluginGet('request', requestArgs)\n .then((result) => {\n if ((0, lodash_1.isNil)(result)) {\n return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts);\n }\n return result;\n }));\n return Plugins_1.default.pluginAlter('wrapRequestPromise', request, requestArgs);\n }\n /**\n * Execute an API request to any external system. This is a wrapper around the Web fetch method.\n *\n * ```ts\n * Formio.request('https://examples.form.io').then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {Headers} header - An object of headers to pass to the request.\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>|*}\n */\n static request(url, method, data, header, opts) {\n if (!url) {\n return Promise.reject('No url provided');\n }\n method = (method || 'GET').toUpperCase();\n // For reverse compatibility, if they provided the ignoreCache parameter,\n // then change it back to the options format where that is a parameter.\n if ((0, lodash_1.isBoolean)(opts)) {\n opts = { ignoreCache: opts };\n }\n if (!opts || !(0, lodash_1.isObject)(opts)) {\n opts = {};\n }\n // Generate a cachekey.\n const cacheKey = btoa(encodeURI(url));\n // Get the cached promise to save multiple loads.\n if (!opts.ignoreCache && method === 'GET' && Formio.cache.hasOwnProperty(cacheKey)) {\n return Promise.resolve(Formio.cloneResponse(Formio.cache[cacheKey]));\n }\n if (url[0] === '/') {\n url = Formio.baseUrl + url;\n }\n // Set up and fetch request\n const headers = header || new Headers(opts.headers || {\n 'Accept': 'application/json',\n 'Content-type': 'application/json'\n });\n const token = Formio.getToken(opts);\n if (token && !opts.noToken) {\n headers.set('x-jwt-token', token);\n }\n // The fetch-ponyfill can't handle a proper Headers class anymore. Change it back to an object.\n const headerObj = {};\n headers.forEach(function (value, name) {\n headerObj[name] = value;\n });\n let options = {\n method: method,\n headers: headerObj,\n mode: 'cors'\n };\n if (data) {\n options.body = JSON.stringify(data);\n }\n // Allow plugins to alter the options.\n options = Plugins_1.default.pluginAlter('requestOptions', options, url);\n if (options.namespace || Formio.namespace) {\n opts.namespace = options.namespace || Formio.namespace;\n }\n const requestToken = options.headers['x-jwt-token'];\n const result = Plugins_1.default.pluginAlter('wrapFetchRequestPromise', Formio.fetch(url, options), { url, method, data, opts }).then((response) => {\n // Allow plugins to respond.\n response = Plugins_1.default.pluginAlter('requestResponse', response, Formio, data);\n if (!response.ok) {\n if (response.status === 440) {\n Formio.setToken(null, opts);\n Formio.events.emit('formio.sessionExpired', response.body || response);\n }\n else if (response.status === 401) {\n Formio.events.emit('formio.unauthorized', response.body || response);\n }\n else if (response.status === 416) {\n Formio.events.emit('formio.rangeIsNotSatisfiable', response.body || response);\n }\n else if (response.status === 504) {\n return Promise.reject(new Error('Network request failed'));\n }\n // Parse and return the error as a rejected promise to reject this promise\n return (response.headers.get('content-type').includes('application/json')\n ? response.json()\n : response.text())\n .then((error) => {\n return Promise.reject(error);\n });\n }\n // Handle fetch results\n const respToken = response.headers.get('x-jwt-token');\n // In some strange cases, the fetch library will return an x-jwt-token without sending\n // one to the server. This has even been debugged on the server to verify that no token\n // was introduced with the request, but the response contains a token. This is an Invalid\n // case where we do not send an x-jwt-token and get one in return for any GET request.\n let tokenIntroduced = false;\n if ((method === 'GET') &&\n !requestToken &&\n respToken &&\n !opts.external &&\n !url.includes('token=') &&\n !url.includes('x-jwt-token=')) {\n console.warn('Token was introduced in request.');\n tokenIntroduced = true;\n }\n if (response.status >= 200 &&\n response.status < 300 &&\n respToken &&\n respToken !== '' &&\n !tokenIntroduced) {\n Formio.setToken(respToken, Object.assign(Object.assign({}, opts), { fromCurrent: (opts.fromCurrent || !!requestToken) }));\n }\n // 204 is no content. Don't try to .json() it.\n if (response.status === 204) {\n return {};\n }\n const getResult = response.headers.get('content-type').includes('application/json')\n ? response.json()\n : response.text();\n return getResult.then((result) => {\n // Add some content-range metadata to the result here\n let range = response.headers.get('content-range');\n if (range && (0, lodash_1.isObject)(result)) {\n range = range.split('/');\n if (range[0] !== '*') {\n const skipLimit = range[0].split('-');\n result.skip = Number(skipLimit[0]);\n result.limit = skipLimit[1] - skipLimit[0] + 1;\n }\n result.serverCount = range[1] === '*' ? range[1] : Number(range[1]);\n }\n if (!opts.getHeaders) {\n return result;\n }\n const headers = {};\n response.headers.forEach((item, key) => {\n headers[key] = item;\n });\n // Return the result with the headers.\n return {\n result,\n headers,\n };\n });\n })\n .then((result) => {\n if (opts.getHeaders) {\n return result;\n }\n // Cache the response.\n if (method === 'GET') {\n Formio.cache[cacheKey] = result;\n }\n return Formio.cloneResponse(result);\n })\n .catch((err) => {\n if (err === 'Bad Token' && opts.noToken !== false) {\n Formio.setToken(null, opts);\n Formio.events.emit('formio.badToken', err);\n }\n if (err.message) {\n err = new Error(`Could not connect to API server (${err.message}): ${url}`);\n err.networkError = true;\n }\n if (method === 'GET') {\n delete Formio.cache[cacheKey];\n }\n return Promise.reject(err);\n });\n return result;\n }\n // Needed to maintain reverse compatability...\n static get token() {\n return Formio.tokens.formioToken || '';\n }\n // Needed to maintain reverse compatability...\n static set token(token) {\n Formio.tokens.formioToken = token || '';\n }\n static useSessionToken(options) {\n if (typeof localStorage === 'undefined') {\n return;\n }\n let namespace = options;\n if (typeof options === 'object') {\n options = options.namespace;\n }\n const tokenName = `${namespace || Formio.namespace || 'formio'}Token`;\n const token = localStorage.getItem(tokenName);\n if (token) {\n localStorage.removeItem(tokenName);\n sessionStorage.setItem(tokenName, token);\n }\n const userName = `${namespace || Formio.namespace || 'formio'}User`;\n const user = localStorage.getItem(userName);\n if (user) {\n localStorage.removeItem(userName);\n sessionStorage.setItem(userName, user);\n }\n localStorage.setItem('useSessionToken', 'true');\n }\n /**\n * Sets the JWT in storage to be used within an application.\n *\n * @param {string} token - The JWT token to set.\n * @param {object} options - Options as follows\n * @param {string} options.namespace - The namespace to save the token within. i.e. \"formio\"\n * @param {Formio} options.formio - The Formio instance.\n * @return {Promise<object>|void}\n */\n static setToken(token = '', opts = {}) {\n token = token || '';\n opts = (typeof opts === 'string') ? { namespace: opts } : opts || {};\n const tokenName = `${opts.namespace || Formio.namespace || 'formio'}Token`;\n if (!Formio.tokens) {\n Formio.tokens = {};\n }\n const storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage;\n if (!token) {\n if (!opts.fromUser) {\n opts.fromToken = true;\n Formio.setUser(null, opts);\n }\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.removeItem(tokenName);\n }\n catch (err) {\n browser_cookies_1.default.erase(tokenName, { path: '/' });\n }\n Formio.tokens[tokenName] = token;\n return Promise.resolve(null);\n }\n if (Formio.tokens[tokenName] !== token) {\n Formio.tokens[tokenName] = token;\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.setItem(tokenName, token);\n }\n catch (err) {\n browser_cookies_1.default.set(tokenName, token, { path: '/' });\n }\n }\n // Return or updates the current user\n return Formio.currentUser(opts.formio, opts);\n }\n /**\n * Returns the token set within the application for the user.\n *\n * @param {object} options - The options as follows.\n * @param {string} options.namespace - The namespace of the token you wish to fetch.\n * @param {boolean} options.decode - If you would like the token returned as decoded JSON.\n * @return {*}\n */\n static getToken(options) {\n options = (typeof options === 'string') ? { namespace: options } : options || {};\n const tokenName = `${options.namespace || Formio.namespace || 'formio'}Token`;\n const decodedTokenName = options.decode ? `${tokenName}Decoded` : tokenName;\n if (!Formio.tokens) {\n Formio.tokens = {};\n }\n if (Formio.tokens[decodedTokenName]) {\n return Formio.tokens[decodedTokenName];\n }\n try {\n const token = localStorage.getItem('useSessionToken')\n ? sessionStorage.getItem(tokenName)\n : localStorage.getItem(tokenName);\n Formio.tokens[tokenName] = token || '';\n if (options.decode) {\n Formio.tokens[decodedTokenName] = Formio.tokens[tokenName] ? (0, jwtDecode_1.jwtDecode)(Formio.tokens[tokenName]) : {};\n return Formio.tokens[decodedTokenName];\n }\n return Formio.tokens[tokenName];\n }\n catch (e) {\n Formio.tokens[tokenName] = browser_cookies_1.default.get(tokenName);\n return '';\n }\n }\n /**\n * Sets the current user within the application cache.\n *\n * @param {object} user - JSON object of the user you wish to set.\n * @param {object} options - Options as follows\n * @param {string} options.namespace - The namespace of the tokens\n */\n static setUser(user, opts = {}) {\n const userName = `${opts.namespace || Formio.namespace || 'formio'}User`;\n const storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage;\n if (!user) {\n if (!opts.fromToken) {\n opts.fromUser = true;\n Formio.setToken(null, opts);\n }\n // Emit an event on the cleared user.\n Formio.events.emit('formio.user', null);\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n return storage.removeItem(userName);\n }\n catch (err) {\n return browser_cookies_1.default.erase(userName, { path: '/' });\n }\n }\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.setItem(userName, JSON.stringify(user));\n }\n catch (err) {\n browser_cookies_1.default.set(userName, JSON.stringify(user), { path: '/' });\n }\n // Emit an event on the authenticated user.\n Formio.events.emit('formio.user', user);\n }\n /**\n * Returns the user JSON.\n *\n * @param {object} options - Options as follows\n * @param {string} namespace - The namespace of the tokens stored within this application.\n * @return {object} - The user object.\n */\n static getUser(options) {\n options = options || {};\n const userName = `${options.namespace || Formio.namespace || 'formio'}User`;\n try {\n return JSON.parse((localStorage.getItem('useSessionToken')\n ? sessionStorage\n : localStorage).getItem(userName) || '');\n }\n catch (e) {\n return JSON.parse(browser_cookies_1.default.get(userName));\n }\n }\n /**\n * Sets the BaseURL for the application.\n *\n * @description Every application developed using the JavaScript SDK must set both the {@link Formio.setBaseUrl} and\n * {@link Formio.setProjectUrl} methods. These two functions ensure that every URL passed into the constructor of this\n * class can determine the \"project\" context for which the application is running.\n *\n * Any Open Source server applications will set both the {@link Formio.setBaseUrl} and {@link Formio.setProjectUrl}\n * values will be the same value.\n *\n * ```ts\n * Formio.setBaseUrl('https://yourwebsite.com/forms');\n * Formio.setProjectUrl('https://yourwebsite.com/forms/project');\n *\n * // Now the Formio constructor will know what is the \"project\" and what is the form alias name. Without setBaseUrl\n * // and setProjectUrl, this would throw an error.\n *\n * const formio = new Formio('https://yourwebsite.com/forms/project/user');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {string} url - The URL of the Base API url.\n */\n static setBaseUrl(url) {\n Formio.baseUrl = url;\n if (!Formio.projectUrlSet) {\n Formio.projectUrl = url;\n }\n }\n /**\n * Returns the current base url described at {@link Formio.setBaseUrl}\n *\n * @return {string} - The base url of the application.\n */\n static getBaseUrl() {\n return Formio.baseUrl;\n }\n static setApiUrl(url) {\n return Formio.setBaseUrl(url);\n }\n static getApiUrl() {\n return Formio.getBaseUrl();\n }\n static setAppUrl(url) {\n console.warn('Formio.setAppUrl() is deprecated. Use Formio.setProjectUrl instead.');\n Formio.projectUrl = url;\n Formio.projectUrlSet = true;\n }\n /**\n * Sets the Project Url for the application. This is an important method that needs to be set for all applications. It\n * is documented @ {@link Formio.setBaseUrl}.\n *\n * @param {string} url - The project api url.\n */\n static setProjectUrl(url) {\n Formio.projectUrl = url;\n Formio.projectUrlSet = true;\n }\n /**\n * The Auth URL can be set to customize the authentication requests made from an application. By default, this is\n * just the same value as {@link Formio.projectUrl}\n *\n * @param {string} url - The authentication url\n */\n static setAuthUrl(url) {\n Formio.authUrl = url;\n }\n static getAppUrl() {\n console.warn('Formio.getAppUrl() is deprecated. Use Formio.getProjectUrl instead.');\n return Formio.projectUrl;\n }\n /**\n * Returns the Project url described at {@link Formio.setProjectUrl}\n *\n * @return {string|string} - The Project Url.\n */\n static getProjectUrl() {\n return Formio.projectUrl;\n }\n /**\n * Clears the runtime internal API cache.\n *\n * @description By default, the Formio class will cache all API requests in memory so that any subsequent requests\n * using GET method will return the cached results as long as the API URl is the same as what was cached previously.\n * This cache can be cleared using this method as follows.\n *\n * ```ts\n * Formio.clearCache();\n * ```\n *\n * Or, if you just wish to clear a single request, then the {@link Formio.request#options.ignoreCache} option can be\n * provided when making an API request as follows.\n *\n * ```ts\n * Formio.loadForm({}, {\n * ignoreCache: true\n * }).then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * Both of the following will ensure that a new request is made to the API server and that the results will not be\n * from the cached result.\n */\n static clearCache() {\n Formio.cache = {};\n }\n /**\n * Return the access information about a Project, such as the Role ID's for that project, and if the server is\n * configured to do so, the Form and Resource access configurations that the authenticated user has access to.\n *\n * @description This is useful for an application to determine the UI for a specific user to identify which forms they have\n * access to submit or read.\n *\n * @param {Formio} formio - The Formio instance.\n * @return {Promise<Response>}\n */\n static accessInfo(formio) {\n const projectUrl = formio ? formio.projectUrl : Formio.projectUrl;\n return Formio.makeRequest(formio, 'accessInfo', `${projectUrl}/access`);\n }\n /**\n * Returns an array of roles for the project, which includes the ID's and names of those roles.\n *\n * @param {Formio} formio - The Formio instance.\n * @return {Promise<Response>}\n */\n static projectRoles(formio) {\n const projectUrl = formio ? formio.projectUrl : Formio.projectUrl;\n return Formio.makeRequest(formio, 'projectRoles', `${projectUrl}/role`);\n }\n /**\n * Return the currentUser object. This will fetch the user from the server and respond with the Submission JSON\n * of that user object.\n *\n * @param {Formio} formio - The Formio instance\n * @param {object} options - The options passed to {@link Formio.getUser}\n * @return {Promise<R>|*}\n */\n static currentUser(formio, options = {}) {\n let authUrl = Formio.authUrl;\n if (!authUrl) {\n authUrl = formio ? formio.projectUrl : (Formio.projectUrl || Formio.baseUrl);\n }\n authUrl += '/current';\n if (!options.ignoreCache || options.fromCurrent) {\n const user = Formio.getUser(options);\n if (user) {\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', Promise.resolve(user), {\n url: authUrl,\n method: 'GET',\n options\n });\n }\n }\n const token = Formio.getToken(options);\n if ((!options || !options.external) && !token) {\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', Promise.resolve(null), {\n url: authUrl,\n method: 'GET',\n options\n });\n }\n options.fromCurrent = true;\n return Formio.makeRequest(formio, 'currentUser', authUrl, 'GET', null, options)\n .then((response) => {\n Formio.setUser(response, options);\n return response;\n });\n }\n /**\n * Performs a logout of the Form.io application. This will reset all cache, as well as make a request to the logout\n * endpoint of the Form.io api platform.\n *\n * @param {Formio} formio - A Formio instance.\n * @param {object} options - Options passed to both {@link Formio.setToken} as well as {@link Formio.setUser}\n * @return {Promise<Response>}\n */\n static logout(formio, options = {}) {\n options.formio = formio;\n const projectUrl = Formio.authUrl ? Formio.authUrl : (formio ? formio.projectUrl : Formio.baseUrl);\n const logout = () => {\n Formio.setToken(null, options);\n Formio.setUser(null, options);\n Formio.clearCache();\n localStorage.removeItem('useSessionToken');\n };\n return Formio.makeRequest(formio, 'logout', `${projectUrl}/logout`)\n .then(function (result) {\n logout();\n if (result.shouldRedirect && result.url) {\n window.location.href = result.url;\n }\n return result;\n })\n .catch(function (err) {\n logout();\n throw err;\n });\n }\n /**\n * Returns the query passed to a page in JSON object format.\n *\n * @description For example, lets say you visit your application using\n * the url as follows.\n *\n * ```\n * https://yourapplication.com/?token=23423423423&username=Joe\n * ```\n *\n * The following code will provide your application with the following.\n *\n * ```ts\n * const query Formio.pageQuery();\n * console.log(query.token); // Will print 23423423423\n * console.log(query.username); // Will print Joe\n * ```\n *\n * @return {{}} - A JSON object representation of the query that was passed to the URL of an application.\n */\n static pageQuery() {\n const pageQuery = {};\n pageQuery.paths = [];\n const hashes = location.hash.substr(1).replace(/\\?/g, '&').split('&');\n let parts = [];\n location.search.substr(1).split('&').forEach(function (item) {\n parts = item.split('=');\n if (parts.length > 1) {\n pageQuery[parts[0]] = parts[1] && decodeURIComponent(parts[1]);\n }\n });\n hashes.forEach(function (item) {\n parts = item.split('=');\n if (parts.length > 1) {\n pageQuery[parts[0]] = parts[1] && decodeURIComponent(parts[1]);\n }\n else if (item.indexOf('/') === 0) {\n pageQuery.paths = item.substr(1).split('/');\n }\n });\n return pageQuery;\n }\n /**\n * Much like {@link Formio.currentUser}, but instead automatically injects the Bearer tokens into the headers to\n * perform a Token swap of the OAuth token which will then return the JWT token for that user.\n *\n * @param {Formio} formio - The Formio instance\n * @param {string} token - An OAuth Bearer token to use for a token swap between the OAuth provider and Form.io\n * @return {Promise<R>|*}\n */\n static oAuthCurrentUser(formio, token) {\n return Formio.currentUser(formio, {\n external: true,\n headers: {\n Authorization: `Bearer ${token}`\n }\n });\n }\n static oauthLogoutURI(uri, options) {\n options = (typeof options === 'string') ? { namespace: options } : options || {};\n const logoutURIName = `${options.namespace || Formio.namespace || 'formio'}LogoutAuthUrl`;\n Formio.tokens[logoutURIName];\n localStorage.setItem(logoutURIName, uri);\n return Formio.tokens[logoutURIName];\n }\n /**\n * Perform a SAML initialization.\n *\n * @description Typically, you would use the {@link Formio.ssoInit} method to perform this function\n * since this method is an alias for the following.\n *\n * ```ts\n * Formio.samlInit();\n * Formio.ssoInit('saml'); // This is the exact same thing as calling Formio.samlInit\n * ```\n *\n * This method will return false if the process is just starting. The code below is a typical block of code that is\n * used to automatically trigger the SAML authentication process within your application using a Button component.\n *\n * ```ts\n * if (Formio.pageQuery().saml) {\n * const sso = Formio.samlInit();\n * if (sso) {\n * sso.then((user) => {\n * // The SSO user is now loaded!\n * console.log(user);\n * });\n * }\n * }\n * ```\n *\n * You can then place the following code withiin the \"Custom\" action of a Button component on your form.\n *\n * ```ts\n * Formio.samlInit();\n * ```\n *\n * Now when you click on this button, it will start the handshake process with SAML, and once it returns, will pass\n * a \"saml\" query parameter back to your application which will execute the code to load the current user from SAML.\n *\n * @param {object} options - Options to pass to the SAML initialization process.\n * @param {string} options.relay - The URL that will be used as the authentication \"relay\" that occurs during a SAML handshake process.\n * @return {boolean|Promise<Object>|void}\n */\n static samlInit(options = {}) {\n const query = Formio.pageQuery();\n if (query.saml) {\n Formio.setUser(null);\n const retVal = Formio.setToken(query.saml);\n let uri = window.location.toString();\n uri = uri.substring(0, uri.indexOf('?'));\n if (window.location.hash) {\n uri += window.location.hash;\n }\n window.history.replaceState({}, document.title, uri);\n return retVal;\n }\n // Set the relay if not provided.\n if (!options.relay) {\n options.relay = window.location.href;\n }\n // go to the saml sso endpoint for this project.\n const authUrl = Formio.authUrl || Formio.projectUrl;\n window.location.href = `${authUrl}/saml/sso?relay=${encodeURI(options.relay)}`;\n return false;\n }\n /**\n * Perform an Okta Authentication process using the {@link https://developer.okta.com/code/javascript/okta_auth_sdk|Okta SDK}.\n *\n * @description This method does require that you first include the Okta JavaScript SDK within your application as follows.\n *\n * First you need to include the Okta Authentication script.\n *\n * ```html\n * <script src=\"https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/2.0.1/okta-auth-js.min.js\" type=\"text/javascript\"></script>\n * ```\n *\n * Then you can call this method as follows.\n *\n * ```ts\n * Formio.oktaInit();\n * ```\n *\n * @param {object} options - Options that are passed directly to the {@link https://github.com/okta/okta-auth-js#configuration-reference|Okta SDK constructor}\n * @param {constructor} options.OktaAuth - If the OktaAuth constructor is not provided global to the application, it can be provided to this method using this property.\n * @param {Formio} options.formio - The Formio instance.\n * @param {Array<string>} options.scopes - Scopes that are passed to the {@link https://github.com/okta/okta-auth-js#tokengetwithredirectoptions|getWithRedirect} method from the Okta SDK.\n * @return {Promise<Object>}\n */\n static oktaInit(options = {}) {\n if (typeof OktaAuth !== undefined) {\n options.OktaAuth = OktaAuth;\n }\n if (typeof options.OktaAuth === undefined) {\n const errorMessage = 'Cannot find OktaAuth. Please include the Okta JavaScript SDK within your application. See https://developer.okta.com/code/javascript/okta_auth_sdk for an example.';\n console.warn(errorMessage);\n return Promise.reject(errorMessage);\n }\n return new Promise((resolve, reject) => {\n const Okta = options.OktaAuth;\n delete options.OktaAuth;\n const authClient = new Okta(options);\n authClient.tokenManager.get('accessToken')\n .then((accessToken) => {\n if (accessToken) {\n resolve(Formio.oAuthCurrentUser(options.formio, accessToken.accessToken));\n }\n else if (location.hash) {\n authClient.token.parseFromUrl()\n .then((token) => {\n authClient.tokenManager.add('accessToken', token);\n resolve(Formio.oAuthCurrentUser(options.formio, token.accessToken));\n })\n .catch((err) => {\n console.warn(err);\n reject(err);\n });\n }\n else {\n authClient.token.getWithRedirect({\n responseType: 'token',\n scopes: options.scopes\n });\n resolve(false);\n }\n })\n .catch((error) => {\n reject(error);\n });\n });\n }\n /**\n * A common static method to trigger any SSO processes. This method is really just an alias for other static methods.\n *\n * @param {('saml'|'okta')} type - The type of SSO to trigger. 'saml' is an alias for {@link Formio.samlInit}, and 'okta' is an alias for {@link Formio.oktaInit}.\n * @param {object} options - Options to pass to the specific sso methods\n * @return {*|Promise<Object>|boolean|void}\n */\n static ssoInit(type, options = {}) {\n switch (type) {\n case 'saml':\n return Formio.samlInit(options);\n case 'okta':\n return Formio.oktaInit(options);\n default:\n console.warn('Unknown SSO type');\n return Promise.reject('Unknown SSO type');\n }\n }\n /**\n * Lazy load a remote library dependency.\n *\n * @description This is useful for components that wish to lazy load a required library\n * by adding that library to the <scripts> section of the HTML webpage, and then provide a promise that will resolve\n * when the library becomes available for use.\n *\n * @example Load Google Maps API.\n * ```ts\n * Formio.requireLibrary('googleMaps', 'google.maps.Map', 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap', true).then(() => {\n * // Once the promise resolves, the following can now be used within your application.\n * const map = new google.maps.Map(document.getElementById(\"map\"), {...});\n * });\n * ```\n *\n * @param {string} name - The internal name to give to the library you are loading. This is useful for caching the library for later use.\n * @param {string} property - The name of the global property that will be added to the global namespace once the library has been loaded. This is used to check to see if the property exists before resolving the promise that the library is ready for use.\n * @param {string} src - The URL of the library to lazy load.\n * @param {boolean} polling - Determines if polling should be used to determine if they library is ready to use. If set to false, then it will rely on a global callback called ${name}Callback where \"name\" is the first property passed to this method. When this is called, that will indicate when the library is ready. In most cases, you will want to pass true to this parameter to initiate a polling method to check for the library availability in the global context.\n * @return {Promise<object>} - A promise that will resolve when the plugin is ready to be used.\n */\n static requireLibrary(name, property, src, polling = false, onload) {\n if (!Formio.libraries.hasOwnProperty(name)) {\n Formio.libraries[name] = {};\n Formio.libraries[name].ready = new Promise((resolve, reject) => {\n Formio.libraries[name].resolve = resolve;\n Formio.libraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = () => Formio.libraries[name].resolve();\n }\n // See if the plugin already exists.\n const plugin = (0, lodash_1.get)(window, property);\n if (plugin) {\n Formio.libraries[name].resolve(plugin);\n }\n else {\n src = Array.isArray(src) ? src : [src];\n src.forEach((lib) => {\n let attrs = {};\n let elementType = '';\n if (typeof lib === 'string') {\n lib = {\n type: 'script',\n src: lib,\n };\n }\n switch (lib.type) {\n case 'script':\n elementType = 'script';\n attrs = {\n src: lib.src,\n type: 'text/javascript',\n defer: true,\n async: true,\n referrerpolicy: 'origin',\n };\n break;\n case 'styles':\n elementType = 'link';\n attrs = {\n href: lib.src,\n rel: 'stylesheet',\n };\n break;\n }\n // Add the script to the top of the page.\n const element = document.createElement(elementType);\n if (element.setAttribute) {\n for (const attr in attrs) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n if (onload) {\n element.addEventListener('load', () => {\n Formio.libraries[name].loaded = true;\n onload(Formio.libraries[name].ready);\n });\n }\n const { head } = document;\n if (head) {\n head.appendChild(element);\n }\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n const interval = setInterval(() => {\n const plugin = (0, lodash_1.get)(window, property);\n if (plugin) {\n clearInterval(interval);\n Formio.libraries[name].resolve(plugin);\n }\n }, 200);\n }\n }\n }\n const lib = Formio.libraries[name];\n return onload && lib.loaded ? onload(lib.ready) : lib.ready;\n }\n /**\n * Determines if a lazy loaded library is ready to be used.\n *\n * @description Example: Let's assume that the example provided at {@link Formio.requireLibrary} was used elsewhere in your application.\n * You could now use the following within a separate place that will also resolve once the library is ready to be used.\n *\n * ```js\n * Formio.libraryReady('googleMaps').then(() => {\n * // Once the promise resolves, the following can now be used within your application.\n * const map = new google.maps.Map(document.getElementById(\"map\"), {...});\n * });\n * ```\n *\n * @param {string} name - The name of the library to check.\n * @return {Promise<object>} - A promise that will resolve when the library is ready to be used.\n */\n static libraryReady(name) {\n if (Formio.libraries.hasOwnProperty(name) &&\n Formio.libraries[name].ready) {\n return Formio.libraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n }\n /**\n * Clones the response from the API so that it cannot be mutated.\n *\n * @param response\n */\n static cloneResponse(response) {\n const copy = (0, fastCloneDeep_1.fastCloneDeep)(response);\n if (Array.isArray(response)) {\n copy.skip = response.skip;\n copy.limit = response.limit;\n copy.serverCount = response.serverCount;\n }\n return copy;\n }\n /**\n * Sets the project path type.\n *\n * @param type\n */\n static setPathType(type) {\n if (typeof type === 'string') {\n Formio.pathType = type;\n }\n }\n /**\n * Gets the project path type.\n */\n static getPathType() {\n return Formio.pathType;\n }\n}\nexports.Formio = Formio;\n/**\n * The base API url of the Form.io Platform. Example: https://api.form.io\n */\nFormio.baseUrl = 'https://api.form.io';\n/**\n * The project API url of the Form.io Project. Example: https://examples.form.io\n */\nFormio.projectUrl = '';\n/**\n * The project url to use for Authentication.\n */\nFormio.authUrl = '';\n/**\n * Set to true if the project url has been established with ```Formio.setProjectUrl()```\n */\nFormio.projectUrlSet = false;\n/**\n * The Form.io API Cache. This ensures that requests to the same API endpoint are cached.\n */\nFormio.cache = {};\n/**\n * The namespace used to save the Form.io Token's and variables within an application.\n */\nFormio.namespace = '';\n/**\n * Handles events fired within this SDK library.\n */\nFormio.events = new eventemitter3_1.default();\n/**\n * Stores all of the libraries lazy loaded with ```Formio.requireLibrary``` method.\n */\nFormio.libraries = {};\n/**\n * A direct interface to the Form.io fetch polyfill.\n */\nFormio.fetch = fetch;\n/**\n * A direct interface to the Form.io fetch Headers polyfill.\n */\nFormio.Headers = Headers;\n/**\n * All of the auth tokens for this session.\n */\nFormio.tokens = {};\n/**\n * The version of this library.\n */\nFormio.version = '---VERSION---';\n/**\n * The global options for the Formio library.\n */\nFormio.options = {};\n// Add Plugin methods.\nFormio.plugins = Plugins_1.default.plugins;\nFormio.deregisterPlugin = Plugins_1.default.deregisterPlugin;\nFormio.registerPlugin = Plugins_1.default.registerPlugin;\nFormio.getPlugin = Plugins_1.default.getPlugin;\nFormio.pluginWait = Plugins_1.default.pluginWait;\nFormio.pluginGet = Plugins_1.default.pluginGet;\nFormio.pluginAlter = Plugins_1.default.pluginAlter;\n// Adds Formio to the Plugins Interface.\nPlugins_1.default.Formio = Formio;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/sdk/Formio.js?");
|
|
4999
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.Formio = exports.FormioPathType = void 0;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst fastCloneDeep_1 = __webpack_require__(/*! ../utils/fastCloneDeep */ \"./node_modules/@formio/core/lib/utils/fastCloneDeep.js\");\nconst lodash_1 = __webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\");\nconst formUtil_1 = __webpack_require__(/*! ../utils/formUtil */ \"./node_modules/@formio/core/lib/utils/formUtil.js\");\nconst jwtDecode_1 = __webpack_require__(/*! ../utils/jwtDecode */ \"./node_modules/@formio/core/lib/utils/jwtDecode.js\");\nconst eventemitter3_1 = __importDefault(__webpack_require__(/*! eventemitter3 */ \"./node_modules/eventemitter3/index.js\"));\nconst browser_cookies_1 = __importDefault(__webpack_require__(/*! browser-cookies */ \"./node_modules/browser-cookies/src/browser-cookies.js\"));\nconst { fetch, Headers } = (0, fetch_ponyfill_1.default)();\nconst Plugins_1 = __importDefault(__webpack_require__(/*! ./Plugins */ \"./node_modules/@formio/core/lib/sdk/Plugins.js\"));\n/**\n * The different path types for a project.\n */\nvar FormioPathType;\n(function (FormioPathType) {\n FormioPathType[\"Subdirectories\"] = \"Subdirectories\";\n FormioPathType[\"Subdomains\"] = \"Subdomains\";\n})(FormioPathType || (exports.FormioPathType = FormioPathType = {}));\n/**\n * The Formio interface class. This is a minimalistic API library that allows you to work with the Form.io API's within JavaScript.\n *\n * ## Usage\n * Creating an instance of Formio is simple, and takes only a path (URL String). The path can be different, depending on the desired output.\n * The Formio instance can also access higher level operations, depending on how granular of a path you start with.\n *\n * ```ts\n * var formio = new Formio(<endpoint>, [options]);\n * ```\n *\n * Where **endpoint** is any valid API endpoint within Form.io. These URL's can provide a number of different methods depending on the granularity of the endpoint. This allows you to use the same interface but have access to different methods depending on how granular the endpoint url is.\n * **options** is defined within the {link Formio.constructor} documentation.\n *\n * Here is an example of how this library can be used to load a form JSON from the Form.io API's\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n */\nclass Formio {\n /* eslint-disable max-statements */\n /**\n * @constructor\n * @param {string} path - A project, form, and submission API Url.\n * @param {FormioOptions} options - Available options to configure the Javascript API.\n */\n constructor(path, options = {}) {\n this.path = path;\n this.options = options;\n /**\n * The base API url of the Form.io Platform. Example: https://api.form.io\n */\n this.base = '';\n /**\n * The Projects Endpoint derived from the provided source.\n *\n * @example https://api.form.io/project\n */\n this.projectsUrl = '';\n /**\n * A specific project endpoint derived from the provided source.\n *\n * @example https://examples.form.io\n */\n this.projectUrl = '';\n /**\n * The Project ID found within the provided source.\n */\n this.projectId = '';\n /**\n * A specific Role URL provided the source.\n *\n * @example https://examples.form.io/role/2342343234234234\n */\n this.roleUrl = '';\n /**\n * The roles endpoint derived from the provided source.\n *\n * @example https://examples.form.io/role\n */\n this.rolesUrl = '';\n /**\n * The roleID derieved from the provided source.\n */\n this.roleId = '';\n /**\n * A specific form url derived from the provided source.\n *\n * @example https://examples.form.io/example\n */\n this.formUrl = '';\n /**\n * The forms url derived from the provided source.\n *\n * @example https://example.form.io/form\n */\n this.formsUrl = '';\n /**\n * The Form ID derived from the provided source.\n */\n this.formId = '';\n /**\n * The submissions URL derived from the provided source.\n *\n * @example https://examples.form.io/example/submission\n */\n this.submissionsUrl = '';\n /**\n * A specific submissions URL derived from a provided source.\n *\n * @example https://examples.form.io/example/submission/223423423423\n */\n this.submissionUrl = '';\n /**\n * The submission ID provided a submission url.\n */\n this.submissionId = '';\n /**\n * The actions url provided a form url as the source.\n *\n * @example https://examples.form.io/example/action\n */\n this.actionsUrl = '';\n /**\n * The Action ID derived from a provided Action url.\n */\n this.actionId = '';\n /**\n * A specific action api endoint.\n */\n this.actionUrl = '';\n this.vsUrl = '';\n this.vId = '';\n this.vUrl = '';\n /**\n * The query string derived from the provided src url.\n */\n this.query = '';\n /**\n * If this is a non-project url, such is the case for Open Source API.\n */\n this.noProject = false;\n // Ensure we have an instance of Formio.\n if (!(this instanceof Formio)) {\n return new Formio(path);\n }\n if (options.useSessionToken) {\n Formio.useSessionToken(options);\n }\n if (options.hasOwnProperty('base') && options.base) {\n this.base = options.base;\n }\n else if (Formio.baseUrl) {\n this.base = Formio.baseUrl;\n }\n else if (window && window.location) {\n const match = window.location.href.match(/http[s]?:\\/\\/api./);\n this.base = match ? match[0] : window.location.origin;\n }\n if (!path) {\n // Allow user to create new projects if this was instantiated without\n // a url\n this.projectUrl = Formio.projectUrl || `${this.base}/project`;\n this.projectsUrl = `${this.base}/project`;\n this.projectId = '';\n this.query = '';\n return;\n }\n if (options.hasOwnProperty('project') && options.project) {\n this.projectUrl = options.project;\n }\n const project = this.projectUrl || Formio.projectUrl;\n const projectRegEx = /(^|\\/)(project)($|\\/[^/]+)/;\n const isProjectUrl = (path.search(projectRegEx) !== -1);\n // The baseURL is the same as the projectUrl, and does not contain \"/project/MONGO_ID\" in\n // its domain. This is almost certainly against the Open Source server.\n if (project && this.base === project && !isProjectUrl) {\n this.noProject = true;\n this.projectUrl = this.base;\n }\n // Normalize to an absolute path.\n if ((path.indexOf('http') !== 0) && (path.indexOf('//') !== 0)) {\n path = this.base + path;\n }\n const hostparts = this.getUrlParts(path);\n let hostName = '';\n let parts = [];\n if (hostparts) {\n hostName = hostparts[1] + hostparts[2];\n path = hostparts.length > 3 ? hostparts[3] : '';\n const queryparts = path.split('?');\n if (queryparts.length > 1) {\n path = queryparts[0];\n this.query = `?${queryparts[1]}`;\n }\n }\n // Register a specific path.\n const registerPath = (name, base) => {\n this[`${name}sUrl`] = `${base}/${name}`;\n const regex = new RegExp(`/${name}/([^/]+)`);\n if (path && path.search(regex) !== -1) {\n parts = path.match(regex);\n this[`${name}Url`] = parts ? (base + parts[0]) : '';\n this[`${name}Id`] = (parts.length > 1) ? parts[1] : '';\n base += parts[0];\n }\n return base;\n };\n // Register an array of items.\n const registerItems = (items, base, staticBase) => {\n for (const i in items) {\n if (items.hasOwnProperty(i)) {\n const item = items[i];\n if (Array.isArray(item)) {\n registerItems(item, base, true);\n }\n else {\n const newBase = registerPath(item, base);\n base = staticBase ? base : newBase;\n }\n }\n }\n };\n if (!this.projectUrl || (this.projectUrl === this.base)) {\n // If a project uses Subdirectories path type, we need to specify a projectUrl\n if (!this.projectUrl && !isProjectUrl && Formio.pathType === 'Subdirectories') {\n const regex = `^${hostName.replace(/\\//g, '\\\\/')}.[^/]+`;\n const match = project.match(new RegExp(regex));\n this.projectUrl = match ? match[0] : hostName;\n }\n else {\n this.projectUrl = hostName;\n }\n }\n // Check if we have a specified path type.\n let isNotSubdomainType = false;\n if (Formio.pathType) {\n isNotSubdomainType = Formio.pathType !== 'Subdomains';\n }\n if (!this.noProject) {\n // Determine the projectUrl and projectId\n if (isProjectUrl) {\n // Get project id as project/:projectId.\n registerItems(['project'], hostName);\n path = path.replace(projectRegEx, '');\n }\n else if (hostName === this.base) {\n // Get project id as first part of path (subdirectory).\n if (hostparts && hostparts.length > 3 && path.split('/').length > 1) {\n const isFile = path.match(/.json/);\n const pathParts = path.split('/');\n if (isFile) {\n this.projectUrl = hostName;\n }\n else {\n pathParts.shift(); // Throw away the first /.\n const projectId = pathParts.shift();\n if (projectId) {\n this.projectId = projectId;\n path = `/${pathParts.join('/')}`;\n this.projectUrl = `${hostName}/${this.projectId}`;\n }\n }\n }\n }\n else {\n // Get project id from subdomain.\n if (hostparts && hostparts.length > 2 && (hostparts[2].split('.').length > 2 || hostName.includes('localhost')) && !isNotSubdomainType) {\n this.projectUrl = hostName;\n this.projectId = hostparts[2].split('.')[0];\n }\n }\n this.projectsUrl = this.projectsUrl || `${this.base}/project`;\n }\n // Configure Role urls and role ids.\n registerItems(['role'], this.projectUrl);\n // Configure Form urls and form ids.\n if (/(^|\\/)(form)($|\\/)/.test(path)) {\n registerItems(['form', ['submission', 'action', 'v']], this.projectUrl);\n }\n else {\n const subRegEx = new RegExp('/(submission|action|v)($|/.*)');\n const subs = path.match(subRegEx);\n if ((subs && (subs.length > 1))) {\n this.pathType = subs[1];\n }\n path = path.replace(subRegEx, '');\n path = path.replace(/\\/$/, '');\n this.formsUrl = `${this.projectUrl}/form`;\n this.formUrl = path ? this.projectUrl + path : '';\n this.formId = path.replace(/^\\/+|\\/+$/g, '');\n const items = ['submission', 'action', 'v'];\n for (const i in items) {\n if (items.hasOwnProperty(i)) {\n const item = items[i];\n this[`${item}sUrl`] = `${this.projectUrl + path}/${item}`;\n if ((this.pathType === item) && subs && (subs.length > 2) && subs[2]) {\n this[`${item}Id`] = subs[2].replace(/^\\/+|\\/+$/g, '');\n this[`${item}Url`] = this.projectUrl + path + subs[0];\n }\n }\n }\n }\n // Set the app url if it is not set.\n if (!Formio.projectUrlSet) {\n Formio.projectUrl = this.projectUrl;\n }\n }\n /* eslint-enable max-statements */\n /**\n * Deletes a remote resource of any provided type.\n *\n * @param {string} type - The type of resource to delete. \"submission\", \"form\", etc.\n * @param {object} options - The options passed to {@link Formio.request}\n * @return {Promise<Response>}\n */\n delete(type, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n if (!this[_id]) {\n return Promise.reject('Nothing to delete');\n }\n Formio.cache = {};\n return this.makeRequest(type, this[_url], 'delete', null, opts);\n }\n /**\n * Returns the index (array of records) for any provided type.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} query - A query object to pass to the request.\n * @param {object} query.params - A map (key-value pairs) of URL query parameters to add to the url.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n index(type, query, opts) {\n const _url = `${type}Url`;\n query = query || '';\n if (query && (0, lodash_1.isObject)(query)) {\n query = `?${Formio.serialize(query.params)}`;\n }\n return this.makeRequest(type, this[_url] + query, 'get', null, opts);\n }\n /**\n * Save a document record using \"upsert\". If the document does not exist, it will be created, if the _id is provided,\n * it will be updated.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} data - The resource data object.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n save(type, data, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n const method = (this[_id] || data._id) ? 'put' : 'post';\n let reqUrl = this[_id] ? this[_url] : this[`${type}sUrl`];\n if (!this[_id] && data._id && (method === 'put') && !reqUrl.includes(data._id)) {\n reqUrl += `/${data._id}`;\n }\n Formio.cache = {};\n return this.makeRequest(type, reqUrl + this.query, method, data, opts);\n }\n /**\n * @summary Load (GET) a document record.\n *\n * @param {string} type - The type of resource to fetch the index of. \"submission\", \"form\", etc.\n * @param {object} query - A query object to pass to the request.\n * @param {object} query.params - A map (key-value pairs) of URL query parameters to add to the url.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n load(type, query, opts) {\n const _id = `${type}Id`;\n const _url = `${type}Url`;\n if (query && (0, lodash_1.isObject)(query)) {\n query = Formio.serialize(query.params);\n }\n if (query) {\n query = this.query ? (`${this.query}&${query}`) : (`?${query}`);\n }\n else {\n query = this.query;\n }\n if (!this[_id]) {\n return Promise.reject(`Missing ${_id}`);\n }\n let url = this[_url] + query;\n if (type === 'form' && !isNaN(parseInt(this.vId))) {\n url += url.indexOf('?') === -1 ? '?' : '&';\n url += `formRevision=${this.vId}`;\n }\n return this.makeRequest(type, url, 'get', null, opts);\n }\n /**\n * @summary Call {@link Formio.makeRequest} for this Formio instance.\n *\n * @param {string} type - The request resource type. \"submission\", \"form\", etc.\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>}\n */\n makeRequest(type, url, method, data, opts) {\n return Formio.makeRequest(this, type, url, method, data, opts);\n }\n /**\n * @summary Loads a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadProject().then((project) => {\n * console.log(project);\n * });\n * ```\n *\n * @param {object} query - Query parameters to pass to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadProject(query, opts) {\n return this.load('project', query, opts);\n }\n /**\n * Saves or Updates a project.\n *\n * ### Create a new project\n * ```ts\n * const formio = new Formio();\n * formio.saveProject({\n * title: 'My Project',\n * path: 'myproject',\n * name: 'myproject'\n * });\n * ```\n *\n * ### Update an existing project\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadProject().then((project) => {\n * project.title = 'Title changed';\n * formio.saveProject(project).then(() => {\n * console.log('Done saving project!');\n * });\n * });\n * ```\n *\n * @param {object} data - The project JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveProject(data, opts) {\n return this.save('project', data, opts);\n }\n /**\n * Deletes a project\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.deleteProject();\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n deleteProject(opts) {\n return this.delete('project', opts);\n }\n /**\n * Loads a list of all projects.\n *\n * ```ts\n * Formio.loadProjects().then((projects) => {\n * console.log(projects);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {*}\n */\n static loadProjects(query, opts) {\n query = query || '';\n if ((0, lodash_1.isObject)(query)) {\n query = `?${Formio.serialize(query.params)}`;\n }\n return Formio.makeStaticRequest(`${Formio.baseUrl}/project${query}`, 'GET', null, opts);\n }\n /**\n * Loads a role within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/role/234234234234');\n * formio.loadRole().then((role) => {\n * console.log(role);\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadRole(opts) {\n return this.load('role', null, opts);\n }\n /**\n * Create a new or Update an existing role within a project.\n *\n * ### Create new Role example\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.saveRole({\n * title: 'Employee',\n * description: 'A person who belongs to a company.'\n * }).then((role) => {\n * console.log(role);\n * });\n * ```\n *\n * ### Update existing role example\n * ```ts\n * const formio = new Formio('https://examples.form.io/role/234234234234234');\n * formio.loadRole().then((role) => {\n * role.title = 'Manager';\n * formio.saveRole(role).then(() => {\n * console.log('DONE');\n * });\n * });\n * ```\n *\n * @param {object} role - The Role JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveRole(data, opts) {\n return this.save('role', data, opts);\n }\n /**\n * Deletes a role within a project.\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteRole(opts) {\n return this.delete('role', opts);\n }\n /**\n * Load all roles within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadRoles().then((roles) => {\n * console.log(roles);\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadRoles(opts) {\n return this.index('roles', null, opts);\n }\n /**\n * Loads a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n loadForm(query, opts) {\n return this.load('form', query, opts)\n .then((currentForm) => {\n // Check to see if there isn't a number in vId.\n if (!currentForm.revisions || isNaN(parseInt(this.vId))) {\n return currentForm;\n }\n // If a submission already exists but form is marked to load current version of form.\n if (currentForm.revisions === 'current' && this.submissionId) {\n return currentForm;\n }\n // eslint-disable-next-line eqeqeq\n if (currentForm._vid == this.vId || currentForm.revisionId === this.vId) {\n return currentForm;\n }\n // If they specified a revision form, load the revised form components.\n if (query && (0, lodash_1.isObject)(query)) {\n query = Formio.serialize(query.params);\n }\n if (query) {\n query = this.query ? (`${this.query}&${query}`) : (`?${query}`);\n }\n else {\n query = this.query;\n }\n return this.makeRequest('form', this.vUrl + query, 'get', null, opts)\n .then((revisionForm) => {\n currentForm._vid = revisionForm._vid;\n currentForm.components = revisionForm.components;\n currentForm.settings = revisionForm.settings;\n currentForm.revisionId = revisionForm.revisionId;\n // Using object.assign so we don't cross polinate multiple form loads.\n return Object.assign({}, currentForm);\n })\n // If we couldn't load the revision, just return the original form.\n .catch(() => Object.assign({}, currentForm));\n });\n }\n /**\n * Create or Update a specific form.\n *\n * ### Create form example\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.saveForm({\n * title: 'Employee',\n * type: 'resource',\n * path: 'employee',\n * name: 'employee',\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name'\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name'\n * }\n * ]\n * });\n * ```\n *\n * ### Update a form example\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadForm().then((form) => {\n * form.title = 'Changed Title';\n * formio.saveForm(form).then(() => {\n * console.log('DONE!!!');\n * });\n * });\n * ```\n *\n * @param {object} data - The Form JSON to create or update.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveForm(data, opts) {\n return this.save('form', data, opts);\n }\n /**\n * Deletes a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.deleteForm().then(() => {\n * console.log('Deleted!');\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteForm(opts) {\n return this.delete('form', opts);\n }\n /**\n * Loads all forms within a project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.loadForms().then((forms) => {\n * console.log(forms);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadForms(query, opts) {\n return this.index('forms', query, opts);\n }\n /**\n * Loads a specific submissionn.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/23423423423423423');\n * formio.loadSubmission().then((submission) => {\n * console.log(submission);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n loadSubmission(query, opts) {\n return this.load('submission', query, opts)\n .then((submission) => {\n this.vId = submission._frid || submission._fvid;\n this.vUrl = `${this.formUrl}/v/${this.vId}`;\n return submission;\n });\n }\n /**\n * Creates a new or Updates an existing submission.\n *\n * ### Create a new submission\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.saveSubmission({\n * data: {\n * firstName: 'Joe',\n * lastName: 'Smith'\n * }\n * }).then((submission) => {\n * // This will now be the complete submission object saved on the server.\n * console.log(submission);\n * });\n * ```\n *\n * ### Update an existing submission\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/23423423423423423');\n * formio.loadSubmission().then((submission) => {\n * submission.data.lastName = 'Thompson';\n * formio.saveSubmission(submission).then(() => {\n * console.log('DONE');\n * });\n * });\n * ```\n *\n * @param {object} data - The submission JSON object.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveSubmission(data, opts) {\n if (!isNaN(parseInt(this.vId)) && !data._fvid) {\n data._fvid = this.vId;\n }\n return this.save('submission', data, opts);\n }\n /**\n * Deletes a submission.\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteSubmission(opts) {\n return this.delete('submission', opts);\n }\n /**\n * Loads all submissions within a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadSubmissions({\n * params: {\n * limit: 25,\n * 'data.lastName__regex': 'smith'\n * }\n * }).then((submissions) => {\n * // Should print out 25 submissions where the last name contains \"smith\".\n * console.log(submissions);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadSubmissions(query, opts) {\n return this.index('submissions', query, opts);\n }\n /**\n * Loads a form action.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.loadAction().then((action) => {\n * console.log(action);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n loadAction(query, opts) {\n return this.load('action', query, opts);\n }\n /**\n * Create a new or update an existing action.\n *\n * ### Create a new action for a form.\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.saveAction({\n * data: {\n * name: 'webhook',\n * title: 'Webhook Action',\n * method: ['create', 'update', 'delete'],\n * handler: ['after'],\n * condition: {},\n * settings: {\n * url: 'https://example.com',\n * headers: [{}],\n * block: false,\n * forwardHeaders: false\n * }\n * }\n * }).then((action) => {\n * console.log(action);\n * });\n * ```\n *\n * ### Update an action\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.loadAction().then((action) => {\n * action.title = 'Updated title';\n * formio.saveAction(action).then(() => {\n * console.log('Done!');\n * });\n * });\n * ```\n *\n * @param {object} data - The action JSON\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Object>}\n */\n saveAction(data, opts) {\n return this.save('action', data, opts);\n }\n /**\n * Delete an action\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/action/234234234234');\n * formio.deleteAction().then(() => {\n * console.log('Action was deleted.');\n * });\n * ```\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n deleteAction(opts) {\n return this.delete('action', opts);\n }\n /**\n * Loads all actions within a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.loadActions().then((actions) => {\n * console.log(actions);\n * });\n * ```\n *\n * @param {object} query - Query parameters similar to {@link Formio#load}.\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<Response>}\n */\n loadActions(query, opts) {\n return this.index('actions', query, opts);\n }\n /**\n * Returns a list of available actions\n *\n * @return {Promise<Response>}\n */\n availableActions() {\n return this.makeRequest('availableActions', `${this.formUrl}/actions`);\n }\n /**\n * Returns the action information for a specific action, such as \"save\".\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/actions/save');\n * formio.actionInfo().then((info) => {\n * console.log(info);\n * });\n * ```\n *\n * @param {string} name - The name of the action you would like to get information for. i.e. \"save\", \"webhook\", etc.\n * @return {Promise<Response>}\n */\n actionInfo(name) {\n return this.makeRequest('actionInfo', `${this.formUrl}/actions/${name}`);\n }\n /**\n * Determine if a string ID is a valid MongoID.\n *\n * @param {string} id - The id that should be tested if it is avalid id.\n * @return {boolean} - true if it is a valid MongoId, false otherwise.\n */\n isObjectId(id) {\n const checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$');\n return checkForHexRegExp.test(id);\n }\n /**\n * Get the project ID of project.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io');\n * formio.getProjectId().then((projectId) => {\n * console.log(projectId);\n * };\n * ```\n *\n * @return {Promise<string>}\n */\n getProjectId() {\n if (!this.projectId) {\n return Promise.resolve('');\n }\n if (this.isObjectId(this.projectId)) {\n return Promise.resolve(this.projectId);\n }\n else {\n return this.loadProject().then((project) => {\n return project._id;\n });\n }\n }\n /**\n * Get the ID of a form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example');\n * formio.getFormId().then((formId) => {\n * console.log(formId);\n * });\n * ```\n *\n * @return {Promise<string>}\n */\n getFormId() {\n if (!this.formId) {\n return Promise.resolve('');\n }\n if (this.isObjectId(this.formId)) {\n return Promise.resolve(this.formId);\n }\n else {\n return this.loadForm().then((form) => {\n return form._id;\n });\n }\n }\n /**\n * Instance method for {@link Formio.currentUser}\n *\n * @param {object} options - Options to pass to {@link Formio.request}\n * @return {Promise<object>}\n */\n currentUser(options) {\n return Formio.currentUser(this, options);\n }\n /**\n * Instance method for {@link Formio.accessInfo}\n *\n * @return {Promise<Response>}\n */\n accessInfo() {\n return Formio.accessInfo(this);\n }\n /**\n * Sets OAuth Logout URL.\n *\n * @param {string} uri - Logout URL.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string}\n */\n oauthLogoutURI(uri, options) {\n return Formio.oauthLogoutURI(uri, Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Returns the JWT token for this instance.\n *\n * @param {object} options - The following options are provided.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string} - The JWT token for this user.\n */\n getToken(options) {\n return Formio.getToken(Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Sets the JWT token for this instance.\n *\n * @param {string} token - The JWT token to set.\n * @param {object} options - The following options are provided.\n * @param {string} options.namespace - The localStorage namespace to use when retrieving tokens from storage.\n * @return {string} - The JWT token that was set.\n */\n setToken(token, options) {\n return Formio.setToken(token, Object.assign({ formio: this }, this.options, options));\n }\n /**\n * Returns a temporary authentication token for single purpose token generation.\n *\n * @param {number|string} expire - The amount of seconds to wait before this temp token expires.\n * @param {string} allowed - The allowed path string inn the format GET:/path\n * @param {object} options - The options passed to {@link Formio#getToken}\n */\n getTempToken(expire, allowed, options) {\n const token = Formio.getToken(options);\n if (!token) {\n return Promise.reject('You must be authenticated to generate a temporary auth token.');\n }\n const authUrl = Formio.authUrl || this.projectUrl;\n return this.makeRequest('tempToken', `${authUrl}/token`, 'GET', null, {\n ignoreCache: true,\n header: new Headers({\n 'x-expire': expire,\n 'x-allow': allowed\n })\n });\n }\n /**\n * Get a PDF download url for a submission, which will generate a new PDF of the submission. This method will first\n * fetch a temporary download token, and then append this to the download url for this form.\n *\n * ```ts\n * const formio = new Formio('https://examples.form.io/example/submission/324234234234234');\n * formio.getDownloadUrl().then((url) => {\n * console.log(url);\n * });\n * ```\n *\n * @param {object} [form] - The form JSON to fetch a download url for.\n * @return {Promise<string>} - The download url.\n */\n getDownloadUrl(form) {\n if (!this.submissionId) {\n return Promise.resolve('');\n }\n if (!form) {\n // Make sure to load the form first.\n return this.loadForm().then((_form) => {\n if (!_form) {\n return '';\n }\n return this.getDownloadUrl(_form);\n });\n }\n let apiUrl = `/project/${form.project}`;\n apiUrl += `/form/${form._id}`;\n apiUrl += `/submission/${this.submissionId}`;\n const postfix = form.submissionRevisions && form.settings.changeLog ? '/download/changelog' : '/download';\n apiUrl += postfix;\n let download = this.base + apiUrl;\n return new Promise((resolve, reject) => {\n this.getTempToken(3600, `GET:${apiUrl}`).then((tempToken) => {\n download += `?token=${tempToken.key}`;\n resolve(download);\n }, () => {\n resolve(download);\n }).catch(reject);\n });\n }\n /**\n * Returns the user permissions to a form and submission.\n *\n * @param user - The user or current user if undefined. For anonymous, use \"null\"\n * @param form - The form or current form if undefined. For no form check, use \"null\"\n * @param submission - The submisison or \"index\" if undefined.\n *\n * @return {{create: boolean, read: boolean, edit: boolean, delete: boolean}}\n */\n userPermissions(user, form, submission) {\n return Promise.all([\n (form !== undefined) ? Promise.resolve(form) : this.loadForm(),\n (user !== undefined) ? Promise.resolve(user) : this.currentUser(),\n (submission !== undefined || !this.submissionId) ? Promise.resolve(submission) : this.loadSubmission(),\n this.accessInfo()\n ]).then((results) => {\n const form = results.shift();\n const user = results.shift() || { _id: false, roles: [] };\n const submission = results.shift();\n const access = results.shift();\n const permMap = {\n create: 'create',\n read: 'read',\n update: 'edit',\n delete: 'delete'\n };\n const perms = {\n user: user,\n form: form,\n access: access,\n create: false,\n read: false,\n edit: false,\n delete: false\n };\n for (const roleName in access.roles) {\n if (access.roles.hasOwnProperty(roleName)) {\n const role = access.roles[roleName];\n if (role.default && (user._id === false)) {\n // User is anonymous. Add the anonymous role.\n user.roles.push(role._id);\n }\n else if (role.admin && user.roles.indexOf(role._id) !== -1) {\n perms.create = true;\n perms.read = true;\n perms.delete = true;\n perms.edit = true;\n return perms;\n }\n }\n }\n if (form && form.submissionAccess) {\n for (let i = 0; i < form.submissionAccess.length; i++) {\n const permission = form.submissionAccess[i];\n const [perm, scope] = permission.type.split('_');\n if (['create', 'read', 'update', 'delete'].includes(perm)) {\n if ((0, lodash_1.intersection)(permission.roles, user.roles).length) {\n perms[permMap[perm]] = (scope === 'all') || (!submission || (user._id === submission.owner));\n }\n }\n }\n }\n // check for Group Permissions\n if (submission) {\n // we would anyway need to loop through components for create permission, so we'll do that for all of them\n (0, formUtil_1.eachComponent)(form.components, (component, path) => {\n if (component && component.defaultPermission) {\n const value = (0, lodash_1.get)(submission.data, path);\n // make it work for single-select Group and multi-select Group\n const groups = Array.isArray(value) ? value : [value];\n groups.forEach(group => {\n if (group && group._id && // group id is present\n user.roles.indexOf(group._id) > -1 // user has group id in his roles\n ) {\n if (component.defaultPermission === 'read') {\n perms[permMap.read] = true;\n }\n if (component.defaultPermission === 'create') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n }\n if (component.defaultPermission === 'write') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n perms[permMap.update] = true;\n }\n if (component.defaultPermission === 'admin') {\n perms[permMap.create] = true;\n perms[permMap.read] = true;\n perms[permMap.update] = true;\n perms[permMap.delete] = true;\n }\n }\n });\n }\n });\n }\n return perms;\n });\n }\n /**\n * `Determine if the current user can submit a form.\n * @return {*}\n */\n canSubmit() {\n return this.userPermissions().then((perms) => {\n // If there is user and they cannot create, then check anonymous user permissions.\n if (!perms.create && Formio.getUser()) {\n return this.userPermissions(null).then((anonPerms) => {\n if (anonPerms.create) {\n Formio.setUser(null);\n return true;\n }\n return false;\n });\n }\n return perms.create;\n });\n }\n getUrlParts(url) {\n return Formio.getUrlParts(url, this);\n }\n static getUrlParts(url, formio) {\n const base = (formio && formio.base) ? formio.base : Formio.baseUrl;\n let regex = '^(http[s]?:\\\\/\\\\/)';\n if (base && url.indexOf(base) === 0) {\n regex += `(${base.replace(/^http[s]?:\\/\\//, '')})`;\n }\n else {\n regex += '([^/]+)';\n }\n regex += '($|\\\\/.*)';\n return url.match(new RegExp(regex));\n }\n static serialize(obj, _interpolate) {\n const str = [];\n const interpolate = (item) => {\n return _interpolate ? _interpolate(item) : item;\n };\n for (const p in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, p)) {\n str.push(`${encodeURIComponent(p)}=${encodeURIComponent(interpolate(obj[p]))}`);\n }\n }\n return str.join('&');\n }\n static getRequestArgs(formio, type, url, method, data, opts) {\n method = (method || 'GET').toUpperCase();\n if (!opts || !(0, lodash_1.isObject)(opts)) {\n opts = {};\n }\n const requestArgs = {\n url,\n method,\n data: data || null,\n opts\n };\n if (type) {\n requestArgs.type = type;\n }\n if (formio) {\n requestArgs.formio = formio;\n }\n return requestArgs;\n }\n static makeStaticRequest(url, method, data, opts) {\n const requestArgs = Formio.getRequestArgs(null, '', url, method, data, opts);\n const request = Plugins_1.default.pluginWait('preRequest', requestArgs)\n .then(() => Plugins_1.default.pluginGet('staticRequest', requestArgs)\n .then((result) => {\n if ((0, lodash_1.isNil)(result)) {\n return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts);\n }\n return result;\n }));\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', request, requestArgs);\n }\n /**\n * Make an API request and wrap that request with the Form.io Request plugin system. This is very similar to the\n * {Formio.request} method with a difference being that it will pass the request through the Form.io request plugin.\n *\n * @param {Formio} formio - An instance of the Formio class.\n * @param {string} type - The request resource type. \"submission\", \"form\", etc.\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>}\n */\n static makeRequest(formio, type, url, method, data, opts) {\n if (!formio) {\n return Formio.makeStaticRequest(url, method, data, opts);\n }\n const requestArgs = Formio.getRequestArgs(formio, type, url, method, data, opts);\n requestArgs.opts = requestArgs.opts || {};\n requestArgs.opts.formio = formio;\n //for Formio requests default Accept and Content-type headers\n if (!requestArgs.opts.headers) {\n requestArgs.opts.headers = {};\n }\n requestArgs.opts.headers = (0, lodash_1.defaults)(requestArgs.opts.headers, {\n 'Accept': 'application/json',\n 'Content-type': 'application/json'\n });\n const request = Plugins_1.default.pluginWait('preRequest', requestArgs)\n .then(() => Plugins_1.default.pluginGet('request', requestArgs)\n .then((result) => {\n if ((0, lodash_1.isNil)(result)) {\n return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts);\n }\n return result;\n }));\n return Plugins_1.default.pluginAlter('wrapRequestPromise', request, requestArgs);\n }\n /**\n * Execute an API request to any external system. This is a wrapper around the Web fetch method.\n *\n * ```ts\n * Formio.request('https://examples.form.io').then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {string} url - The URL to request.\n * @param {string} method - The request method. GET, PUT, POST, DELETE, or PATCH\n * @param {object} data - The data to pass to the request (for PUT, POST, and PATCH methods)\n * @param {Headers} header - An object of headers to pass to the request.\n * @param {object} options - An object of options to pass to the request method.\n * @param {boolean} options.ignoreCache - To ignore internal caching of the request.\n * @param {object} options.headers - An object of headers to pass along to the request.\n * @param {boolean} options.noToken - If set to true, this will not include the Form.io x-jwt-token along with the request.\n * @param {string} options.namespace - The Form.io namespace to prepend to all LocalStorage variables such as formioToken.\n * @param {boolean} options.getHeaders - Set this if you wish to include the response headers with the return of this method.\n * @return {Promise<Response>|*}\n */\n static request(url, method, data, header, opts) {\n if (!url) {\n return Promise.reject('No url provided');\n }\n method = (method || 'GET').toUpperCase();\n // For reverse compatibility, if they provided the ignoreCache parameter,\n // then change it back to the options format where that is a parameter.\n if ((0, lodash_1.isBoolean)(opts)) {\n opts = { ignoreCache: opts };\n }\n if (!opts || !(0, lodash_1.isObject)(opts)) {\n opts = {};\n }\n // Generate a cachekey.\n const cacheKey = btoa(encodeURI(url));\n // Get the cached promise to save multiple loads.\n if (!opts.ignoreCache && method === 'GET' && Formio.cache.hasOwnProperty(cacheKey)) {\n return Promise.resolve(Formio.cloneResponse(Formio.cache[cacheKey]));\n }\n if (url[0] === '/') {\n url = Formio.baseUrl + url;\n }\n // Set up and fetch request\n const headers = header || new Headers(opts.headers || {\n 'Accept': 'application/json',\n 'Content-type': 'application/json'\n });\n const token = Formio.getToken(opts);\n if (token && !opts.noToken) {\n headers.set('x-jwt-token', token);\n }\n // The fetch-ponyfill can't handle a proper Headers class anymore. Change it back to an object.\n const headerObj = {};\n headers.forEach(function (value, name) {\n headerObj[name] = value;\n });\n let options = {\n method: method,\n headers: headerObj,\n mode: 'cors'\n };\n if (data) {\n options.body = JSON.stringify(data);\n }\n // Allow plugins to alter the options.\n options = Plugins_1.default.pluginAlter('requestOptions', options, url);\n if (options.namespace || Formio.namespace) {\n opts.namespace = options.namespace || Formio.namespace;\n }\n const requestToken = options.headers['x-jwt-token'];\n const result = Plugins_1.default.pluginAlter('wrapFetchRequestPromise', Formio.fetch(url, options), { url, method, data, opts }).then((response) => {\n // Allow plugins to respond.\n response = Plugins_1.default.pluginAlter('requestResponse', response, Formio, data);\n if (!response.ok) {\n if (response.status === 440) {\n Formio.setToken(null, opts);\n Formio.events.emit('formio.sessionExpired', response.body);\n }\n else if (response.status === 401) {\n Formio.events.emit('formio.unauthorized', response.body);\n }\n else if (response.status === 416) {\n Formio.events.emit('formio.rangeIsNotSatisfiable', response.body);\n }\n else if (response.status === 504) {\n return Promise.reject(new Error('Network request failed'));\n }\n // Parse and return the error as a rejected promise to reject this promise\n return (response.headers.get('content-type').includes('application/json')\n ? response.json()\n : response.text())\n .then((error) => {\n return Promise.reject(error);\n });\n }\n // Handle fetch results\n const respToken = response.headers.get('x-jwt-token');\n // In some strange cases, the fetch library will return an x-jwt-token without sending\n // one to the server. This has even been debugged on the server to verify that no token\n // was introduced with the request, but the response contains a token. This is an Invalid\n // case where we do not send an x-jwt-token and get one in return for any GET request.\n let tokenIntroduced = false;\n if ((method === 'GET') &&\n !requestToken &&\n respToken &&\n !opts.external &&\n !url.includes('token=') &&\n !url.includes('x-jwt-token=')) {\n console.warn('Token was introduced in request.');\n tokenIntroduced = true;\n }\n if (response.status >= 200 &&\n response.status < 300 &&\n respToken &&\n respToken !== '' &&\n !tokenIntroduced) {\n Formio.setToken(respToken, Object.assign(Object.assign({}, opts), { fromCurrent: (opts.fromCurrent || !!requestToken) }));\n }\n // 204 is no content. Don't try to .json() it.\n if (response.status === 204) {\n return {};\n }\n const getResult = response.headers.get('content-type').includes('application/json')\n ? response.json()\n : response.text();\n return getResult.then((result) => {\n // Add some content-range metadata to the result here\n let range = response.headers.get('content-range');\n if (range && (0, lodash_1.isObject)(result)) {\n range = range.split('/');\n if (range[0] !== '*') {\n const skipLimit = range[0].split('-');\n result.skip = Number(skipLimit[0]);\n result.limit = skipLimit[1] - skipLimit[0] + 1;\n }\n result.serverCount = range[1] === '*' ? range[1] : Number(range[1]);\n }\n if (!opts.getHeaders) {\n return result;\n }\n const headers = {};\n response.headers.forEach((item, key) => {\n headers[key] = item;\n });\n // Return the result with the headers.\n return {\n result,\n headers,\n };\n });\n })\n .then((result) => {\n if (opts.getHeaders) {\n return result;\n }\n // Cache the response.\n if (method === 'GET') {\n Formio.cache[cacheKey] = result;\n }\n return Formio.cloneResponse(result);\n })\n .catch((err) => {\n if (err === 'Bad Token' && opts.noToken !== false) {\n Formio.setToken(null, opts);\n Formio.events.emit('formio.badToken', err);\n }\n if (err.message) {\n err = new Error(`Could not connect to API server (${err.message}): ${url}`);\n err.networkError = true;\n }\n if (method === 'GET') {\n delete Formio.cache[cacheKey];\n }\n return Promise.reject(err);\n });\n return result;\n }\n // Needed to maintain reverse compatability...\n static get token() {\n return Formio.tokens.formioToken || '';\n }\n // Needed to maintain reverse compatability...\n static set token(token) {\n Formio.tokens.formioToken = token || '';\n }\n static useSessionToken(options) {\n if (typeof localStorage === 'undefined') {\n return;\n }\n let namespace = options;\n if (typeof options === 'object') {\n options = options.namespace;\n }\n const tokenName = `${namespace || Formio.namespace || 'formio'}Token`;\n const token = localStorage.getItem(tokenName);\n if (token) {\n localStorage.removeItem(tokenName);\n sessionStorage.setItem(tokenName, token);\n }\n const userName = `${namespace || Formio.namespace || 'formio'}User`;\n const user = localStorage.getItem(userName);\n if (user) {\n localStorage.removeItem(userName);\n sessionStorage.setItem(userName, user);\n }\n localStorage.setItem('useSessionToken', 'true');\n }\n /**\n * Sets the JWT in storage to be used within an application.\n *\n * @param {string} token - The JWT token to set.\n * @param {object} options - Options as follows\n * @param {string} options.namespace - The namespace to save the token within. i.e. \"formio\"\n * @param {Formio} options.formio - The Formio instance.\n * @return {Promise<object>|void}\n */\n static setToken(token = '', opts = {}) {\n token = token || '';\n opts = (typeof opts === 'string') ? { namespace: opts } : opts || {};\n const tokenName = `${opts.namespace || Formio.namespace || 'formio'}Token`;\n if (!Formio.tokens) {\n Formio.tokens = {};\n }\n const storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage;\n if (!token) {\n if (!opts.fromUser) {\n opts.fromToken = true;\n Formio.setUser(null, opts);\n }\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.removeItem(tokenName);\n }\n catch (err) {\n browser_cookies_1.default.erase(tokenName, { path: '/' });\n }\n Formio.tokens[tokenName] = token;\n return Promise.resolve(null);\n }\n if (Formio.tokens[tokenName] !== token) {\n Formio.tokens[tokenName] = token;\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.setItem(tokenName, token);\n }\n catch (err) {\n browser_cookies_1.default.set(tokenName, token, { path: '/' });\n }\n }\n // Return or updates the current user\n return Formio.currentUser(opts.formio, opts);\n }\n /**\n * Returns the token set within the application for the user.\n *\n * @param {object} options - The options as follows.\n * @param {string} options.namespace - The namespace of the token you wish to fetch.\n * @param {boolean} options.decode - If you would like the token returned as decoded JSON.\n * @return {*}\n */\n static getToken(options) {\n options = (typeof options === 'string') ? { namespace: options } : options || {};\n const tokenName = `${options.namespace || Formio.namespace || 'formio'}Token`;\n const decodedTokenName = options.decode ? `${tokenName}Decoded` : tokenName;\n if (!Formio.tokens) {\n Formio.tokens = {};\n }\n if (Formio.tokens[decodedTokenName]) {\n return Formio.tokens[decodedTokenName];\n }\n try {\n const token = localStorage.getItem('useSessionToken')\n ? sessionStorage.getItem(tokenName)\n : localStorage.getItem(tokenName);\n Formio.tokens[tokenName] = token || '';\n if (options.decode) {\n Formio.tokens[decodedTokenName] = Formio.tokens[tokenName] ? (0, jwtDecode_1.jwtDecode)(Formio.tokens[tokenName]) : {};\n return Formio.tokens[decodedTokenName];\n }\n return Formio.tokens[tokenName];\n }\n catch (e) {\n Formio.tokens[tokenName] = browser_cookies_1.default.get(tokenName);\n return '';\n }\n }\n /**\n * Sets the current user within the application cache.\n *\n * @param {object} user - JSON object of the user you wish to set.\n * @param {object} options - Options as follows\n * @param {string} options.namespace - The namespace of the tokens\n */\n static setUser(user, opts = {}) {\n const userName = `${opts.namespace || Formio.namespace || 'formio'}User`;\n const storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage;\n if (!user) {\n if (!opts.fromToken) {\n opts.fromUser = true;\n Formio.setToken(null, opts);\n }\n // Emit an event on the cleared user.\n Formio.events.emit('formio.user', null);\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n return storage.removeItem(userName);\n }\n catch (err) {\n return browser_cookies_1.default.erase(userName, { path: '/' });\n }\n }\n // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode.\n try {\n storage.setItem(userName, JSON.stringify(user));\n }\n catch (err) {\n browser_cookies_1.default.set(userName, JSON.stringify(user), { path: '/' });\n }\n // Emit an event on the authenticated user.\n Formio.events.emit('formio.user', user);\n }\n /**\n * Returns the user JSON.\n *\n * @param {object} options - Options as follows\n * @param {string} namespace - The namespace of the tokens stored within this application.\n * @return {object} - The user object.\n */\n static getUser(options) {\n options = options || {};\n const userName = `${options.namespace || Formio.namespace || 'formio'}User`;\n try {\n return JSON.parse((localStorage.getItem('useSessionToken')\n ? sessionStorage\n : localStorage).getItem(userName) || '');\n }\n catch (e) {\n return JSON.parse(browser_cookies_1.default.get(userName));\n }\n }\n /**\n * Sets the BaseURL for the application.\n *\n * @description Every application developed using the JavaScript SDK must set both the {@link Formio.setBaseUrl} and\n * {@link Formio.setProjectUrl} methods. These two functions ensure that every URL passed into the constructor of this\n * class can determine the \"project\" context for which the application is running.\n *\n * Any Open Source server applications will set both the {@link Formio.setBaseUrl} and {@link Formio.setProjectUrl}\n * values will be the same value.\n *\n * ```ts\n * Formio.setBaseUrl('https://yourwebsite.com/forms');\n * Formio.setProjectUrl('https://yourwebsite.com/forms/project');\n *\n * // Now the Formio constructor will know what is the \"project\" and what is the form alias name. Without setBaseUrl\n * // and setProjectUrl, this would throw an error.\n *\n * const formio = new Formio('https://yourwebsite.com/forms/project/user');\n * formio.loadForm().then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * @param {string} url - The URL of the Base API url.\n */\n static setBaseUrl(url) {\n Formio.baseUrl = url;\n if (!Formio.projectUrlSet) {\n Formio.projectUrl = url;\n }\n }\n /**\n * Returns the current base url described at {@link Formio.setBaseUrl}\n *\n * @return {string} - The base url of the application.\n */\n static getBaseUrl() {\n return Formio.baseUrl;\n }\n static setApiUrl(url) {\n return Formio.setBaseUrl(url);\n }\n static getApiUrl() {\n return Formio.getBaseUrl();\n }\n static setAppUrl(url) {\n console.warn('Formio.setAppUrl() is deprecated. Use Formio.setProjectUrl instead.');\n Formio.projectUrl = url;\n Formio.projectUrlSet = true;\n }\n /**\n * Sets the Project Url for the application. This is an important method that needs to be set for all applications. It\n * is documented @ {@link Formio.setBaseUrl}.\n *\n * @param {string} url - The project api url.\n */\n static setProjectUrl(url) {\n Formio.projectUrl = url;\n Formio.projectUrlSet = true;\n }\n /**\n * The Auth URL can be set to customize the authentication requests made from an application. By default, this is\n * just the same value as {@link Formio.projectUrl}\n *\n * @param {string} url - The authentication url\n */\n static setAuthUrl(url) {\n Formio.authUrl = url;\n }\n static getAppUrl() {\n console.warn('Formio.getAppUrl() is deprecated. Use Formio.getProjectUrl instead.');\n return Formio.projectUrl;\n }\n /**\n * Returns the Project url described at {@link Formio.setProjectUrl}\n *\n * @return {string|string} - The Project Url.\n */\n static getProjectUrl() {\n return Formio.projectUrl;\n }\n /**\n * Clears the runtime internal API cache.\n *\n * @description By default, the Formio class will cache all API requests in memory so that any subsequent requests\n * using GET method will return the cached results as long as the API URl is the same as what was cached previously.\n * This cache can be cleared using this method as follows.\n *\n * ```ts\n * Formio.clearCache();\n * ```\n *\n * Or, if you just wish to clear a single request, then the {@link Formio.request#options.ignoreCache} option can be\n * provided when making an API request as follows.\n *\n * ```ts\n * Formio.loadForm({}, {\n * ignoreCache: true\n * }).then((form) => {\n * console.log(form);\n * });\n * ```\n *\n * Both of the following will ensure that a new request is made to the API server and that the results will not be\n * from the cached result.\n */\n static clearCache() {\n Formio.cache = {};\n }\n /**\n * Return the access information about a Project, such as the Role ID's for that project, and if the server is\n * configured to do so, the Form and Resource access configurations that the authenticated user has access to.\n *\n * @description This is useful for an application to determine the UI for a specific user to identify which forms they have\n * access to submit or read.\n *\n * @param {Formio} formio - The Formio instance.\n * @return {Promise<Response>}\n */\n static accessInfo(formio) {\n const projectUrl = formio ? formio.projectUrl : Formio.projectUrl;\n return Formio.makeRequest(formio, 'accessInfo', `${projectUrl}/access`);\n }\n /**\n * Returns an array of roles for the project, which includes the ID's and names of those roles.\n *\n * @param {Formio} formio - The Formio instance.\n * @return {Promise<Response>}\n */\n static projectRoles(formio) {\n const projectUrl = formio ? formio.projectUrl : Formio.projectUrl;\n return Formio.makeRequest(formio, 'projectRoles', `${projectUrl}/role`);\n }\n /**\n * Return the currentUser object. This will fetch the user from the server and respond with the Submission JSON\n * of that user object.\n *\n * @param {Formio} formio - The Formio instance\n * @param {object} options - The options passed to {@link Formio.getUser}\n * @return {Promise<R>|*}\n */\n static currentUser(formio, options = {}) {\n let authUrl = Formio.authUrl;\n if (!authUrl) {\n authUrl = formio ? formio.projectUrl : (Formio.projectUrl || Formio.baseUrl);\n }\n authUrl += '/current';\n if (!options.ignoreCache || options.fromCurrent) {\n const user = Formio.getUser(options);\n if (user) {\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', Promise.resolve(user), {\n url: authUrl,\n method: 'GET',\n options\n });\n }\n }\n const token = Formio.getToken(options);\n if ((!options || !options.external) && !token) {\n return Plugins_1.default.pluginAlter('wrapStaticRequestPromise', Promise.resolve(null), {\n url: authUrl,\n method: 'GET',\n options\n });\n }\n options.fromCurrent = true;\n return Formio.makeRequest(formio, 'currentUser', authUrl, 'GET', null, options)\n .then((response) => {\n Formio.setUser(response, options);\n return response;\n });\n }\n /**\n * Performs a logout of the Form.io application. This will reset all cache, as well as make a request to the logout\n * endpoint of the Form.io api platform.\n *\n * @param {Formio} formio - A Formio instance.\n * @param {object} options - Options passed to both {@link Formio.setToken} as well as {@link Formio.setUser}\n * @return {Promise<Response>}\n */\n static logout(formio, options = {}) {\n options.formio = formio;\n const projectUrl = Formio.authUrl ? Formio.authUrl : (formio ? formio.projectUrl : Formio.baseUrl);\n const logout = () => {\n Formio.setToken(null, options);\n Formio.setUser(null, options);\n Formio.clearCache();\n localStorage.removeItem('useSessionToken');\n };\n return Formio.makeRequest(formio, 'logout', `${projectUrl}/logout`)\n .then(function (result) {\n logout();\n if (result.shouldRedirect && result.url) {\n window.location.href = result.url;\n }\n return result;\n })\n .catch(function (err) {\n logout();\n throw err;\n });\n }\n /**\n * Returns the query passed to a page in JSON object format.\n *\n * @description For example, lets say you visit your application using\n * the url as follows.\n *\n * ```\n * https://yourapplication.com/?token=23423423423&username=Joe\n * ```\n *\n * The following code will provide your application with the following.\n *\n * ```ts\n * const query Formio.pageQuery();\n * console.log(query.token); // Will print 23423423423\n * console.log(query.username); // Will print Joe\n * ```\n *\n * @return {{}} - A JSON object representation of the query that was passed to the URL of an application.\n */\n static pageQuery() {\n const pageQuery = {};\n pageQuery.paths = [];\n const hashes = location.hash.substr(1).replace(/\\?/g, '&').split('&');\n let parts = [];\n location.search.substr(1).split('&').forEach(function (item) {\n parts = item.split('=');\n if (parts.length > 1) {\n pageQuery[parts[0]] = parts[1] && decodeURIComponent(parts[1]);\n }\n });\n hashes.forEach(function (item) {\n parts = item.split('=');\n if (parts.length > 1) {\n pageQuery[parts[0]] = parts[1] && decodeURIComponent(parts[1]);\n }\n else if (item.indexOf('/') === 0) {\n pageQuery.paths = item.substr(1).split('/');\n }\n });\n return pageQuery;\n }\n /**\n * Much like {@link Formio.currentUser}, but instead automatically injects the Bearer tokens into the headers to\n * perform a Token swap of the OAuth token which will then return the JWT token for that user.\n *\n * @param {Formio} formio - The Formio instance\n * @param {string} token - An OAuth Bearer token to use for a token swap between the OAuth provider and Form.io\n * @return {Promise<R>|*}\n */\n static oAuthCurrentUser(formio, token) {\n return Formio.currentUser(formio, {\n external: true,\n headers: {\n Authorization: `Bearer ${token}`\n }\n });\n }\n static oauthLogoutURI(uri, options) {\n options = (typeof options === 'string') ? { namespace: options } : options || {};\n const logoutURIName = `${options.namespace || Formio.namespace || 'formio'}LogoutAuthUrl`;\n Formio.tokens[logoutURIName];\n localStorage.setItem(logoutURIName, uri);\n return Formio.tokens[logoutURIName];\n }\n /**\n * Perform a SAML initialization.\n *\n * @description Typically, you would use the {@link Formio.ssoInit} method to perform this function\n * since this method is an alias for the following.\n *\n * ```ts\n * Formio.samlInit();\n * Formio.ssoInit('saml'); // This is the exact same thing as calling Formio.samlInit\n * ```\n *\n * This method will return false if the process is just starting. The code below is a typical block of code that is\n * used to automatically trigger the SAML authentication process within your application using a Button component.\n *\n * ```ts\n * if (Formio.pageQuery().saml) {\n * const sso = Formio.samlInit();\n * if (sso) {\n * sso.then((user) => {\n * // The SSO user is now loaded!\n * console.log(user);\n * });\n * }\n * }\n * ```\n *\n * You can then place the following code withiin the \"Custom\" action of a Button component on your form.\n *\n * ```ts\n * Formio.samlInit();\n * ```\n *\n * Now when you click on this button, it will start the handshake process with SAML, and once it returns, will pass\n * a \"saml\" query parameter back to your application which will execute the code to load the current user from SAML.\n *\n * @param {object} options - Options to pass to the SAML initialization process.\n * @param {string} options.relay - The URL that will be used as the authentication \"relay\" that occurs during a SAML handshake process.\n * @return {boolean|Promise<Object>|void}\n */\n static samlInit(options = {}) {\n const query = Formio.pageQuery();\n if (query.saml) {\n Formio.setUser(null);\n const retVal = Formio.setToken(query.saml);\n let uri = window.location.toString();\n uri = uri.substring(0, uri.indexOf('?'));\n if (window.location.hash) {\n uri += window.location.hash;\n }\n window.history.replaceState({}, document.title, uri);\n return retVal;\n }\n // Set the relay if not provided.\n if (!options.relay) {\n options.relay = window.location.href;\n }\n // go to the saml sso endpoint for this project.\n const authUrl = Formio.authUrl || Formio.projectUrl;\n window.location.href = `${authUrl}/saml/sso?relay=${encodeURI(options.relay)}`;\n return false;\n }\n /**\n * Perform an Okta Authentication process using the {@link https://developer.okta.com/code/javascript/okta_auth_sdk|Okta SDK}.\n *\n * @description This method does require that you first include the Okta JavaScript SDK within your application as follows.\n *\n * First you need to include the Okta Authentication script.\n *\n * ```html\n * <script src=\"https://ok1static.oktacdn.com/assets/js/sdk/okta-auth-js/2.0.1/okta-auth-js.min.js\" type=\"text/javascript\"></script>\n * ```\n *\n * Then you can call this method as follows.\n *\n * ```ts\n * Formio.oktaInit();\n * ```\n *\n * @param {object} options - Options that are passed directly to the {@link https://github.com/okta/okta-auth-js#configuration-reference|Okta SDK constructor}\n * @param {constructor} options.OktaAuth - If the OktaAuth constructor is not provided global to the application, it can be provided to this method using this property.\n * @param {Formio} options.formio - The Formio instance.\n * @param {Array<string>} options.scopes - Scopes that are passed to the {@link https://github.com/okta/okta-auth-js#tokengetwithredirectoptions|getWithRedirect} method from the Okta SDK.\n * @return {Promise<Object>}\n */\n static oktaInit(options = {}) {\n if (typeof OktaAuth !== undefined) {\n options.OktaAuth = OktaAuth;\n }\n if (typeof options.OktaAuth === undefined) {\n const errorMessage = 'Cannot find OktaAuth. Please include the Okta JavaScript SDK within your application. See https://developer.okta.com/code/javascript/okta_auth_sdk for an example.';\n console.warn(errorMessage);\n return Promise.reject(errorMessage);\n }\n return new Promise((resolve, reject) => {\n const Okta = options.OktaAuth;\n delete options.OktaAuth;\n const authClient = new Okta(options);\n authClient.tokenManager.get('accessToken')\n .then((accessToken) => {\n if (accessToken) {\n resolve(Formio.oAuthCurrentUser(options.formio, accessToken.accessToken));\n }\n else if (location.hash) {\n authClient.token.parseFromUrl()\n .then((token) => {\n authClient.tokenManager.add('accessToken', token);\n resolve(Formio.oAuthCurrentUser(options.formio, token.accessToken));\n })\n .catch((err) => {\n console.warn(err);\n reject(err);\n });\n }\n else {\n authClient.token.getWithRedirect({\n responseType: 'token',\n scopes: options.scopes\n });\n resolve(false);\n }\n })\n .catch((error) => {\n reject(error);\n });\n });\n }\n /**\n * A common static method to trigger any SSO processes. This method is really just an alias for other static methods.\n *\n * @param {('saml'|'okta')} type - The type of SSO to trigger. 'saml' is an alias for {@link Formio.samlInit}, and 'okta' is an alias for {@link Formio.oktaInit}.\n * @param {object} options - Options to pass to the specific sso methods\n * @return {*|Promise<Object>|boolean|void}\n */\n static ssoInit(type, options = {}) {\n switch (type) {\n case 'saml':\n return Formio.samlInit(options);\n case 'okta':\n return Formio.oktaInit(options);\n default:\n console.warn('Unknown SSO type');\n return Promise.reject('Unknown SSO type');\n }\n }\n /**\n * Lazy load a remote library dependency.\n *\n * @description This is useful for components that wish to lazy load a required library\n * by adding that library to the <scripts> section of the HTML webpage, and then provide a promise that will resolve\n * when the library becomes available for use.\n *\n * @example Load Google Maps API.\n * ```ts\n * Formio.requireLibrary('googleMaps', 'google.maps.Map', 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap', true).then(() => {\n * // Once the promise resolves, the following can now be used within your application.\n * const map = new google.maps.Map(document.getElementById(\"map\"), {...});\n * });\n * ```\n *\n * @param {string} name - The internal name to give to the library you are loading. This is useful for caching the library for later use.\n * @param {string} property - The name of the global property that will be added to the global namespace once the library has been loaded. This is used to check to see if the property exists before resolving the promise that the library is ready for use.\n * @param {string} src - The URL of the library to lazy load.\n * @param {boolean} polling - Determines if polling should be used to determine if they library is ready to use. If set to false, then it will rely on a global callback called ${name}Callback where \"name\" is the first property passed to this method. When this is called, that will indicate when the library is ready. In most cases, you will want to pass true to this parameter to initiate a polling method to check for the library availability in the global context.\n * @return {Promise<object>} - A promise that will resolve when the plugin is ready to be used.\n */\n static requireLibrary(name, property, src, polling = false, onload) {\n if (!Formio.libraries.hasOwnProperty(name)) {\n Formio.libraries[name] = {};\n Formio.libraries[name].ready = new Promise((resolve, reject) => {\n Formio.libraries[name].resolve = resolve;\n Formio.libraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = () => Formio.libraries[name].resolve();\n }\n // See if the plugin already exists.\n const plugin = (0, lodash_1.get)(window, property);\n if (plugin) {\n Formio.libraries[name].resolve(plugin);\n }\n else {\n src = Array.isArray(src) ? src : [src];\n src.forEach((lib) => {\n let attrs = {};\n let elementType = '';\n if (typeof lib === 'string') {\n lib = {\n type: 'script',\n src: lib,\n };\n }\n switch (lib.type) {\n case 'script':\n elementType = 'script';\n attrs = {\n src: lib.src,\n type: 'text/javascript',\n defer: true,\n async: true,\n referrerpolicy: 'origin',\n };\n break;\n case 'styles':\n elementType = 'link';\n attrs = {\n href: lib.src,\n rel: 'stylesheet',\n };\n break;\n }\n // Add the script to the top of the page.\n const element = document.createElement(elementType);\n if (element.setAttribute) {\n for (const attr in attrs) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n if (onload) {\n element.addEventListener('load', () => {\n Formio.libraries[name].loaded = true;\n onload(Formio.libraries[name].ready);\n });\n }\n const { head } = document;\n if (head) {\n head.appendChild(element);\n }\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n const interval = setInterval(() => {\n const plugin = (0, lodash_1.get)(window, property);\n if (plugin) {\n clearInterval(interval);\n Formio.libraries[name].resolve(plugin);\n }\n }, 200);\n }\n }\n }\n const lib = Formio.libraries[name];\n return onload && lib.loaded ? onload(lib.ready) : lib.ready;\n }\n /**\n * Determines if a lazy loaded library is ready to be used.\n *\n * @description Example: Let's assume that the example provided at {@link Formio.requireLibrary} was used elsewhere in your application.\n * You could now use the following within a separate place that will also resolve once the library is ready to be used.\n *\n * ```js\n * Formio.libraryReady('googleMaps').then(() => {\n * // Once the promise resolves, the following can now be used within your application.\n * const map = new google.maps.Map(document.getElementById(\"map\"), {...});\n * });\n * ```\n *\n * @param {string} name - The name of the library to check.\n * @return {Promise<object>} - A promise that will resolve when the library is ready to be used.\n */\n static libraryReady(name) {\n if (Formio.libraries.hasOwnProperty(name) &&\n Formio.libraries[name].ready) {\n return Formio.libraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n }\n /**\n * Clones the response from the API so that it cannot be mutated.\n *\n * @param response\n */\n static cloneResponse(response) {\n const copy = (0, fastCloneDeep_1.fastCloneDeep)(response);\n if (Array.isArray(response)) {\n copy.skip = response.skip;\n copy.limit = response.limit;\n copy.serverCount = response.serverCount;\n }\n return copy;\n }\n /**\n * Sets the project path type.\n *\n * @param type\n */\n static setPathType(type) {\n if (typeof type === 'string') {\n Formio.pathType = type;\n }\n }\n /**\n * Gets the project path type.\n */\n static getPathType() {\n return Formio.pathType;\n }\n}\nexports.Formio = Formio;\n/**\n * The base API url of the Form.io Platform. Example: https://api.form.io\n */\nFormio.baseUrl = 'https://api.form.io';\n/**\n * The project API url of the Form.io Project. Example: https://examples.form.io\n */\nFormio.projectUrl = '';\n/**\n * The project url to use for Authentication.\n */\nFormio.authUrl = '';\n/**\n * Set to true if the project url has been established with ```Formio.setProjectUrl()```\n */\nFormio.projectUrlSet = false;\n/**\n * The Form.io API Cache. This ensures that requests to the same API endpoint are cached.\n */\nFormio.cache = {};\n/**\n * The namespace used to save the Form.io Token's and variables within an application.\n */\nFormio.namespace = '';\n/**\n * Handles events fired within this SDK library.\n */\nFormio.events = new eventemitter3_1.default();\n/**\n * Stores all of the libraries lazy loaded with ```Formio.requireLibrary``` method.\n */\nFormio.libraries = {};\n/**\n * A direct interface to the Form.io fetch polyfill.\n */\nFormio.fetch = fetch;\n/**\n * A direct interface to the Form.io fetch Headers polyfill.\n */\nFormio.Headers = Headers;\n/**\n * All of the auth tokens for this session.\n */\nFormio.tokens = {};\n/**\n * The version of this library.\n */\nFormio.version = '---VERSION---';\n/**\n * The global options for the Formio library.\n */\nFormio.options = {};\n// Add Plugin methods.\nFormio.plugins = Plugins_1.default.plugins;\nFormio.deregisterPlugin = Plugins_1.default.deregisterPlugin;\nFormio.registerPlugin = Plugins_1.default.registerPlugin;\nFormio.getPlugin = Plugins_1.default.getPlugin;\nFormio.pluginWait = Plugins_1.default.pluginWait;\nFormio.pluginGet = Plugins_1.default.pluginGet;\nFormio.pluginAlter = Plugins_1.default.pluginAlter;\n// Adds Formio to the Plugins Interface.\nPlugins_1.default.Formio = Formio;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/sdk/Formio.js?");
|
|
4999
5000
|
|
|
5000
5001
|
/***/ }),
|
|
5001
5002
|
|
|
@@ -5248,7 +5249,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5248
5249
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5249
5250
|
|
|
5250
5251
|
"use strict";
|
|
5251
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst compare_versions_1 = __webpack_require__(/*! compare-versions */ \"./node_modules/compare-versions/lib/esm/index.js\");\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst i18n_1 = __importDefault(__webpack_require__(/*! ./i18n */ \"./lib/cjs/i18n.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst NestedDataComponent_1 = __importDefault(__webpack_require__(/*! ./components/_classes/nesteddata/NestedDataComponent */ \"./lib/cjs/components/_classes/nesteddata/NestedDataComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\n// Initialize the available forms.\nFormio_1.Formio.forms = {};\n// Allow people to register components.\nFormio_1.Formio.registerComponent = Components_1.default.setComponent;\nfunction getIconSet(icons) {\n if (icons === 'fontawesome') {\n return 'fa';\n }\n return icons || '';\n}\nfunction getOptions(options) {\n options = lodash_1.default.defaults(options, {\n submitOnEnter: false,\n iconset: getIconSet((options && options.icons) ? options.icons : Formio_1.Formio.icons),\n i18next: null,\n saveDraft: false,\n alwaysDirty: false,\n saveDraftThrottle: 5000,\n display: 'form',\n cdnUrl: Formio_1.Formio.cdn.baseUrl\n });\n if (!options.events) {\n options.events = new EventEmitter_1.default();\n }\n return options;\n}\n/**\n * Represents a JSON value.\n * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON\n */\n/**\n * Represents a JSON array.\n * @typedef {Array<JSON>} JSONArray\n */\n/**\n * Represents a JSON object.\n * @typedef {{[key: string]: JSON}} JSONObject\n */\n/**\n * @typedef {Object} FormioHooks\n * @property {function} [beforeSubmit]\n * @property {function} [beforeCancel]\n * @property {function} [beforeNext]\n * @property {function} [beforePrev]\n * @property {function} [attachComponent]\n * @property {function} [setDataValue]\n * @property {function} [addComponents]\n * @property {function} [addComponent]\n * @property {function} [customValidation]\n * @property {function} [attachWebform]\n */\n/**\n * @typedef {Object} SanitizeConfig\n * @property {string[]} [addAttr]\n * @property {string[]} [addTags]\n * @property {string[]} [allowedAttrs]\n * @property {string[]} [allowedTags]\n * @property {string[]} [allowedUriRegex]\n * @property {string[]} [addUriSafeAttr]\n */\n/**\n * @typedef {Object} ButtonSettings\n * @property {boolean} [showPrevious]\n * @property {boolean} [showNext]\n * @property {boolean} [showCancel]\n * @property {boolean} [showSubmit]\n */\n/**\n * @typedef {Object} FormOptions\n * @property {boolean} [saveDraft] - Enable the save draft feature.\n * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.\n * @property {boolean} [readOnly] - Set this form to readOnly.\n * @property {boolean} [noAlerts] - Disable the alerts dialog.\n * @property {{[key: string]: string}} [i18n] - The translation file for this rendering.\n * @property {string} [template] - Custom logic for creation of elements.\n * @property {boolean} [noDefaults] - Exclude default values from the settings.\n * @property {any} [fileService] - The file service for this form.\n * @property {EventEmitter} [events] - The EventEmitter for this form.\n * @property {string} [language] - The language to render this form in.\n * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form.\n * @property {boolean} [viewAsHtml] - View the form as raw HTML.\n * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form.\n * @property {boolean} [highlightErrors] - Highlight any errors on the form.\n * @property {string} [componentErrorClass] - The error class for components.\n * @property {any} [templates] - The templates for this form.\n * @property {string} [iconset] - The iconset for this form.\n * @property {Component[]} [components] - The components for this form.\n * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form.\n * @property {boolean} [showHiddenFields] - Show hidden fields.\n * @property {{[key: string]: boolean}} [hide] - Hidden components for this form.\n * @property {{[key: string]: boolean}} [show] - Components to show for this form.\n * @property {Formio} [formio] - The Formio instance for this form.\n * @property {string} [decimalSeparator] - The decimal separator for this form.\n * @property {string} [thousandsSeparator] - The thousands separator for this form.\n * @property {FormioHooks} [hooks] - The hooks for this form.\n * @property {boolean} [alwaysDirty] - Always be dirty.\n * @property {boolean} [skipDraftRestore] - Skip restoring a draft.\n * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form.\n * @property {string} [cdnUrl] - The CDN url for this form.\n * @property {boolean} [flatten] - Flatten the form.\n * @property {boolean} [sanitize] - Sanitize the form.\n * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form.\n * @property {ButtonSettings} [buttonSettings] - The button settings for this form.\n * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form.\n * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms).\n * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms).\n * @property {boolean} [showCheckboxBackground] - Show the checkbox background.\n * @property {number} [zoom] - The zoom for PDF forms.\n */\n/**\n * Renders a Form.io form within the webpage.\n */\nclass Webform extends NestedDataComponent_1.default {\n /**\n * Creates a new Form instance.\n *\n * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance.\n * @param {FormOptions} [options] - The options to create a new form instance.\n */\n constructor(elementOrOptions, options) {\n let element, formOptions;\n if (elementOrOptions instanceof HTMLElement || options) {\n element = elementOrOptions;\n formOptions = options;\n }\n else {\n formOptions = elementOrOptions;\n }\n super(null, getOptions(formOptions));\n this.executeShortcuts = (event) => {\n const { target } = event;\n if (!this.keyboardCatchableElement(target)) {\n return;\n }\n const ctrl = event.ctrlKey || event.metaKey;\n const keyCode = event.keyCode;\n let char = '';\n if (65 <= keyCode && keyCode <= 90) {\n char = String.fromCharCode(keyCode);\n }\n else if (keyCode === 13) {\n char = 'Enter';\n }\n else if (keyCode === 27) {\n char = 'Esc';\n }\n lodash_1.default.each(this.shortcuts, (shortcut) => {\n if (shortcut.ctrl && !ctrl) {\n return;\n }\n if (shortcut.shortcut === char) {\n shortcut.element.click();\n event.preventDefault();\n }\n });\n };\n this.setElement(element);\n // Keep track of all available forms globally.\n Formio_1.Formio.forms[this.id] = this;\n // Set the base url.\n if (this.options.baseUrl) {\n Formio_1.Formio.setBaseUrl(this.options.baseUrl);\n }\n /**\n * The type of this element.\n * @type {string}\n */\n this.type = 'form';\n this._src = '';\n this._loading = false;\n this._form = {};\n this.draftEnabled = false;\n this.savingDraft = true;\n if (this.options.saveDraftThrottle) {\n this.triggerSaveDraft = lodash_1.default.throttle(this.saveDraft.bind(this), this.options.saveDraftThrottle);\n }\n else {\n this.triggerSaveDraft = this.saveDraft.bind(this);\n }\n /**\n * Determines if this form should submit the API on submit.\n * @type {boolean}\n */\n this.nosubmit = false;\n /**\n * Determines if the form has tried to be submitted, error or not.\n *\n * @type {boolean}\n */\n this.submitted = false;\n /**\n * Determines if the form is being submitted at the moment.\n *\n * @type {boolean}\n */\n this.submitting = false;\n /**\n * The Formio instance for this form.\n * @type {Formio}\n */\n this.formio = null;\n /**\n * The loader HTML element.\n * @type {HTMLElement}\n */\n this.loader = null;\n /**\n * The alert HTML element\n * @type {HTMLElement}\n */\n this.alert = null;\n /**\n * Promise that is triggered when the submission is done loading.\n * @type {Promise}\n */\n this.onSubmission = null;\n /**\n * Determines if this submission is explicitly set.\n * @type {boolean}\n */\n this.submissionSet = false;\n /**\n * Promise that executes when the form is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is ready!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n this.formReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.formReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.formReadyReject = reject;\n });\n /**\n * Promise that executes when the submission is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.submissionReady.then(() => {\n * console.log('The submission is ready!');\n * });\n * form.src = 'https://examples.form.io/example/submission/234234234234234243';\n */\n this.submissionReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.submissionReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.submissionReadyReject = reject;\n });\n this.shortcuts = [];\n // Set language after everything is established.\n this.language = this.i18next.language;\n // See if we need to restore the draft from a user.\n if (this.options.saveDraft) {\n this.formReady.then(() => {\n if (!this.options.skipDraftRestore) {\n const user = Formio_1.Formio.getUser();\n // Only restore a draft if the submission isn't explicitly set.\n if (user && !this.submissionSet) {\n this.restoreDraft(user._id);\n }\n }\n else {\n // Enable drafts\n this.draftEnabled = true;\n this.savingDraft = false;\n }\n });\n }\n this.component.clearOnHide = false;\n // Ensure the root is set to this component.\n this.root = this;\n this.localRoot = this;\n }\n /* eslint-enable max-statements */\n get language() {\n return this.options.language;\n }\n get emptyValue() {\n return null;\n }\n componentContext() {\n return this._data;\n }\n /**\n * Sets the language for this form.\n *\n * @param lang\n * @return {Promise}\n */\n set language(lang) {\n if (!this.i18next) {\n return;\n }\n this.options.language = lang;\n if (this.i18next.language === lang) {\n return;\n }\n this.i18next.changeLanguage(lang, (err) => {\n if (err) {\n return;\n }\n this.rebuild();\n this.emit('languageChanged');\n });\n }\n get componentComponents() {\n return this.form.components;\n }\n get shadowRoot() {\n return this.options.shadowRoot;\n }\n /**\n * Add a language for translations\n *\n * @param code\n * @param lang\n * @param active\n * @return {*}\n */\n addLanguage(code, lang, active = false) {\n if (this.i18next) {\n var translations = lodash_1.default.assign((0, utils_1.fastCloneDeep)(i18n_1.default.resources.en.translation), lang);\n this.i18next.addResourceBundle(code, 'translation', translations, true, true);\n if (active) {\n this.language = code;\n }\n }\n }\n keyboardCatchableElement(element) {\n if (element.nodeName === 'TEXTAREA') {\n return false;\n }\n if (element.nodeName === 'INPUT') {\n return [\n 'text',\n 'email',\n 'password'\n ].indexOf(element.type) === -1;\n }\n return true;\n }\n addShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n shortcut = lodash_1.default.capitalize(shortcut);\n if (shortcut === 'Enter' || shortcut === 'Esc') {\n // Restrict Enter and Esc only for buttons\n if (element.tagName !== 'BUTTON') {\n return;\n }\n this.shortcuts.push({\n shortcut,\n element\n });\n }\n else {\n this.shortcuts.push({\n ctrl: true,\n shortcut,\n element\n });\n }\n }\n removeShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n lodash_1.default.remove(this.shortcuts, {\n shortcut,\n element\n });\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get src() {\n return this._src;\n }\n /**\n * Loads the submission if applicable.\n */\n loadSubmission() {\n this.loadingSubmission = true;\n if (this.formio.submissionId) {\n this.onSubmission = this.formio.loadSubmission().then((submission) => this.setSubmission(submission), (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n else {\n this.submissionReadyResolve();\n }\n return this.submissionReady;\n }\n /**\n * Set the src of the form renderer.\n *\n * @param value\n * @param options\n */\n setSrc(value, options) {\n if (this.setUrl(value, options)) {\n this.nosubmit = false;\n return this.formio.loadForm({ params: { live: 1 } }).then((form) => {\n const setForm = this.setForm(form);\n this.loadSubmission();\n return setForm;\n }).catch((err) => {\n console.warn(err);\n this.formReadyReject(err);\n });\n }\n return Promise.resolve();\n }\n /**\n * Set the Form source, which is typically the Form.io embed URL.\n *\n * @param {string} value - The value of the form embed url.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is formReady!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n set src(value) {\n this.setSrc(value);\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get url() {\n return this._src;\n }\n /**\n * Sets the url of the form renderer.\n *\n * @param value\n * @param options\n */\n setUrl(value, options) {\n if (!value ||\n (typeof value !== 'string') ||\n (value === this._src)) {\n return false;\n }\n this._src = value;\n this.nosubmit = true;\n this.formio = this.options.formio = new Formio_1.Formio(value, options);\n if (this.type === 'form') {\n // Set the options source so this can be passed to other components.\n this.options.src = value;\n }\n return true;\n }\n /**\n * Set the form source but don't initialize the form and submission from the url.\n *\n * @param {string} value - The value of the form embed url.\n */\n set url(value) {\n this.setUrl(value);\n }\n /**\n * Called when both the form and submission have been loaded.\n *\n * @returns {Promise} - The promise to trigger when both form and submission have loaded.\n */\n get ready() {\n return this.formReady.then(() => {\n return super.ready.then(() => {\n return this.loadingSubmission ? this.submissionReady : true;\n });\n });\n }\n /**\n * Returns if this form is loading.\n *\n * @returns {boolean} - TRUE means the form is loading, FALSE otherwise.\n */\n get loading() {\n return this._loading;\n }\n /**\n * Set the loading state for this form, and also show the loader spinner.\n *\n * @param {boolean} loading - If this form should be \"loading\" or not.\n */\n set loading(loading) {\n if (this._loading !== loading) {\n this._loading = loading;\n if (!this.loader && loading) {\n this.loader = this.ce('div', {\n class: 'loader-wrapper'\n });\n const spinner = this.ce('div', {\n class: 'loader text-center'\n });\n this.loader.appendChild(spinner);\n }\n /* eslint-disable max-depth */\n if (this.loader) {\n try {\n if (loading) {\n this.prependTo(this.loader, this.wrapper);\n }\n else {\n this.removeChildFrom(this.loader, this.wrapper);\n }\n }\n catch (err) {\n // ingore\n }\n }\n /* eslint-enable max-depth */\n }\n }\n /**\n * Sets the JSON schema for the form to be rendered.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.setForm({\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name',\n * placeholder: 'Enter your first name.',\n * input: true\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name',\n * placeholder: 'Enter your last name',\n * input: true\n * },\n * {\n * type: 'button',\n * action: 'submit',\n * label: 'Submit',\n * theme: 'primary'\n * }\n * ]\n * });\n *\n * @param {Object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema.\n * @param flags\n * @returns {*}\n */\n setForm(form, flags) {\n var _a, _b, _c;\n const isFormAlreadySet = this._form && ((_a = this._form.components) === null || _a === void 0 ? void 0 : _a.length);\n try {\n // Do not set the form again if it has been already set\n if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) {\n return Promise.resolve();\n }\n // Create the form.\n this._form = (flags === null || flags === void 0 ? void 0 : flags.keepAsReference) ? form : lodash_1.default.cloneDeep(form);\n if (this.onSetForm) {\n this.onSetForm(lodash_1.default.cloneDeep(this._form), form);\n }\n if ((_c = (_b = this.parent) === null || _b === void 0 ? void 0 : _b.component) === null || _c === void 0 ? void 0 : _c.modalEdit) {\n return Promise.resolve();\n }\n }\n catch (err) {\n console.warn(err);\n // If provided form is not a valid JSON object, do not set it too\n return Promise.resolve();\n }\n // Allow the form to provide component overrides.\n if (form && form.settings && form.settings.components) {\n this.options.components = form.settings.components;\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options\n if (!this.options.sanitizeConfig && !this.builderMode) {\n this.options.sanitizeConfig = lodash_1.default.get(form, 'settings.sanitizeConfig') || lodash_1.default.get(form, 'globalSettings.sanitizeConfig');\n }\n if ('schema' in form && (0, compare_versions_1.compareVersions)(form.schema, '1.x') > 0) {\n this.ready.then(() => {\n this.setAlert('alert alert-danger', 'Form schema is for a newer version, please upgrade your renderer. Some functionality may not work.');\n });\n }\n // See if they pass a module, and evaluate it if so.\n if (form && form.module) {\n let formModule = null;\n if (typeof form.module === 'string') {\n try {\n formModule = this.evaluate(`return ${form.module}`);\n }\n catch (err) {\n console.warn(err);\n }\n }\n else {\n formModule = form.module;\n }\n if (formModule) {\n Formio_1.Formio.use(formModule);\n // Since we got here after instantiation, we need to manually apply form options.\n if (formModule.options && formModule.options.form) {\n this.options = Object.assign(this.options, formModule.options.form);\n }\n }\n }\n this.initialized = false;\n const rebuild = this.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n this.emit('formLoad', form);\n this.triggerCaptcha();\n // Make sure to trigger onChange after a render event occurs to speed up form rendering.\n setTimeout(() => {\n this.onChange(flags);\n this.formReadyResolve();\n }, 0);\n return this.formReady;\n });\n }\n /**\n * Gets the form object.\n *\n * @returns {Object} - The form JSON schema.\n */\n get form() {\n if (!this._form) {\n this._form = {\n components: []\n };\n }\n return this._form;\n }\n /**\n * Sets the form value.\n *\n * @alias setForm\n * @param {Object} form - The form schema object.\n */\n set form(form) {\n this.setForm(form);\n }\n /**\n * Returns the submission object that was set within this form.\n *\n * @returns {Object}\n */\n get submission() {\n return this.getValue();\n }\n /**\n * Sets the submission of a form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n *\n * @param {Object} submission - The Form.io submission object.\n */\n set submission(submission) {\n this.setSubmission(submission);\n }\n /**\n * Sets a submission and returns the promise when it is ready.\n * @param submission\n * @param flags\n * @return {Promise.<TResult>}\n */\n setSubmission(submission, flags = {}) {\n flags = Object.assign(Object.assign({}, flags), { fromSubmission: lodash_1.default.has(flags, 'fromSubmission') ? flags.fromSubmission : true });\n return this.onSubmission = this.formReady.then((resolveFlags) => {\n if (resolveFlags) {\n flags = Object.assign(Object.assign({}, flags), resolveFlags);\n }\n this.submissionSet = true;\n this.triggerChange(flags);\n this.emit('beforeSetSubmission', submission);\n this.setValue(submission, flags);\n return this.submissionReadyResolve(submission);\n }, (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n handleDraftError(errName, errDetails, restoreDraft) {\n const errorMessage = lodash_1.default.trim(`${this.t(errName)} ${errDetails || ''}`);\n console.warn(errorMessage);\n this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage);\n }\n /**\n * Saves a submission draft.\n */\n saveDraft() {\n if (!this.draftEnabled) {\n return;\n }\n if (!this.formio) {\n this.handleDraftError('saveDraftInstanceError');\n return;\n }\n if (!Formio_1.Formio.getUser()) {\n this.handleDraftError('saveDraftAuthError');\n return;\n }\n const draft = (0, utils_1.fastCloneDeep)(this.submission);\n draft.state = 'draft';\n if (!this.savingDraft && !this.submitting) {\n this.emit('saveDraftBegin');\n this.savingDraft = true;\n this.formio.saveSubmission(draft).then((sub) => {\n // Set id to submission to avoid creating new draft submission\n this.submission._id = sub._id;\n this.savingDraft = false;\n this.emit('saveDraft', sub);\n })\n .catch(err => {\n this.savingDraft = false;\n this.handleDraftError('saveDraftError', err);\n });\n }\n }\n /**\n * Restores a draft submission based on the user who is authenticated.\n *\n * @param {userId} - The user id where we need to restore the draft from.\n */\n restoreDraft(userId) {\n const formio = this.formio || this.options.formio;\n if (!formio) {\n this.handleDraftError('restoreDraftInstanceError', null, true);\n return;\n }\n this.savingDraft = true;\n formio.loadSubmissions({\n params: {\n state: 'draft',\n owner: userId,\n sort: '-created'\n }\n }).then(submissions => {\n if (submissions.length > 0 && !this.options.skipDraftRestore) {\n const draft = (0, utils_1.fastCloneDeep)(submissions[0]);\n return this.setSubmission(draft).then(() => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', draft);\n });\n }\n // Enable drafts so that we can keep track of changes.\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', null);\n })\n .catch(err => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.handleDraftError('restoreDraftError', err, true);\n });\n }\n get schema() {\n const schema = (0, utils_1.fastCloneDeep)(lodash_1.default.omit(this._form, ['components']));\n schema.components = [];\n this.eachComponent((component) => schema.components.push(component.schema));\n return schema;\n }\n mergeData(_this, _that) {\n lodash_1.default.mergeWith(_this, _that, (thisValue, thatValue) => {\n if (Array.isArray(thisValue) && Array.isArray(thatValue) && thisValue.length !== thatValue.length) {\n return thatValue;\n }\n });\n }\n setValue(submission, flags = {}) {\n if (!submission || !submission.data) {\n submission = {\n data: {},\n metadata: submission.metadata,\n };\n }\n // Metadata needs to be available before setValue\n this._submission.metadata = submission.metadata\n ? lodash_1.default.cloneDeep(submission.metadata)\n : {};\n this.editing = !!submission._id;\n // Set the timezone in the options if available.\n if (!this.options.submissionTimezone &&\n submission.metadata &&\n submission.metadata.timezone) {\n this.options.submissionTimezone = submission.metadata.timezone;\n }\n const changed = super.setValue(submission.data, flags);\n if (!flags.sanitize) {\n this.mergeData(this.data, submission.data);\n }\n submission.data = this.data;\n this._submission = submission;\n return changed;\n }\n getValue() {\n if (!this._submission.data) {\n this._submission.data = {};\n }\n if (this.viewOnly) {\n return this._submission;\n }\n const submission = this._submission;\n submission.data = this.data;\n return this._submission;\n }\n /**\n * Build the form.\n */\n init() {\n if (this.options.submission) {\n const submission = lodash_1.default.extend({}, this.options.submission);\n this._submission = submission;\n this._data = submission.data;\n }\n else {\n this._submission = this._submission || { data: {} };\n }\n // Remove any existing components.\n if (this.components && this.components.length) {\n this.destroyComponents();\n this.components = [];\n }\n if (this.component) {\n this.component.components = this.form ? this.form.components : [];\n }\n else {\n this.component = this.form;\n }\n this.component.type = 'form';\n this.component.input = false;\n this.addComponents();\n this.on('submitButton', options => {\n this.submit(false, options).catch(e => {\n options.instance.loading = false;\n return e !== false && e !== undefined && console.log(e);\n });\n }, true);\n this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true);\n this.on('requestUrl', (args) => (this.submitUrl(args.url, args.headers)), true);\n this.on('resetForm', () => this.resetValue(), true);\n this.on('deleteSubmission', () => this.deleteSubmission(), true);\n this.on('refreshData', () => this.updateValue(), true);\n this.executeFormController();\n return this.formReady;\n }\n executeFormController() {\n // If no controller value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n if (!this.form || !this.form.controller\n || ((!this.visible || this.component.hidden) && this.component.clearOnHide && !this.rootPristine)) {\n return false;\n }\n this.formReady.then(() => {\n this.evaluate(this.form.controller, {\n components: this.components,\n instance: this,\n });\n });\n }\n teardown() {\n this.emit('formDelete', this.id);\n delete Formio_1.Formio.forms[this.id];\n delete this.executeShortcuts;\n delete this.triggerSaveDraft;\n super.teardown();\n }\n destroy(all = false) {\n this.off('submitButton');\n this.off('checkValidity');\n this.off('requestUrl');\n this.off('resetForm');\n this.off('deleteSubmission');\n this.off('refreshData');\n return super.destroy(all);\n }\n build(element) {\n if (element || this.element) {\n return this.ready.then(() => {\n element = element || this.element;\n super.build(element);\n });\n }\n return this.ready;\n }\n getClassName() {\n let classes = 'formio-form';\n if (this.options.readOnly) {\n classes += ' formio-read-only';\n }\n return classes;\n }\n render() {\n return super.render(this.renderTemplate('webform', {\n classes: this.getClassName(),\n children: this.renderComponents(),\n }), this.builderMode ? 'builder' : 'form', true);\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element) {\n return Promise.resolve();\n }\n this.clear();\n this.setContent(this.element, this.render());\n return this.attach(this.element);\n }\n attach(element) {\n this.setElement(element);\n this.loadRefs(element, { webform: 'single' });\n const childPromise = this.attachComponents(this.refs.webform);\n this.addEventListener(document, 'keydown', this.executeShortcuts);\n this.currentForm = this;\n this.hook('attachWebform', element, this);\n return childPromise.then(() => {\n this.emit('render', this.element);\n return this.setValue(this._submission, {\n noUpdateEvent: true,\n });\n });\n }\n hasRequiredFields() {\n let result = false;\n (0, formUtils_1.eachComponent)(this.form.components, (component) => {\n if (component.validate.required) {\n result = true;\n return true;\n }\n }, true);\n return result;\n }\n resetValue() {\n lodash_1.default.each(this.getComponents(), (comp) => (comp.resetValue()));\n this.setPristine(true);\n this.onChange({ resetValue: true });\n }\n /**\n * Sets a new alert to display in the error dialog of the form.\n *\n * @param {string} type - The type of alert to display. \"danger\", \"success\", \"warning\", etc.\n * @param {string} message - The message to show in the alert.\n * @param {Object} options\n */\n setAlert(type, message, options) {\n if (!type && this.submitted) {\n if (this.alert) {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n return;\n }\n if (this.options.noAlerts) {\n if (!message) {\n this.emit('error', false);\n }\n return;\n }\n if (this.alert) {\n try {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n catch (err) {\n // ignore\n }\n }\n if (message) {\n const attrs = {\n class: (options && options.classes) || `alert alert-${type}`,\n id: `error-list-${this.id}`,\n };\n const templateOptions = {\n message: message instanceof HTMLElement ? message.outerHTML : message,\n attrs: attrs,\n type\n };\n this.alert = (0, utils_1.convertStringToHTMLElement)(this.renderTemplate('alert', templateOptions), `#${attrs.id}`);\n }\n if (!this.alert) {\n return;\n }\n this.loadRefs(this.alert, { errorRef: 'multiple' });\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.addEventListener(el, 'click', (e) => {\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n });\n this.addEventListener(el, 'keydown', (e) => {\n if (e.keyCode === 13) {\n e.preventDefault();\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n }\n });\n });\n }\n this.prepend(this.alert);\n }\n /**\n * Focus on selected component.\n *\n * @param {string} key - The key of selected component.\n * @returns {*}\n */\n focusOnComponent(key) {\n if (key) {\n const component = this.getComponent(key);\n if (component) {\n component.focus();\n }\n }\n }\n /**\n * Show the errors of this form within the alert dialog.\n *\n * @param {Object} error - An optional additional error to display along with the component errors.\n * @returns {*}\n */\n /* eslint-disable no-unused-vars */\n showErrors(errors, triggerEvent) {\n this.loading = false;\n if (!Array.isArray(errors)) {\n errors = [errors];\n }\n errors = errors.concat(this.customErrors).filter((err) => !!err);\n if (!errors.length) {\n this.setAlert(false);\n return;\n }\n // Mark any components as invalid if in a custom message.\n errors.forEach((err) => {\n const { components = [] } = err;\n if (err.component) {\n components.push(err.component);\n }\n if (err.path) {\n components.push(err.path);\n }\n components.forEach((path) => {\n const originalPath = (0, utils_1.getStringFromComponentPath)(path);\n const component = this.getComponent(path, lodash_1.default.identity, originalPath);\n if (err.fromServer) {\n if (component.serverErrors) {\n component.serverErrors.push(err);\n }\n else {\n component.serverErrors = [err];\n }\n }\n const components = lodash_1.default.compact(Array.isArray(component) ? component : [component]);\n components.forEach((component) => component.setCustomValidity(err.message, true));\n });\n });\n const displayedErrors = [];\n if (errors.length) {\n errors = lodash_1.default.uniqBy(errors, error => error.message);\n const createListItem = (message, index) => {\n var _a, _b, _c;\n const err = errors[index];\n const messageFromIndex = !lodash_1.default.isUndefined(index) && errors && errors[index];\n const keyOrPath = ((messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.formattedKeyOrPath) || (messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.path) || ((_a = messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.context) === null || _a === void 0 ? void 0 : _a.path)) || (((_b = err.context) === null || _b === void 0 ? void 0 : _b.component) && ((_c = err.context) === null || _c === void 0 ? void 0 : _c.component.key)) || (err.component && err.component.key) || err.fromServer && err.path;\n const formattedKeyOrPath = keyOrPath ? (0, utils_1.getStringFromComponentPath)(keyOrPath) : '';\n if (typeof err !== 'string' && !err.formattedKeyOrPath) {\n err.formattedKeyOrPath = formattedKeyOrPath;\n }\n return {\n message: (0, utils_1.unescapeHTML)(message),\n keyOrPath: formattedKeyOrPath\n };\n };\n errors.forEach(({ message, context, fromServer, component }, index) => {\n const text = !(component === null || component === void 0 ? void 0 : component.label) || (context === null || context === void 0 ? void 0 : context.hasLabel) || fromServer\n ? this.t('alertMessage', { message: this.t(message) })\n : this.t('alertMessageWithLabel', {\n label: this.t(component === null || component === void 0 ? void 0 : component.label),\n message: this.t(message),\n });\n displayedErrors.push(createListItem(text, index));\n });\n }\n const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });\n this.root.setAlert('danger', errorsList);\n if (triggerEvent) {\n this.emit('error', errors);\n }\n return errors;\n }\n /* eslint-enable no-unused-vars */\n /**\n * Called when the submission has completed, or if the submission needs to be sent to an external library.\n *\n * @param {Object} submission - The submission object.\n * @param {boolean} saved - Whether or not this submission was saved to the server.\n * @returns {object} - The submission object.\n */\n onSubmit(submission, saved) {\n var _a;\n this.loading = false;\n this.submitting = false;\n this.setPristine(true);\n // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here.\n this.setValue((0, utils_1.fastCloneDeep)(submission), {\n noValidate: true,\n noCheck: true\n });\n this.setAlert('success', `<p>${this.t('complete')}</p>`);\n // Cancel triggered saveDraft to prevent overriding the submitted state\n if (this.draftEnabled && ((_a = this.triggerSaveDraft) === null || _a === void 0 ? void 0 : _a.cancel)) {\n this.triggerSaveDraft.cancel();\n }\n this.emit('submit', submission, saved);\n if (saved) {\n this.emit('submitDone', submission);\n }\n return submission;\n }\n normalizeError(error) {\n if (error) {\n if (typeof error === 'object' && 'details' in error) {\n error = error.details;\n }\n if (typeof error === 'string') {\n error = { message: error };\n }\n }\n return error;\n }\n /**\n * Called when an error occurs during the submission.\n *\n * @param {Object} error - The error that occured.\n */\n onSubmissionError(error) {\n error = this.normalizeError(error);\n this.submitting = false;\n this.setPristine(false);\n this.emit('submitError', error || this.errors);\n // Allow for silent cancellations (no error message, no submit button error state)\n if (error && error.silent) {\n this.emit('change', { isValid: true }, { silent: true });\n return false;\n }\n const errors = this.showErrors(error, true);\n if (this.root && this.root.alert) {\n this.scrollIntoView(this.root.alert);\n }\n return errors;\n }\n /**\n * Trigger the change event for this form.\n *\n * @param changed\n * @param flags\n */\n onChange(flags, changed, modified, changes) {\n flags = flags || {};\n let isChangeEventEmitted = false;\n super.onChange(flags, true);\n const value = lodash_1.default.clone(this.submission);\n flags.changed = value.changed = changed;\n flags.changes = changes;\n if (modified && this.pristine) {\n this.pristine = false;\n }\n this.checkData(value.data, flags);\n const shouldValidate = !flags.noValidate || flags.fromIFrame || (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed);\n const errors = shouldValidate ? this.validate(value.data, Object.assign(Object.assign({}, flags), { process: 'change' })) : [];\n value.isValid = errors.length === 0;\n this.loading = false;\n if (this.submitted) {\n // show server errors while they are not cleaned/fixed\n const nonComponentServerErrors = lodash_1.default.filter(this.serverErrors || [], err => !err.component && !err.path);\n this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors);\n }\n // See if we need to save the draft of the form.\n if (modified && this.options.saveDraft) {\n this.triggerSaveDraft();\n }\n if (!flags || !flags.noEmit) {\n this.emit('change', value, flags, modified);\n isChangeEventEmitted = true;\n }\n // The form is initialized after the first change event occurs.\n if (isChangeEventEmitted && !this.initialized) {\n this.emit('initialized');\n this.initialized = true;\n }\n }\n /**\n * Send a delete request to the server.\n */\n deleteSubmission() {\n return this.formio.deleteSubmission()\n .then(() => {\n this.emit('submissionDeleted', this.submission);\n this.resetValue();\n });\n }\n /**\n * Cancels the submission.\n *\n * @alias reset\n */\n cancel(noconfirm) {\n const shouldReset = this.hook('beforeCancel', true);\n if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) {\n this.resetValue();\n return true;\n }\n else {\n this.emit('cancelSubmit');\n return false;\n }\n }\n setMetadata(submission) {\n // Add in metadata about client submitting the form\n submission.metadata = submission.metadata || {};\n lodash_1.default.defaults(submission.metadata, {\n timezone: lodash_1.default.get(this, '_submission.metadata.timezone', (0, utils_1.currentTimezone)()),\n offset: parseInt(lodash_1.default.get(this, '_submission.metadata.offset', (0, moment_1.default)().utcOffset()), 10),\n origin: document.location.origin,\n referrer: document.referrer,\n browserName: navigator.appName,\n userAgent: navigator.userAgent,\n pathName: window.location.pathname,\n onLine: navigator.onLine\n });\n }\n submitForm(options = {}) {\n this.clearServerErrors();\n return new Promise((resolve, reject) => {\n // Read-only forms should never submit.\n if (this.options.readOnly) {\n return resolve({\n submission: this.submission,\n saved: false\n });\n }\n const submission = (0, utils_1.fastCloneDeep)(this.submission || {});\n this.setMetadata(submission);\n submission.state = options.state || submission.state || 'submitted';\n const isDraft = (submission.state === 'draft');\n this.hook('beforeSubmit', Object.assign(Object.assign({}, submission), { component: options.component }), (err, data) => {\n var _a;\n if (err) {\n return reject(err);\n }\n submission._vnote = data && data._vnote ? data._vnote : '';\n try {\n if (!isDraft && !options.noValidate) {\n if (!submission.data) {\n return reject('Invalid Submission');\n }\n const errors = this.validate(submission.data, {\n dirty: true,\n silentCheck: false,\n process: 'submit'\n });\n if (errors.length || ((_a = options.beforeSubmitResults) === null || _a === void 0 ? void 0 : _a.some((result) => result.status === 'rejected'))) {\n return reject(errors);\n }\n }\n }\n catch (err) {\n console.error(err);\n }\n this.everyComponent((comp) => {\n if (submission._vnote && comp.type === 'form' && comp.component.reference) {\n lodash_1.default.get(submission.data, comp.path, {})._vnote = submission._vnote;\n }\n const { persistent } = comp.component;\n if (persistent === 'client-only') {\n lodash_1.default.unset(submission.data, comp.path);\n }\n });\n this.hook('customValidation', Object.assign(Object.assign({}, submission), { component: options.component }), (err) => {\n if (err) {\n // If string is returned, cast to object.\n if (typeof err === 'string') {\n err = {\n message: err\n };\n }\n // Ensure err is an array.\n err = Array.isArray(err) ? err : [err];\n return reject(err);\n }\n this.loading = true;\n // Use the form action to submit the form if available.\n if (this._form && this._form.action) {\n const method = (submission.data._id && this._form.action.includes(submission.data._id)) ? 'PUT' : 'POST';\n return Formio_1.Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {})\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n }\n const submitFormio = this.formio;\n if (this.nosubmit || !submitFormio) {\n return resolve({\n submission,\n saved: false,\n });\n }\n // If this is an actionUrl, then make sure to save the action and not the submission.\n const submitMethod = submitFormio.actionUrl ? 'saveAction' : 'saveSubmission';\n submitFormio[submitMethod](submission)\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n });\n });\n });\n }\n setServerErrors(error) {\n if (error.details) {\n this.serverErrors = error.details.filter((err) => err.level ? err.level === 'error' : err).map((err) => {\n err.fromServer = true;\n return err;\n });\n }\n else if (typeof error === 'string') {\n this.serverErrors = [{ fromServer: true, level: 'error', message: error }];\n }\n }\n executeSubmit(options) {\n this.submitted = true;\n this.submitting = true;\n return this.submitForm(options)\n .then(({ submission, saved }) => this.onSubmit(submission, saved))\n .then((results) => {\n this.submissionInProcess = false;\n return results;\n })\n .catch((err) => {\n this.submissionInProcess = false;\n return Promise.reject(this.onSubmissionError(err));\n });\n }\n clearServerErrors() {\n var _a;\n (_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.forEach((error) => {\n if (error.path) {\n const pathArray = (0, utils_1.getArrayFromComponentPath)(error.path);\n const component = this.getComponent(pathArray, lodash_1.default.identity, error.formattedKeyOrPath);\n if (component) {\n component.serverErrors = [];\n }\n }\n });\n this.serverErrors = [];\n }\n /**\n * Submits the form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n * form.submit().then((submission) => {\n * console.log(submission);\n * });\n *\n * @param {boolean} before - If this submission occured from the before handlers.\n *\n * @returns {Promise} - A promise when the form is done submitting.\n */\n submit(before, options = {}) {\n this.submissionInProcess = true;\n if (!before) {\n return this.beforeSubmit(options).then(() => this.executeSubmit(options));\n }\n else {\n return this.executeSubmit(options);\n }\n }\n submitUrl(URL, headers) {\n if (!URL) {\n return console.warn('Missing URL argument');\n }\n const submission = this.submission || {};\n const API_URL = URL;\n const settings = {\n method: 'POST',\n headers: {}\n };\n if (headers && headers.length > 0) {\n headers.map((e) => {\n if (e.header !== '' && e.value !== '') {\n settings.headers[e.header] = this.interpolate(e.value, submission);\n }\n });\n }\n if (API_URL && settings) {\n Formio_1.Formio.makeStaticRequest(API_URL, settings.method, submission, { headers: settings.headers }).then(() => {\n this.emit('requestDone');\n this.setAlert('success', '<p> Success </p>');\n }).catch((e) => {\n const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`;\n this.emit('error', message);\n console.error(message);\n this.setAlert('danger', `<p> ${message} </p>`);\n return Promise.reject(this.onSubmissionError(e));\n });\n }\n else {\n this.emit('error', 'You should add a URL to this button.');\n this.setAlert('warning', 'You should add a URL to this button.');\n return console.warn('You should add a URL to this button.');\n }\n }\n triggerCaptcha() {\n if (!this || !this.components) {\n return;\n }\n const captchaComponent = [];\n (0, formUtils_1.eachComponent)(this.components, (component) => {\n if (/^(re)?captcha$/.test(component.type) && component.component.eventType === 'formLoad') {\n captchaComponent.push(component);\n }\n });\n if (captchaComponent.length > 0) {\n captchaComponent[0].verify(`${this.form.name ? this.form.name : 'form'}Load`);\n }\n }\n set nosubmit(value) {\n this._nosubmit = !!value;\n this.emit('nosubmit', this._nosubmit);\n }\n get nosubmit() {\n return this._nosubmit || false;\n }\n get conditions() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.conditions) !== null && _b !== void 0 ? _b : [];\n }\n get variables() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.variables) !== null && _b !== void 0 ? _b : [];\n }\n}\nexports[\"default\"] = Webform;\nWebform.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWebform.setApiUrl = Formio_1.Formio.setApiUrl;\nWebform.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Webform.js?");
|
|
5252
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst compare_versions_1 = __webpack_require__(/*! compare-versions */ \"./node_modules/compare-versions/lib/esm/index.js\");\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst i18n_1 = __importDefault(__webpack_require__(/*! ./i18n */ \"./lib/cjs/i18n.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst NestedDataComponent_1 = __importDefault(__webpack_require__(/*! ./components/_classes/nesteddata/NestedDataComponent */ \"./lib/cjs/components/_classes/nesteddata/NestedDataComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\n// Initialize the available forms.\nFormio_1.Formio.forms = {};\n// Allow people to register components.\nFormio_1.Formio.registerComponent = Components_1.default.setComponent;\nfunction getIconSet(icons) {\n if (icons === 'fontawesome') {\n return 'fa';\n }\n return icons || '';\n}\nfunction getOptions(options) {\n options = lodash_1.default.defaults(options, {\n submitOnEnter: false,\n iconset: getIconSet((options && options.icons) ? options.icons : Formio_1.Formio.icons),\n i18next: null,\n saveDraft: false,\n alwaysDirty: false,\n saveDraftThrottle: 5000,\n display: 'form',\n cdnUrl: Formio_1.Formio.cdn.baseUrl\n });\n if (!options.events) {\n options.events = new EventEmitter_1.default();\n }\n return options;\n}\n/**\n * Represents a JSON value.\n * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON\n */\n/**\n * Represents a JSON array.\n * @typedef {Array<JSON>} JSONArray\n */\n/**\n * Represents a JSON object.\n * @typedef {{[key: string]: JSON}} JSONObject\n */\n/**\n * @typedef {Object} FormioHooks\n * @property {function} [beforeSubmit]\n * @property {function} [beforeCancel]\n * @property {function} [beforeNext]\n * @property {function} [beforePrev]\n * @property {function} [attachComponent]\n * @property {function} [setDataValue]\n * @property {function} [addComponents]\n * @property {function} [addComponent]\n * @property {function} [customValidation]\n * @property {function} [attachWebform]\n */\n/**\n * @typedef {Object} SanitizeConfig\n * @property {string[]} [addAttr]\n * @property {string[]} [addTags]\n * @property {string[]} [allowedAttrs]\n * @property {string[]} [allowedTags]\n * @property {string[]} [allowedUriRegex]\n * @property {string[]} [addUriSafeAttr]\n */\n/**\n * @typedef {Object} ButtonSettings\n * @property {boolean} [showPrevious]\n * @property {boolean} [showNext]\n * @property {boolean} [showCancel]\n * @property {boolean} [showSubmit]\n */\n/**\n * @typedef {Object} FormOptions\n * @property {boolean} [saveDraft] - Enable the save draft feature.\n * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.\n * @property {boolean} [readOnly] - Set this form to readOnly.\n * @property {boolean} [noAlerts] - Disable the alerts dialog.\n * @property {{[key: string]: string}} [i18n] - The translation file for this rendering.\n * @property {string} [template] - Custom logic for creation of elements.\n * @property {boolean} [noDefaults] - Exclude default values from the settings.\n * @property {any} [fileService] - The file service for this form.\n * @property {EventEmitter} [events] - The EventEmitter for this form.\n * @property {string} [language] - The language to render this form in.\n * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form.\n * @property {boolean} [viewAsHtml] - View the form as raw HTML.\n * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form.\n * @property {boolean} [highlightErrors] - Highlight any errors on the form.\n * @property {string} [componentErrorClass] - The error class for components.\n * @property {any} [templates] - The templates for this form.\n * @property {string} [iconset] - The iconset for this form.\n * @property {Component[]} [components] - The components for this form.\n * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form.\n * @property {boolean} [showHiddenFields] - Show hidden fields.\n * @property {{[key: string]: boolean}} [hide] - Hidden components for this form.\n * @property {{[key: string]: boolean}} [show] - Components to show for this form.\n * @property {Formio} [formio] - The Formio instance for this form.\n * @property {string} [decimalSeparator] - The decimal separator for this form.\n * @property {string} [thousandsSeparator] - The thousands separator for this form.\n * @property {FormioHooks} [hooks] - The hooks for this form.\n * @property {boolean} [alwaysDirty] - Always be dirty.\n * @property {boolean} [skipDraftRestore] - Skip restoring a draft.\n * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form.\n * @property {string} [cdnUrl] - The CDN url for this form.\n * @property {boolean} [flatten] - Flatten the form.\n * @property {boolean} [sanitize] - Sanitize the form.\n * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form.\n * @property {ButtonSettings} [buttonSettings] - The button settings for this form.\n * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form.\n * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms).\n * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms).\n * @property {boolean} [showCheckboxBackground] - Show the checkbox background.\n * @property {number} [zoom] - The zoom for PDF forms.\n */\n/**\n * Renders a Form.io form within the webpage.\n */\nclass Webform extends NestedDataComponent_1.default {\n /**\n * Creates a new Form instance.\n *\n * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance.\n * @param {FormOptions} [options] - The options to create a new form instance.\n */\n constructor(elementOrOptions, options) {\n let element, formOptions;\n if (elementOrOptions instanceof HTMLElement || options) {\n element = elementOrOptions;\n formOptions = options;\n }\n else {\n formOptions = elementOrOptions;\n }\n super(null, getOptions(formOptions));\n this.executeShortcuts = (event) => {\n const { target } = event;\n if (!this.keyboardCatchableElement(target)) {\n return;\n }\n const ctrl = event.ctrlKey || event.metaKey;\n const keyCode = event.keyCode;\n let char = '';\n if (65 <= keyCode && keyCode <= 90) {\n char = String.fromCharCode(keyCode);\n }\n else if (keyCode === 13) {\n char = 'Enter';\n }\n else if (keyCode === 27) {\n char = 'Esc';\n }\n lodash_1.default.each(this.shortcuts, (shortcut) => {\n if (shortcut.ctrl && !ctrl) {\n return;\n }\n if (shortcut.shortcut === char) {\n shortcut.element.click();\n event.preventDefault();\n }\n });\n };\n this.setElement(element);\n // Keep track of all available forms globally.\n Formio_1.Formio.forms[this.id] = this;\n // Set the base url.\n if (this.options.baseUrl) {\n Formio_1.Formio.setBaseUrl(this.options.baseUrl);\n }\n /**\n * The type of this element.\n * @type {string}\n */\n this.type = 'form';\n this._src = '';\n this._loading = false;\n this._form = {};\n this.draftEnabled = false;\n this.savingDraft = true;\n if (this.options.saveDraftThrottle) {\n this.triggerSaveDraft = lodash_1.default.throttle(this.saveDraft.bind(this), this.options.saveDraftThrottle);\n }\n else {\n this.triggerSaveDraft = this.saveDraft.bind(this);\n }\n /**\n * Determines if this form should submit the API on submit.\n * @type {boolean}\n */\n this.nosubmit = false;\n /**\n * Determines if the form has tried to be submitted, error or not.\n *\n * @type {boolean}\n */\n this.submitted = false;\n /**\n * Determines if the form is being submitted at the moment.\n *\n * @type {boolean}\n */\n this.submitting = false;\n /**\n * The Formio instance for this form.\n * @type {Formio}\n */\n this.formio = null;\n /**\n * The loader HTML element.\n * @type {HTMLElement}\n */\n this.loader = null;\n /**\n * The alert HTML element\n * @type {HTMLElement}\n */\n this.alert = null;\n /**\n * Promise that is triggered when the submission is done loading.\n * @type {Promise}\n */\n this.onSubmission = null;\n /**\n * Determines if this submission is explicitly set.\n * @type {boolean}\n */\n this.submissionSet = false;\n /**\n * Promise that executes when the form is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is ready!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n this.formReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.formReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.formReadyReject = reject;\n });\n /**\n * Promise that executes when the submission is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.submissionReady.then(() => {\n * console.log('The submission is ready!');\n * });\n * form.src = 'https://examples.form.io/example/submission/234234234234234243';\n */\n this.submissionReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.submissionReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.submissionReadyReject = reject;\n });\n this.shortcuts = [];\n // Set language after everything is established.\n this.language = this.i18next.language;\n // See if we need to restore the draft from a user.\n if (this.options.saveDraft) {\n this.formReady.then(() => {\n if (!this.options.skipDraftRestore) {\n const user = Formio_1.Formio.getUser();\n // Only restore a draft if the submission isn't explicitly set.\n if (user && !this.submissionSet) {\n this.restoreDraft(user._id);\n }\n }\n else {\n // Enable drafts\n this.draftEnabled = true;\n this.savingDraft = false;\n }\n });\n }\n this.component.clearOnHide = false;\n // Ensure the root is set to this component.\n this.root = this;\n this.localRoot = this;\n }\n /* eslint-enable max-statements */\n get language() {\n return this.options.language;\n }\n get emptyValue() {\n return null;\n }\n componentContext() {\n return this._data;\n }\n /**\n * Sets the language for this form.\n *\n * @param lang\n * @return {Promise}\n */\n set language(lang) {\n if (!this.i18next) {\n return;\n }\n this.options.language = lang;\n if (this.i18next.language === lang) {\n return;\n }\n this.i18next.changeLanguage(lang, (err) => {\n if (err) {\n return;\n }\n this.rebuild();\n this.emit('languageChanged');\n });\n }\n get componentComponents() {\n return this.form.components;\n }\n get shadowRoot() {\n return this.options.shadowRoot;\n }\n /**\n * Add a language for translations\n *\n * @param code\n * @param lang\n * @param active\n * @return {*}\n */\n addLanguage(code, lang, active = false) {\n if (this.i18next) {\n var translations = lodash_1.default.assign((0, utils_1.fastCloneDeep)(i18n_1.default.resources.en.translation), lang);\n this.i18next.addResourceBundle(code, 'translation', translations, true, true);\n if (active) {\n this.language = code;\n }\n }\n }\n keyboardCatchableElement(element) {\n if (element.nodeName === 'TEXTAREA') {\n return false;\n }\n if (element.nodeName === 'INPUT') {\n return [\n 'text',\n 'email',\n 'password'\n ].indexOf(element.type) === -1;\n }\n return true;\n }\n addShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n shortcut = lodash_1.default.capitalize(shortcut);\n if (shortcut === 'Enter' || shortcut === 'Esc') {\n // Restrict Enter and Esc only for buttons\n if (element.tagName !== 'BUTTON') {\n return;\n }\n this.shortcuts.push({\n shortcut,\n element\n });\n }\n else {\n this.shortcuts.push({\n ctrl: true,\n shortcut,\n element\n });\n }\n }\n removeShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n lodash_1.default.remove(this.shortcuts, {\n shortcut,\n element\n });\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get src() {\n return this._src;\n }\n /**\n * Loads the submission if applicable.\n */\n loadSubmission() {\n this.loadingSubmission = true;\n if (this.formio.submissionId) {\n this.onSubmission = this.formio.loadSubmission().then((submission) => this.setSubmission(submission), (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n else {\n this.submissionReadyResolve();\n }\n return this.submissionReady;\n }\n /**\n * Set the src of the form renderer.\n *\n * @param value\n * @param options\n */\n setSrc(value, options) {\n if (this.setUrl(value, options)) {\n this.nosubmit = false;\n return this.formio.loadForm({ params: { live: 1 } }).then((form) => {\n const setForm = this.setForm(form);\n this.loadSubmission();\n return setForm;\n }).catch((err) => {\n console.warn(err);\n this.formReadyReject(err);\n });\n }\n return Promise.resolve();\n }\n /**\n * Set the Form source, which is typically the Form.io embed URL.\n *\n * @param {string} value - The value of the form embed url.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is formReady!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n set src(value) {\n this.setSrc(value);\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get url() {\n return this._src;\n }\n /**\n * Sets the url of the form renderer.\n *\n * @param value\n * @param options\n */\n setUrl(value, options) {\n if (!value ||\n (typeof value !== 'string') ||\n (value === this._src)) {\n return false;\n }\n this._src = value;\n this.nosubmit = true;\n this.formio = this.options.formio = new Formio_1.Formio(value, options);\n if (this.type === 'form') {\n // Set the options source so this can be passed to other components.\n this.options.src = value;\n }\n return true;\n }\n /**\n * Set the form source but don't initialize the form and submission from the url.\n *\n * @param {string} value - The value of the form embed url.\n */\n set url(value) {\n this.setUrl(value);\n }\n /**\n * Called when both the form and submission have been loaded.\n *\n * @returns {Promise} - The promise to trigger when both form and submission have loaded.\n */\n get ready() {\n return this.formReady.then(() => {\n return super.ready.then(() => {\n return this.loadingSubmission ? this.submissionReady : true;\n });\n });\n }\n /**\n * Returns if this form is loading.\n *\n * @returns {boolean} - TRUE means the form is loading, FALSE otherwise.\n */\n get loading() {\n return this._loading;\n }\n /**\n * Set the loading state for this form, and also show the loader spinner.\n *\n * @param {boolean} loading - If this form should be \"loading\" or not.\n */\n set loading(loading) {\n if (this._loading !== loading) {\n this._loading = loading;\n if (!this.loader && loading) {\n this.loader = this.ce('div', {\n class: 'loader-wrapper'\n });\n const spinner = this.ce('div', {\n class: 'loader text-center'\n });\n this.loader.appendChild(spinner);\n }\n /* eslint-disable max-depth */\n if (this.loader) {\n try {\n if (loading) {\n this.prependTo(this.loader, this.wrapper);\n }\n else {\n this.removeChildFrom(this.loader, this.wrapper);\n }\n }\n catch (err) {\n // ingore\n }\n }\n /* eslint-enable max-depth */\n }\n }\n /**\n * Sets the JSON schema for the form to be rendered.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.setForm({\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name',\n * placeholder: 'Enter your first name.',\n * input: true\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name',\n * placeholder: 'Enter your last name',\n * input: true\n * },\n * {\n * type: 'button',\n * action: 'submit',\n * label: 'Submit',\n * theme: 'primary'\n * }\n * ]\n * });\n *\n * @param {Object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema.\n * @param flags\n * @returns {*}\n */\n setForm(form, flags) {\n var _a, _b, _c;\n const isFormAlreadySet = this._form && ((_a = this._form.components) === null || _a === void 0 ? void 0 : _a.length);\n try {\n // Do not set the form again if it has been already set\n if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) {\n return Promise.resolve();\n }\n // Create the form.\n this._form = (flags === null || flags === void 0 ? void 0 : flags.keepAsReference) ? form : lodash_1.default.cloneDeep(form);\n if (this.onSetForm) {\n this.onSetForm(lodash_1.default.cloneDeep(this._form), form);\n }\n if ((_c = (_b = this.parent) === null || _b === void 0 ? void 0 : _b.component) === null || _c === void 0 ? void 0 : _c.modalEdit) {\n return Promise.resolve();\n }\n }\n catch (err) {\n console.warn(err);\n // If provided form is not a valid JSON object, do not set it too\n return Promise.resolve();\n }\n // Allow the form to provide component overrides.\n if (form && form.settings && form.settings.components) {\n this.options.components = form.settings.components;\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options\n if (!this.options.sanitizeConfig && !this.builderMode) {\n this.options.sanitizeConfig = lodash_1.default.get(form, 'settings.sanitizeConfig') || lodash_1.default.get(form, 'globalSettings.sanitizeConfig');\n }\n if ('schema' in form && (0, compare_versions_1.compareVersions)(form.schema, '1.x') > 0) {\n this.ready.then(() => {\n this.setAlert('alert alert-danger', 'Form schema is for a newer version, please upgrade your renderer. Some functionality may not work.');\n });\n }\n // See if they pass a module, and evaluate it if so.\n if (form && form.module) {\n let formModule = null;\n if (typeof form.module === 'string') {\n try {\n formModule = this.evaluate(`return ${form.module}`);\n }\n catch (err) {\n console.warn(err);\n }\n }\n else {\n formModule = form.module;\n }\n if (formModule) {\n Formio_1.Formio.use(formModule);\n // Since we got here after instantiation, we need to manually apply form options.\n if (formModule.options && formModule.options.form) {\n this.options = Object.assign(this.options, formModule.options.form);\n }\n }\n }\n this.initialized = false;\n const rebuild = this.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n this.emit('formLoad', form);\n this.triggerCaptcha();\n // Make sure to trigger onChange after a render event occurs to speed up form rendering.\n setTimeout(() => {\n this.onChange(flags);\n this.formReadyResolve();\n }, 0);\n return this.formReady;\n });\n }\n /**\n * Gets the form object.\n *\n * @returns {Object} - The form JSON schema.\n */\n get form() {\n if (!this._form) {\n this._form = {\n components: []\n };\n }\n return this._form;\n }\n /**\n * Sets the form value.\n *\n * @alias setForm\n * @param {Object} form - The form schema object.\n */\n set form(form) {\n this.setForm(form);\n }\n /**\n * Returns the submission object that was set within this form.\n *\n * @returns {Object}\n */\n get submission() {\n return this.getValue();\n }\n /**\n * Sets the submission of a form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n *\n * @param {Object} submission - The Form.io submission object.\n */\n set submission(submission) {\n this.setSubmission(submission);\n }\n /**\n * Sets a submission and returns the promise when it is ready.\n * @param submission\n * @param flags\n * @return {Promise.<TResult>}\n */\n setSubmission(submission, flags = {}) {\n flags = Object.assign(Object.assign({}, flags), { fromSubmission: lodash_1.default.has(flags, 'fromSubmission') ? flags.fromSubmission : true });\n return this.onSubmission = this.formReady.then((resolveFlags) => {\n if (resolveFlags) {\n flags = Object.assign(Object.assign({}, flags), resolveFlags);\n }\n this.submissionSet = true;\n this.triggerChange(flags);\n this.emit('beforeSetSubmission', submission);\n this.setValue(submission, flags);\n return this.submissionReadyResolve(submission);\n }, (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n handleDraftError(errName, errDetails, restoreDraft) {\n const errorMessage = lodash_1.default.trim(`${this.t(errName)} ${errDetails || ''}`);\n console.warn(errorMessage);\n this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage);\n }\n /**\n * Saves a submission draft.\n */\n saveDraft() {\n if (!this.draftEnabled) {\n return;\n }\n if (!this.formio) {\n this.handleDraftError('saveDraftInstanceError');\n return;\n }\n if (!Formio_1.Formio.getUser()) {\n this.handleDraftError('saveDraftAuthError');\n return;\n }\n const draft = (0, utils_1.fastCloneDeep)(this.submission);\n draft.state = 'draft';\n if (!this.savingDraft && !this.submitting) {\n this.emit('saveDraftBegin');\n this.savingDraft = true;\n this.formio.saveSubmission(draft).then((sub) => {\n // Set id to submission to avoid creating new draft submission\n this.submission._id = sub._id;\n this.savingDraft = false;\n this.emit('saveDraft', sub);\n })\n .catch(err => {\n this.savingDraft = false;\n this.handleDraftError('saveDraftError', err);\n });\n }\n }\n /**\n * Restores a draft submission based on the user who is authenticated.\n *\n * @param {userId} - The user id where we need to restore the draft from.\n */\n restoreDraft(userId) {\n const formio = this.formio || this.options.formio;\n if (!formio) {\n this.handleDraftError('restoreDraftInstanceError', null, true);\n return;\n }\n this.savingDraft = true;\n formio.loadSubmissions({\n params: {\n state: 'draft',\n owner: userId,\n sort: '-created'\n }\n }).then(submissions => {\n if (submissions.length > 0 && !this.options.skipDraftRestore) {\n const draft = (0, utils_1.fastCloneDeep)(submissions[0]);\n return this.setSubmission(draft).then(() => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', draft);\n });\n }\n // Enable drafts so that we can keep track of changes.\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', null);\n })\n .catch(err => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.handleDraftError('restoreDraftError', err, true);\n });\n }\n get schema() {\n const schema = (0, utils_1.fastCloneDeep)(lodash_1.default.omit(this._form, ['components']));\n schema.components = [];\n this.eachComponent((component) => schema.components.push(component.schema));\n return schema;\n }\n mergeData(_this, _that) {\n lodash_1.default.mergeWith(_this, _that, (thisValue, thatValue) => {\n if (Array.isArray(thisValue) && Array.isArray(thatValue) && thisValue.length !== thatValue.length) {\n return thatValue;\n }\n });\n }\n setValue(submission, flags = {}) {\n if (!submission || !submission.data) {\n submission = {\n data: {},\n metadata: submission.metadata,\n };\n }\n // Metadata needs to be available before setValue\n this._submission.metadata = submission.metadata\n ? lodash_1.default.cloneDeep(submission.metadata)\n : {};\n this.editing = !!submission._id;\n // Set the timezone in the options if available.\n if (!this.options.submissionTimezone &&\n submission.metadata &&\n submission.metadata.timezone) {\n this.options.submissionTimezone = submission.metadata.timezone;\n }\n const changed = super.setValue(submission.data, flags);\n if (!flags.sanitize) {\n this.mergeData(this.data, submission.data);\n }\n submission.data = this.data;\n this._submission = submission;\n return changed;\n }\n getValue() {\n if (!this._submission.data) {\n this._submission.data = {};\n }\n if (this.viewOnly) {\n return this._submission;\n }\n const submission = this._submission;\n submission.data = this.data;\n return this._submission;\n }\n /**\n * Build the form.\n */\n init() {\n if (this.options.submission) {\n const submission = lodash_1.default.extend({}, this.options.submission);\n this._submission = submission;\n this._data = submission.data;\n }\n else {\n this._submission = this._submission || { data: {} };\n }\n // Remove any existing components.\n if (this.components && this.components.length) {\n this.destroyComponents();\n this.components = [];\n }\n if (this.component) {\n this.component.components = this.form ? this.form.components : [];\n }\n else {\n this.component = this.form;\n }\n this.component.type = 'form';\n this.component.input = false;\n this.addComponents();\n this.on('submitButton', options => {\n this.submit(false, options).catch(e => {\n options.instance.loading = false;\n return e !== false && e !== undefined && console.log(e);\n });\n }, true);\n this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true);\n this.on('requestUrl', (args) => (this.submitUrl(args.url, args.headers)), true);\n this.on('resetForm', () => this.resetValue(), true);\n this.on('deleteSubmission', () => this.deleteSubmission(), true);\n this.on('refreshData', () => this.updateValue(), true);\n this.executeFormController();\n return this.formReady;\n }\n executeFormController() {\n // If no controller value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n if (!this.form || !this.form.controller\n || ((!this.visible || this.component.hidden) && this.component.clearOnHide && !this.rootPristine)) {\n return false;\n }\n this.formReady.then(() => {\n this.evaluate(this.form.controller, {\n components: this.components,\n instance: this,\n });\n });\n }\n teardown() {\n this.emit('formDelete', this.id);\n delete Formio_1.Formio.forms[this.id];\n delete this.executeShortcuts;\n delete this.triggerSaveDraft;\n super.teardown();\n }\n destroy(all = false) {\n this.off('submitButton');\n this.off('checkValidity');\n this.off('requestUrl');\n this.off('resetForm');\n this.off('deleteSubmission');\n this.off('refreshData');\n return super.destroy(all);\n }\n build(element) {\n if (element || this.element) {\n return this.ready.then(() => {\n element = element || this.element;\n super.build(element);\n });\n }\n return this.ready;\n }\n getClassName() {\n let classes = 'formio-form';\n if (this.options.readOnly) {\n classes += ' formio-read-only';\n }\n return classes;\n }\n render() {\n return super.render(this.renderTemplate('webform', {\n classes: this.getClassName(),\n children: this.renderComponents(),\n }), this.builderMode ? 'builder' : 'form', true);\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element) {\n return Promise.resolve();\n }\n this.clear();\n this.setContent(this.element, this.render());\n return this.attach(this.element);\n }\n attach(element) {\n this.setElement(element);\n this.loadRefs(element, { webform: 'single' });\n const childPromise = this.attachComponents(this.refs.webform);\n this.addEventListener(document, 'keydown', this.executeShortcuts);\n this.currentForm = this;\n this.hook('attachWebform', element, this);\n return childPromise.then(() => {\n this.emit('render', this.element);\n return this.setValue(this._submission, {\n noUpdateEvent: true,\n });\n });\n }\n hasRequiredFields() {\n let result = false;\n (0, formUtils_1.eachComponent)(this.form.components, (component) => {\n if (component.validate.required) {\n result = true;\n return true;\n }\n }, true);\n return result;\n }\n resetValue() {\n lodash_1.default.each(this.getComponents(), (comp) => (comp.resetValue()));\n this.setPristine(true);\n this.onChange({ resetValue: true });\n }\n /**\n * Sets a new alert to display in the error dialog of the form.\n *\n * @param {string} type - The type of alert to display. \"danger\", \"success\", \"warning\", etc.\n * @param {string} message - The message to show in the alert.\n * @param {Object} options\n */\n setAlert(type, message, options) {\n if (!type && this.submitted) {\n if (this.alert) {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n return;\n }\n if (this.options.noAlerts) {\n if (!message) {\n this.emit('error', false);\n }\n return;\n }\n if (this.alert) {\n try {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n catch (err) {\n // ignore\n }\n }\n if (message) {\n const attrs = {\n class: (options && options.classes) || `alert alert-${type}`,\n id: `error-list-${this.id}`,\n };\n const templateOptions = {\n message: message instanceof HTMLElement ? message.outerHTML : message,\n attrs: attrs,\n type\n };\n this.alert = (0, utils_1.convertStringToHTMLElement)(this.renderTemplate('alert', templateOptions), `#${attrs.id}`);\n }\n if (!this.alert) {\n return;\n }\n this.loadRefs(this.alert, { errorRef: 'multiple' });\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.addEventListener(el, 'click', (e) => {\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n });\n this.addEventListener(el, 'keydown', (e) => {\n if (e.keyCode === 13) {\n e.preventDefault();\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n }\n });\n });\n }\n this.prepend(this.alert);\n }\n /**\n * Focus on selected component.\n *\n * @param {string} key - The key of selected component.\n * @returns {*}\n */\n focusOnComponent(key) {\n if (key) {\n const component = this.getComponent(key);\n if (component) {\n component.focus();\n }\n }\n }\n /**\n * Show the errors of this form within the alert dialog.\n *\n * @param {Object} error - An optional additional error to display along with the component errors.\n * @returns {*}\n */\n /* eslint-disable no-unused-vars */\n showErrors(errors, triggerEvent) {\n this.loading = false;\n if (!Array.isArray(errors)) {\n errors = [errors];\n }\n errors = errors.concat(this.customErrors).filter((err) => !!err);\n if (!errors.length) {\n this.setAlert(false);\n return;\n }\n // Mark any components as invalid if in a custom message.\n errors.forEach((err) => {\n const { components = [] } = err;\n if (err.component) {\n components.push(err.component);\n }\n if (err.path) {\n components.push(err.path);\n }\n components.forEach((path) => {\n const originalPath = (0, utils_1.getStringFromComponentPath)(path);\n const component = this.getComponent(path, lodash_1.default.identity, originalPath);\n if (err.fromServer) {\n if (component.serverErrors) {\n component.serverErrors.push(err);\n }\n else {\n component.serverErrors = [err];\n }\n }\n const components = lodash_1.default.compact(Array.isArray(component) ? component : [component]);\n components.forEach((component) => component.setCustomValidity(err.message, true));\n });\n });\n const displayedErrors = [];\n if (errors.length) {\n errors = lodash_1.default.uniqBy(errors, error => error.message);\n const createListItem = (message, index) => {\n var _a, _b, _c;\n const err = errors[index];\n const messageFromIndex = !lodash_1.default.isUndefined(index) && errors && errors[index];\n const keyOrPath = ((messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.formattedKeyOrPath) || (messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.path) || ((_a = messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.context) === null || _a === void 0 ? void 0 : _a.path)) || (((_b = err.context) === null || _b === void 0 ? void 0 : _b.component) && ((_c = err.context) === null || _c === void 0 ? void 0 : _c.component.key)) || (err.component && err.component.key) || err.fromServer && err.path;\n const formattedKeyOrPath = keyOrPath ? (0, utils_1.getStringFromComponentPath)(keyOrPath) : '';\n if (typeof err !== 'string' && !err.formattedKeyOrPath) {\n err.formattedKeyOrPath = formattedKeyOrPath;\n }\n return {\n message: (0, utils_1.unescapeHTML)(message),\n keyOrPath: formattedKeyOrPath\n };\n };\n errors.forEach(({ message, context, fromServer, component }, index) => {\n const text = !(component === null || component === void 0 ? void 0 : component.label) || (context === null || context === void 0 ? void 0 : context.hasLabel) || fromServer\n ? this.t('alertMessage', { message: this.t(message) })\n : this.t('alertMessageWithLabel', {\n label: this.t(component === null || component === void 0 ? void 0 : component.label),\n message: this.t(message),\n });\n displayedErrors.push(createListItem(text, index));\n });\n }\n const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });\n this.root.setAlert('danger', errorsList);\n if (triggerEvent) {\n this.emit('error', errors);\n }\n return errors;\n }\n /* eslint-enable no-unused-vars */\n /**\n * Called when the submission has completed, or if the submission needs to be sent to an external library.\n *\n * @param {Object} submission - The submission object.\n * @param {boolean} saved - Whether or not this submission was saved to the server.\n * @returns {object} - The submission object.\n */\n onSubmit(submission, saved) {\n var _a;\n this.loading = false;\n this.submitting = false;\n this.setPristine(true);\n // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here.\n this.setValue((0, utils_1.fastCloneDeep)(submission), {\n noValidate: true,\n noCheck: true\n });\n this.setAlert('success', `<p>${this.t('complete')}</p>`);\n // Cancel triggered saveDraft to prevent overriding the submitted state\n if (this.draftEnabled && ((_a = this.triggerSaveDraft) === null || _a === void 0 ? void 0 : _a.cancel)) {\n this.triggerSaveDraft.cancel();\n }\n this.emit('submit', submission, saved);\n if (saved) {\n this.emit('submitDone', submission);\n }\n return submission;\n }\n normalizeError(error) {\n if (error) {\n if (typeof error === 'object' && 'details' in error) {\n error = error.details;\n }\n if (typeof error === 'string') {\n error = { message: error };\n }\n }\n return error;\n }\n /**\n * Called when an error occurs during the submission.\n *\n * @param {Object} error - The error that occured.\n */\n onSubmissionError(error) {\n error = this.normalizeError(error);\n this.submitting = false;\n this.setPristine(false);\n this.emit('submitError', error || this.errors);\n // Allow for silent cancellations (no error message, no submit button error state)\n if (error && error.silent) {\n this.emit('change', { isValid: true }, { silent: true });\n return false;\n }\n const errors = this.showErrors(error, true);\n if (this.root && this.root.alert) {\n this.scrollIntoView(this.root.alert);\n }\n return errors;\n }\n /**\n * Trigger the change event for this form.\n *\n * @param changed\n * @param flags\n */\n onChange(flags, changed, modified, changes) {\n var _a;\n flags = flags || {};\n let isChangeEventEmitted = false;\n // If this Webform is a nested form, continue to bubble `modified` change to the root\n if (((_a = this.parent) === null || _a === void 0 ? void 0 : _a.subForm) === this) {\n super.onChange(Object.assign(Object.assign({}, flags), { modified }), false);\n }\n else {\n super.onChange(flags, true);\n }\n const value = lodash_1.default.clone(this.submission);\n flags.changed = value.changed = changed;\n flags.changes = changes;\n if (modified && this.pristine) {\n this.pristine = false;\n }\n this.checkData(value.data, flags);\n const shouldValidate = !flags.noValidate || flags.fromIFrame || (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed);\n const errors = shouldValidate ? this.validate(value.data, Object.assign(Object.assign({}, flags), { process: 'change' })) : [];\n value.isValid = errors.length === 0;\n this.loading = false;\n if (this.submitted) {\n // show server errors while they are not cleaned/fixed\n const nonComponentServerErrors = lodash_1.default.filter(this.serverErrors || [], err => !err.component && !err.path);\n this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors);\n }\n // See if we need to save the draft of the form.\n if (modified && this.options.saveDraft) {\n this.triggerSaveDraft();\n }\n if (!flags || !flags.noEmit) {\n this.emit('change', value, flags, modified);\n isChangeEventEmitted = true;\n }\n // The form is initialized after the first change event occurs.\n if (isChangeEventEmitted && !this.initialized) {\n this.emit('initialized');\n this.initialized = true;\n }\n }\n /**\n * Send a delete request to the server.\n */\n deleteSubmission() {\n return this.formio.deleteSubmission()\n .then(() => {\n this.emit('submissionDeleted', this.submission);\n this.resetValue();\n });\n }\n /**\n * Cancels the submission.\n *\n * @alias reset\n */\n cancel(noconfirm) {\n const shouldReset = this.hook('beforeCancel', true);\n if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) {\n this.resetValue();\n return true;\n }\n else {\n this.emit('cancelSubmit');\n return false;\n }\n }\n setMetadata(submission) {\n // Add in metadata about client submitting the form\n submission.metadata = submission.metadata || {};\n lodash_1.default.defaults(submission.metadata, {\n timezone: lodash_1.default.get(this, '_submission.metadata.timezone', (0, utils_1.currentTimezone)()),\n offset: parseInt(lodash_1.default.get(this, '_submission.metadata.offset', (0, moment_1.default)().utcOffset()), 10),\n origin: document.location.origin,\n referrer: document.referrer,\n browserName: navigator.appName,\n userAgent: navigator.userAgent,\n pathName: window.location.pathname,\n onLine: navigator.onLine\n });\n }\n submitForm(options = {}) {\n this.clearServerErrors();\n return new Promise((resolve, reject) => {\n // Read-only forms should never submit.\n if (this.options.readOnly) {\n return resolve({\n submission: this.submission,\n saved: false\n });\n }\n const submission = (0, utils_1.fastCloneDeep)(this.submission || {});\n this.setMetadata(submission);\n submission.state = options.state || submission.state || 'submitted';\n const isDraft = (submission.state === 'draft');\n this.hook('beforeSubmit', Object.assign(Object.assign({}, submission), { component: options.component }), (err, data) => {\n var _a;\n if (err) {\n return reject(err);\n }\n submission._vnote = data && data._vnote ? data._vnote : '';\n try {\n if (!isDraft && !options.noValidate) {\n if (!submission.data) {\n return reject('Invalid Submission');\n }\n const errors = this.validate(submission.data, {\n dirty: true,\n silentCheck: false,\n process: 'submit'\n });\n if (errors.length || ((_a = options.beforeSubmitResults) === null || _a === void 0 ? void 0 : _a.some((result) => result.status === 'rejected'))) {\n return reject(errors);\n }\n }\n }\n catch (err) {\n console.error(err);\n }\n this.everyComponent((comp) => {\n if (submission._vnote && comp.type === 'form' && comp.component.reference) {\n lodash_1.default.get(submission.data, comp.path, {})._vnote = submission._vnote;\n }\n const { persistent } = comp.component;\n if (persistent === 'client-only') {\n lodash_1.default.unset(submission.data, comp.path);\n }\n });\n this.hook('customValidation', Object.assign(Object.assign({}, submission), { component: options.component }), (err) => {\n if (err) {\n // If string is returned, cast to object.\n if (typeof err === 'string') {\n err = {\n message: err\n };\n }\n // Ensure err is an array.\n err = Array.isArray(err) ? err : [err];\n return reject(err);\n }\n this.loading = true;\n // Use the form action to submit the form if available.\n if (this._form && this._form.action) {\n const method = (submission.data._id && this._form.action.includes(submission.data._id)) ? 'PUT' : 'POST';\n return Formio_1.Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {})\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n }\n const submitFormio = this.formio;\n if (this.nosubmit || !submitFormio) {\n return resolve({\n submission,\n saved: false,\n });\n }\n // If this is an actionUrl, then make sure to save the action and not the submission.\n const submitMethod = submitFormio.actionUrl ? 'saveAction' : 'saveSubmission';\n submitFormio[submitMethod](submission)\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n });\n });\n });\n }\n setServerErrors(error) {\n if (error.details) {\n this.serverErrors = error.details.filter((err) => err.level ? err.level === 'error' : err).map((err) => {\n err.fromServer = true;\n return err;\n });\n }\n else if (typeof error === 'string') {\n this.serverErrors = [{ fromServer: true, level: 'error', message: error }];\n }\n }\n executeSubmit(options) {\n this.submitted = true;\n this.submitting = true;\n return this.submitForm(options)\n .then(({ submission, saved }) => this.onSubmit(submission, saved))\n .then((results) => {\n this.submissionInProcess = false;\n return results;\n })\n .catch((err) => {\n this.submissionInProcess = false;\n return Promise.reject(this.onSubmissionError(err));\n });\n }\n clearServerErrors() {\n var _a;\n (_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.forEach((error) => {\n if (error.path) {\n const pathArray = (0, utils_1.getArrayFromComponentPath)(error.path);\n const component = this.getComponent(pathArray, lodash_1.default.identity, error.formattedKeyOrPath);\n if (component) {\n component.serverErrors = [];\n }\n }\n });\n this.serverErrors = [];\n }\n /**\n * Submits the form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n * form.submit().then((submission) => {\n * console.log(submission);\n * });\n *\n * @param {boolean} before - If this submission occured from the before handlers.\n *\n * @returns {Promise} - A promise when the form is done submitting.\n */\n submit(before, options = {}) {\n this.submissionInProcess = true;\n if (!before) {\n return this.beforeSubmit(options).then(() => this.executeSubmit(options));\n }\n else {\n return this.executeSubmit(options);\n }\n }\n submitUrl(URL, headers) {\n if (!URL) {\n return console.warn('Missing URL argument');\n }\n const submission = this.submission || {};\n const API_URL = URL;\n const settings = {\n method: 'POST',\n headers: {}\n };\n if (headers && headers.length > 0) {\n headers.map((e) => {\n if (e.header !== '' && e.value !== '') {\n settings.headers[e.header] = this.interpolate(e.value, submission);\n }\n });\n }\n if (API_URL && settings) {\n Formio_1.Formio.makeStaticRequest(API_URL, settings.method, submission, { headers: settings.headers }).then(() => {\n this.emit('requestDone');\n this.setAlert('success', '<p> Success </p>');\n }).catch((e) => {\n const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`;\n this.emit('error', message);\n console.error(message);\n this.setAlert('danger', `<p> ${message} </p>`);\n return Promise.reject(this.onSubmissionError(e));\n });\n }\n else {\n this.emit('error', 'You should add a URL to this button.');\n this.setAlert('warning', 'You should add a URL to this button.');\n return console.warn('You should add a URL to this button.');\n }\n }\n triggerCaptcha() {\n if (!this || !this.components) {\n return;\n }\n const captchaComponent = [];\n (0, formUtils_1.eachComponent)(this.components, (component) => {\n if (/^(re)?captcha$/.test(component.type) && component.component.eventType === 'formLoad') {\n captchaComponent.push(component);\n }\n });\n if (captchaComponent.length > 0) {\n captchaComponent[0].verify(`${this.form.name ? this.form.name : 'form'}Load`);\n }\n }\n set nosubmit(value) {\n this._nosubmit = !!value;\n this.emit('nosubmit', this._nosubmit);\n }\n get nosubmit() {\n return this._nosubmit || false;\n }\n get conditions() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.conditions) !== null && _b !== void 0 ? _b : [];\n }\n get variables() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.variables) !== null && _b !== void 0 ? _b : [];\n }\n}\nexports[\"default\"] = Webform;\nWebform.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWebform.setApiUrl = Formio_1.Formio.setApiUrl;\nWebform.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Webform.js?");
|
|
5252
5253
|
|
|
5253
5254
|
/***/ }),
|
|
5254
5255
|
|
|
@@ -6414,7 +6415,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6414
6415
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
6415
6416
|
|
|
6416
6417
|
"use strict";
|
|
6417
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./lib/cjs/utils/conditionOperators/ConditionOperator.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass IsEmptyValue extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEmpty';\n }\n static get displayedName() {\n return 'Is Empty';\n }\n static get requireValue() {\n return false;\n }\n execute({ value, instance, conditionComponentPath }) {\n
|
|
6418
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./lib/cjs/utils/conditionOperators/ConditionOperator.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass IsEmptyValue extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEmpty';\n }\n static get displayedName() {\n return 'Is Empty';\n }\n static get requireValue() {\n return false;\n }\n execute({ value, instance, conditionComponentPath }) {\n const isEmptyValue = lodash_1.default.isEmpty(value);\n if (instance && instance.root) {\n const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);\n return conditionTriggerComponent ? conditionTriggerComponent.isEmpty() : isEmptyValue;\n }\n return isEmptyValue;\n }\n getResult(options) {\n return this.execute(options);\n }\n}\nexports[\"default\"] = IsEmptyValue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/conditionOperators/IsEmptyValue.js?");
|
|
6418
6419
|
|
|
6419
6420
|
/***/ }),
|
|
6420
6421
|
|
|
@@ -6425,7 +6426,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6425
6426
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
6426
6427
|
|
|
6427
6428
|
"use strict";
|
|
6428
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./lib/cjs/utils/conditionOperators/ConditionOperator.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils */ \"./lib/cjs/utils/utils.js\");\nclass IsEqualTo extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEqual';\n }\n static get displayedName() {\n return 'Is Equal To';\n }\n execute({ value, comparedValue, instance, conditionComponentPath }) {\n var _a
|
|
6429
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst ConditionOperator_1 = __importDefault(__webpack_require__(/*! ./ConditionOperator */ \"./lib/cjs/utils/conditionOperators/ConditionOperator.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils */ \"./lib/cjs/utils/utils.js\");\nclass IsEqualTo extends ConditionOperator_1.default {\n static get operatorKey() {\n return 'isEqual';\n }\n static get displayedName() {\n return 'Is Equal To';\n }\n execute({ value, comparedValue, instance, conditionComponentPath }) {\n var _a;\n if ((value || value === false) && comparedValue && typeof value !== typeof comparedValue && lodash_1.default.isString(comparedValue)) {\n try {\n comparedValue = JSON.parse(comparedValue);\n }\n // eslint-disable-next-line no-empty\n catch (e) { }\n }\n if (instance && instance.root) {\n const conditionTriggerComponent = instance.root.getComponent(conditionComponentPath);\n if (conditionTriggerComponent\n && (0, utils_1.isSelectResourceWithObjectValue)(conditionTriggerComponent.component)\n && ((_a = conditionTriggerComponent.component) === null || _a === void 0 ? void 0 : _a.template)) {\n if (!value || !lodash_1.default.isPlainObject(value)) {\n return false;\n }\n const { template, valueProperty } = conditionTriggerComponent.component;\n if (valueProperty === 'data') {\n value = { data: value };\n comparedValue = { data: comparedValue };\n }\n return lodash_1.default.every((0, utils_1.getItemTemplateKeys)(template) || [], k => lodash_1.default.isEqual(lodash_1.default.get(value, k), lodash_1.default.get(comparedValue, k)));\n }\n }\n //special check for select boxes\n if (lodash_1.default.isObject(value) && comparedValue && lodash_1.default.isBoolean(value[comparedValue])) {\n return value[comparedValue];\n }\n return lodash_1.default.isEqual(value, comparedValue);\n }\n}\nexports[\"default\"] = IsEqualTo;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/conditionOperators/IsEqualTo.js?");
|
|
6429
6430
|
|
|
6430
6431
|
/***/ }),
|
|
6431
6432
|
|
|
@@ -6568,7 +6569,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
|
|
|
6568
6569
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
6569
6570
|
|
|
6570
6571
|
"use strict";
|
|
6571
|
-
eval("\n/* global jQuery */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.removeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.moment = exports.ConditionOperators = exports.jsonLogic = void 0;\nexports.isSelectResourceWithObjectValue = exports.getItemTemplateKeys = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isInsideScopingComponent = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = exports.withSwitch = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nexports._ = lodash_1.default;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst json_logic_js_1 = __importDefault(__webpack_require__(/*! json-logic-js */ \"./node_modules/json-logic-js/logic.js\"));\nexports.jsonLogic = json_logic_js_1.default;\nconst moment_timezone_1 = __importDefault(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nconst jstimezonedetect_1 = __importDefault(__webpack_require__(/*! jstimezonedetect */ \"./node_modules/jstimezonedetect/dist/jstz.min.js\"));\nconst operators_1 = __webpack_require__(/*! ./jsonlogic/operators */ \"./lib/cjs/utils/jsonlogic/operators.js\");\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.js\"));\nconst formUtils_1 = __webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nexports.Evaluator = Evaluator_1.default;\nconst conditionOperators_1 = __importDefault(__webpack_require__(/*! ./conditionOperators */ \"./lib/cjs/utils/conditionOperators/index.js\"));\nexports.ConditionOperators = conditionOperators_1.default;\nconst interpolate = Evaluator_1.default.interpolate;\nexports.interpolate = interpolate;\nconst { fetch } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\n__exportStar(__webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\"), exports);\n// Configure JsonLogic\noperators_1.lodashOperators.forEach((name) => json_logic_js_1.default.add_operation(`_${name}`, lodash_1.default[name]));\n// Retrieve Any Date\njson_logic_js_1.default.add_operation('getDate', (date) => {\n return (0, moment_timezone_1.default)(date).toISOString();\n});\n// Set Relative Minimum Date\njson_logic_js_1.default.add_operation('relativeMinDate', (relativeMinDate) => {\n return (0, moment_timezone_1.default)().subtract(relativeMinDate, 'days').toISOString();\n});\n// Set Relative Maximum Date\njson_logic_js_1.default.add_operation('relativeMaxDate', (relativeMaxDate) => {\n return (0, moment_timezone_1.default)().add(relativeMaxDate, 'days').toISOString();\n});\nexports.moment = __importStar(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nfunction setPathToComponentAndPerentSchema(component) {\n component.path = getComponentPath(component);\n const dataParent = getDataParentComponent(component);\n if (dataParent && typeof dataParent === 'object') {\n dataParent.path = getComponentPath(dataParent);\n }\n}\n/**\n * Evaluate a method.\n *\n * @param func\n * @param args\n * @return {*}\n */\nfunction evaluate(func, args, ret, tokenize) {\n let returnVal = null;\n const component = args.component ? args.component : { key: 'unknown' };\n if (!args.form && args.instance) {\n args.form = lodash_1.default.get(args.instance, 'root._form', {});\n }\n const componentKey = component.key;\n if (typeof func === 'string') {\n if (ret) {\n func += `;return ${ret}`;\n }\n if (tokenize) {\n // Replace all {{ }} references with actual data.\n func = func.replace(/({{\\s+(.*)\\s+}})/, (match, $1, $2) => {\n if ($2.indexOf('data.') === 0) {\n return lodash_1.default.get(args.data, $2.replace('data.', ''));\n }\n else if ($2.indexOf('row.') === 0) {\n return lodash_1.default.get(args.row, $2.replace('row.', ''));\n }\n // Support legacy...\n return lodash_1.default.get(args.data, $2);\n });\n }\n try {\n func = Evaluator_1.default.evaluator(func, args);\n args = lodash_1.default.values(args);\n }\n catch (err) {\n console.warn(`An error occured within the custom function for ${componentKey}`, err);\n returnVal = null;\n func = false;\n }\n }\n if (typeof func === 'function') {\n try {\n returnVal = Evaluator_1.default.evaluate(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (typeof func === 'object') {\n try {\n returnVal = json_logic_js_1.default.apply(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (func) {\n console.warn(`Unknown function type for ${componentKey}`);\n }\n return returnVal;\n}\nexports.evaluate = evaluate;\nfunction getRandomComponentId() {\n return `e${Math.random().toString(36).substring(7)}`;\n}\nexports.getRandomComponentId = getRandomComponentId;\n/**\n * Get a property value of an element.\n *\n * @param style\n * @param prop\n * @return {number}\n */\nfunction getPropertyValue(style, prop) {\n let value = style.getPropertyValue(prop);\n value = value ? value.replace(/[^0-9.]/g, '') : '0';\n return parseFloat(value);\n}\nexports.getPropertyValue = getPropertyValue;\n/**\n * Get an elements bounding rectagle.\n *\n * @param element\n * @return {{x: string, y: string, width: string, height: string}}\n */\nfunction getElementRect(element) {\n const style = window.getComputedStyle(element, null);\n return {\n x: getPropertyValue(style, 'left'),\n y: getPropertyValue(style, 'top'),\n width: getPropertyValue(style, 'width'),\n height: getPropertyValue(style, 'height')\n };\n}\nexports.getElementRect = getElementRect;\n/**\n * Get non HTMLElement property in the window object\n * @param {String} property\n * @return {any || undefined}\n */\nfunction getScriptPlugin(property) {\n const obj = window[property];\n if (typeof HTMLElement === 'object' ? obj instanceof HTMLElement : //DOM2\n obj && typeof obj === 'object' && true && obj.nodeType === 1 && typeof obj.nodeName === 'string') {\n return undefined;\n }\n return obj;\n}\nexports.getScriptPlugin = getScriptPlugin;\n/**\n * Determines the boolean value of a setting.\n *\n * @param value\n * @return {boolean}\n */\nfunction boolValue(value) {\n if (lodash_1.default.isBoolean(value)) {\n return value;\n }\n else if (lodash_1.default.isString(value)) {\n return (value.toLowerCase() === 'true');\n }\n else {\n return !!value;\n }\n}\nexports.boolValue = boolValue;\n/**\n * Check to see if an ID is a mongoID.\n * @param text\n * @return {Array|{index: number, input: string}|Boolean|*}\n */\nfunction isMongoId(text) {\n return text.toString().match(/^[0-9a-fA-F]{24}$/);\n}\nexports.isMongoId = isMongoId;\n/**\n * Checks the calculated value for a provided component and data.\n *\n * @param {Object} component\n * The component to check for the calculated value.\n * @param {Object} submission\n * A submission object.\n * @param data\n * The full submission data.\n */\nfunction checkCalculated(component, submission, rowData) {\n // Process calculated value stuff if present.\n if (component.calculateValue) {\n lodash_1.default.set(rowData, component.key, evaluate(component.calculateValue, {\n value: undefined,\n data: submission ? submission.data : rowData,\n row: rowData,\n util: this,\n component\n }, 'value'));\n }\n}\nexports.checkCalculated = checkCalculated;\n/**\n * Check if a simple conditional evaluates to true.\n *\n * @param condition\n * @param condition\n * @param row\n * @param data\n * @param instance\n * @returns {boolean}\n */\nfunction getConditionalPathsRecursive(conditionPaths, data) {\n let currentGlobalIndex = 0;\n const conditionalPathsArray = [];\n const getConditionalPaths = (data, currentPath = '', localIndex = 0) => {\n currentPath = currentPath.replace(/^\\.+|\\.+$/g, '');\n const currentLocalIndex = localIndex;\n const currentData = lodash_1.default.get(data, currentPath);\n if (Array.isArray(currentData) && currentData.filter(Boolean).length > 0) {\n if (currentData.some(element => typeof element !== 'object')) {\n return;\n }\n const hasInnerDataArray = currentData.find(x => Array.isArray(x[conditionPaths[currentLocalIndex]]));\n if (hasInnerDataArray) {\n currentData.forEach((_, indexOutside) => {\n const innerCompDataPath = `${currentPath}[${indexOutside}].${conditionPaths[currentLocalIndex]}`;\n getConditionalPaths(data, innerCompDataPath, currentLocalIndex + 1);\n });\n }\n else {\n currentData.forEach((x, index) => {\n if (!lodash_1.default.isNil(x[conditionPaths[currentLocalIndex]])) {\n const compDataPath = `${currentPath}[${index}].${conditionPaths[currentLocalIndex]}`;\n conditionalPathsArray.push(compDataPath);\n }\n });\n }\n }\n else {\n if (!conditionPaths[currentGlobalIndex]) {\n return;\n }\n currentGlobalIndex = currentGlobalIndex + 1;\n getConditionalPaths(data, `${currentPath}.${conditionPaths[currentGlobalIndex - 1]}`, currentGlobalIndex);\n }\n };\n getConditionalPaths(data);\n return conditionalPathsArray;\n}\nfunction checkSimpleConditional(component, condition, row, data, instance) {\n if (condition.when) {\n const value = getComponentActualValue(condition.when, data, row);\n const eq = String(condition.eq);\n const show = String(condition.show);\n // Special check for selectboxes component.\n if (lodash_1.default.isObject(value) && lodash_1.default.has(value, condition.eq)) {\n return String(value[condition.eq]) === show;\n }\n // FOR-179 - Check for multiple values.\n if (Array.isArray(value) && value.map(String).includes(eq)) {\n return show === 'true';\n }\n return (String(value) === eq) === (show === 'true');\n }\n else {\n const { conditions = [], conjunction = 'all', show = true } = condition;\n if (!conditions.length) {\n return true;\n }\n const conditionsResult = lodash_1.default.map(conditions, (cond) => {\n var _a, _b;\n const { value: comparedValue, operator, component: conditionComponentPath } = cond;\n if (!conditionComponentPath) {\n return true;\n }\n const splittedConditionPath = conditionComponentPath.split('.');\n const conditionalPaths = ((_a = instance === null || instance === void 0 ? void 0 : instance.parent) === null || _a === void 0 ? void 0 : _a.type) === 'datagrid' || ((_b = instance === null || instance === void 0 ? void 0 : instance.parent) === null || _b === void 0 ? void 0 : _b.type) === 'editgrid' ? [] : getConditionalPathsRecursive(splittedConditionPath, data);\n if (conditionalPaths.length > 0) {\n return conditionalPaths.map((path) => {\n const value = getComponentActualValue(path, data, row);\n const ConditionOperator = conditionOperators_1.default[operator];\n return ConditionOperator\n ? new ConditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath })\n : true;\n });\n }\n else {\n const value = getComponentActualValue(conditionComponentPath, data, row);\n const СonditionOperator = conditionOperators_1.default[operator];\n return СonditionOperator\n ? new СonditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath })\n : true;\n }\n });\n let result = false;\n switch (conjunction) {\n case 'any':\n result = lodash_1.default.some(conditionsResult.flat(), res => !!res);\n break;\n default:\n result = lodash_1.default.every(conditionsResult.flat(), res => !!res);\n }\n return show ? result : !result;\n }\n}\nexports.checkSimpleConditional = checkSimpleConditional;\nfunction getComponentActualValue(compPath, data, row) {\n let value = null;\n if (row) {\n value = (0, formUtils_1.getValue)({ data: row }, compPath);\n }\n if (data && lodash_1.default.isNil(value)) {\n value = (0, formUtils_1.getValue)({ data }, compPath);\n }\n // FOR-400 - Fix issue where falsey values were being evaluated as show=true\n if (lodash_1.default.isNil(value) || (lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value))) {\n value = '';\n }\n return value;\n}\nexports.getComponentActualValue = getComponentActualValue;\n/**\n * Check custom javascript conditional.\n *\n * @param component\n * @param custom\n * @param row\n * @param data\n * @returns {*}\n */\nfunction checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {\n if (typeof custom === 'string') {\n custom = `var ${variable} = true; ${custom}; return ${variable};`;\n }\n const value = (instance && instance.evaluate) ?\n instance.evaluate(custom, { row, data, form }) :\n evaluate(custom, { row, data, form });\n if (value === null) {\n return onError;\n }\n return value;\n}\nexports.checkCustomConditional = checkCustomConditional;\nfunction checkJsonConditional(component, json, row, data, form, onError) {\n try {\n return json_logic_js_1.default.apply(json, {\n data,\n row,\n form,\n _: lodash_1.default,\n });\n }\n catch (err) {\n console.warn(`An error occurred in jsonLogic advanced condition for ${component.key}`, err);\n return onError;\n }\n}\nexports.checkJsonConditional = checkJsonConditional;\nfunction getRow(component, row, instance, conditional) {\n var _a;\n const condition = conditional || component.conditional;\n // If no component's instance passed (happens only in 6.x server), calculate its path based on the schema\n if (!instance) {\n instance = lodash_1.default.cloneDeep(component);\n setPathToComponentAndPerentSchema(instance);\n }\n const dataParent = getDataParentComponent(instance);\n const parentPath = dataParent ? getComponentPath(dataParent) : null;\n const isTriggerCondtionComponentPath = condition.when || !condition.conditions\n ? (_a = condition.when) === null || _a === void 0 ? void 0 : _a.startsWith(parentPath)\n : lodash_1.default.some(condition.conditions, cond => cond.component.startsWith(parentPath));\n if (dataParent && isTriggerCondtionComponentPath) {\n const newRow = {};\n lodash_1.default.set(newRow, parentPath, row);\n row = newRow;\n }\n return row;\n}\n/**\n * Checks the conditions for a provided component and data.\n *\n * @param component\n * The component to check for the condition.\n * @param row\n * The data within a row\n * @param data\n * The full submission data.\n *\n * @returns {boolean}\n */\nfunction checkCondition(component, row, data, form, instance) {\n const { customConditional, conditional } = component;\n if (customConditional) {\n return checkCustomConditional(component, customConditional, row, data, form, 'show', true, instance);\n }\n else if (conditional && (conditional.when || lodash_1.default.some(conditional.conditions || [], condition => condition.component && condition.operator))) {\n row = getRow(component, row, instance);\n return checkSimpleConditional(component, conditional, row, data, instance);\n }\n else if (conditional && conditional.json) {\n return checkJsonConditional(component, conditional.json, row, data, form, true);\n }\n // Default to show.\n return true;\n}\nexports.checkCondition = checkCondition;\n/**\n * Test a trigger on a component.\n *\n * @param component\n * @param action\n * @param data\n * @param row\n * @returns {mixed}\n */\nfunction checkTrigger(component, trigger, row, data, form, instance) {\n // If trigger is empty, don't fire it\n if (!trigger || !trigger[trigger.type]) {\n return false;\n }\n switch (trigger.type) {\n case 'simple':\n row = getRow(component, row, instance, trigger.simple);\n return checkSimpleConditional(component, trigger.simple, row, data, instance);\n case 'javascript':\n return checkCustomConditional(component, trigger.javascript, row, data, form, 'result', false, instance);\n case 'json':\n return checkJsonConditional(component, trigger.json, row, data, form, false);\n }\n // If none of the types matched, don't fire the trigger.\n return false;\n}\nexports.checkTrigger = checkTrigger;\nfunction setActionProperty(component, action, result, row, data, instance) {\n const property = action.property.value;\n switch (action.property.type) {\n case 'boolean': {\n const currentValue = lodash_1.default.get(component, property, false).toString();\n const newValue = action.state.toString();\n if (currentValue !== newValue) {\n lodash_1.default.set(component, property, newValue === 'true');\n }\n break;\n }\n case 'string': {\n const evalData = {\n data,\n row,\n component,\n result,\n };\n const textValue = action.property.component ? action[action.property.component] : action.text;\n const currentValue = lodash_1.default.get(component, property, '');\n const newValue = (instance && instance.interpolate)\n ? instance.interpolate(textValue, evalData)\n : Evaluator_1.default.interpolate(textValue, evalData);\n if (newValue !== currentValue) {\n lodash_1.default.set(component, property, newValue);\n }\n break;\n }\n }\n return component;\n}\nexports.setActionProperty = setActionProperty;\n/**\n * Removes HTML tags from string e.g. <div>Hello World</div> => Hello World\n * @param {string} str\n * @returns {string}\n */\nfunction removeHTML(str) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return (doc.body.textContent || '').trim();\n}\nexports.removeHTML = removeHTML;\n/**\n * Unescape HTML characters like <, >, & and etc.\n * @param str\n * @returns {string}\n */\nfunction unescapeHTML(str) {\n if (typeof window === 'undefined' || !('DOMParser' in window)) {\n return str;\n }\n const elem = document.createElement('textarea');\n elem.innerHTML = str;\n return elem.value;\n}\nexports.unescapeHTML = unescapeHTML;\n/**\n * Make HTML element from string\n * @param str\n * @param selector\n * @returns {HTMLElement}\n */\nfunction convertStringToHTMLElement(str, selector) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.body.querySelector(selector);\n}\nexports.convertStringToHTMLElement = convertStringToHTMLElement;\n/**\n * Make a filename guaranteed to be unique.\n * @param name\n * @param template\n * @param evalContext\n * @returns {string}\n */\nfunction uniqueName(name, template, evalContext) {\n template = template || '{{fileName}}-{{guid}}';\n //include guid in template anyway, to prevent overwriting issue if filename matches existing file\n if (!template.includes('{{guid}}')) {\n template = `${template}-{{guid}}`;\n }\n const parts = name.split('.');\n let fileName = parts.slice(0, parts.length - 1).join('.');\n const extension = parts.length > 1\n ? `.${lodash_1.default.last(parts)}`\n : '';\n //allow only 100 characters from original name to avoid issues with filename length restrictions\n fileName = fileName.substr(0, 100);\n evalContext = Object.assign(evalContext || {}, {\n fileName,\n guid: guid()\n });\n //only letters, numbers, dots, dashes, underscores and spaces are allowed. Anything else will be replaced with dash\n const uniqueName = `${Evaluator_1.default.interpolate(template, evalContext)}${extension}`.replace(/[^0-9a-zA-Z.\\-_ ]/g, '-');\n return uniqueName;\n}\nexports.uniqueName = uniqueName;\nfunction guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x'\n ? r\n : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\nexports.guid = guid;\n/**\n * Return a translated date setting.\n *\n * @param date\n * @return {(null|Date)}\n */\nfunction getDateSetting(date) {\n if (lodash_1.default.isNil(date) || lodash_1.default.isNaN(date) || date === '') {\n return null;\n }\n if (date instanceof Date) {\n return date;\n }\n else if (typeof date.toDate === 'function') {\n return date.isValid() ? date.toDate() : null;\n }\n let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? (0, moment_timezone_1.default)(date) : null;\n if (dateSetting && dateSetting.isValid()) {\n return dateSetting.toDate();\n }\n dateSetting = null;\n try {\n const value = Evaluator_1.default.evaluator(`return ${date};`, 'moment')(moment_timezone_1.default);\n if (typeof value === 'string') {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n else if (typeof value.toDate === 'function') {\n dateSetting = (0, moment_timezone_1.default)(value.toDate().toUTCString());\n }\n else if (value instanceof Date) {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n }\n catch (e) {\n return null;\n }\n if (!dateSetting) {\n return null;\n }\n // Ensure this is a date.\n if (!dateSetting.isValid()) {\n return null;\n }\n return dateSetting.toDate();\n}\nexports.getDateSetting = getDateSetting;\nfunction isValidDate(date) {\n return lodash_1.default.isDate(date) && !lodash_1.default.isNaN(date.getDate());\n}\nexports.isValidDate = isValidDate;\n/**\n * Get the current timezone string.\n *\n * @return {string}\n */\nfunction currentTimezone() {\n if (moment_timezone_1.default.currentTimezone) {\n return moment_timezone_1.default.currentTimezone;\n }\n moment_timezone_1.default.currentTimezone = jstimezonedetect_1.default.determine().name();\n return moment_timezone_1.default.currentTimezone;\n}\nexports.currentTimezone = currentTimezone;\n/**\n * Get an offset date provided a date object and timezone object.\n *\n * @param date\n * @param timezone\n * @return {Date}\n */\nfunction offsetDate(date, timezone) {\n if (timezone === 'UTC') {\n return {\n date: new Date(date.getTime() + (date.getTimezoneOffset() * 60000)),\n abbr: 'UTC'\n };\n }\n const dateMoment = (0, moment_timezone_1.default)(date).tz(timezone);\n return {\n date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)),\n abbr: dateMoment.format('z')\n };\n}\nexports.offsetDate = offsetDate;\n/**\n * Returns if the zones are loaded.\n *\n * @return {boolean}\n */\nfunction zonesLoaded() {\n return moment_timezone_1.default.zonesLoaded;\n}\nexports.zonesLoaded = zonesLoaded;\n/**\n * Returns if we should load the zones.\n *\n * @param timezone\n * @return {boolean}\n */\nfunction shouldLoadZones(timezone) {\n if (timezone === currentTimezone() || timezone === 'UTC') {\n return false;\n }\n return true;\n}\nexports.shouldLoadZones = shouldLoadZones;\n/**\n * Externally load the timezone data.\n *\n * @return {Promise<any> | *}\n */\nfunction loadZones(url, timezone) {\n if (timezone && !shouldLoadZones(timezone)) {\n // Return non-resolving promise.\n return new Promise(lodash_1.default.noop);\n }\n if (moment_timezone_1.default.zonesPromise) {\n return moment_timezone_1.default.zonesPromise;\n }\n return moment_timezone_1.default.zonesPromise = fetch(url)\n .then(resp => resp.json().then(zones => {\n moment_timezone_1.default.tz.load(zones);\n moment_timezone_1.default.zonesLoaded = true;\n // Trigger a global event that the timezones have finished loading.\n if (document && document.createEvent && document.body && document.body.dispatchEvent) {\n var event = document.createEvent('Event');\n event.initEvent('zonesLoaded', true, true);\n document.body.dispatchEvent(event);\n }\n }));\n}\nexports.loadZones = loadZones;\n/**\n * Get the moment date object for translating dates with timezones.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {*}\n */\nfunction momentDate(value, format, timezone) {\n const momentDate = (0, moment_timezone_1.default)(value);\n if (!timezone) {\n return momentDate;\n }\n if (timezone === 'UTC') {\n timezone = 'Etc/UTC';\n }\n if ((timezone !== currentTimezone() || (format && format.match(/\\s(z$|z\\s)/))) && moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone);\n }\n return momentDate;\n}\nexports.momentDate = momentDate;\n/**\n * Format a date provided a value, format, and timezone object.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) {\n const momentDate = (0, moment_timezone_1.default)(value, flatPickrInputFormat || undefined);\n if (timezone === currentTimezone()) {\n // See if our format contains a \"z\" timezone character.\n if (format.match(/\\s(z$|z\\s)/)) {\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone).format(convertFormatToMoment(format));\n }\n else {\n return momentDate.format(convertFormatToMoment(format.replace(/\\s(z$|z\\s)/, '')));\n }\n }\n // Return the standard format.\n return momentDate.format(convertFormatToMoment(format));\n }\n if (timezone === 'UTC') {\n const offset = offsetDate(momentDate.toDate(), 'UTC');\n return `${(0, moment_timezone_1.default)(offset.date).format(convertFormatToMoment(format))} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded && timezone) {\n return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`);\n }\n else {\n return momentDate.format(convertFormatToMoment(format));\n }\n}\nexports.formatDate = formatDate;\n/**\n * Pass a format function to format within a timezone.\n *\n * @param formatFn\n * @param date\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatOffset(timezonesUrl, formatFn, date, format, timezone) {\n if (timezone === currentTimezone()) {\n return formatFn(date, format);\n }\n if (timezone === 'UTC') {\n return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n const offset = offsetDate(date, timezone);\n return `${formatFn(offset.date, format)} ${offset.abbr}`;\n }\n else {\n return formatFn(date, format);\n }\n}\nexports.formatOffset = formatOffset;\nfunction getLocaleDateFormatInfo(locale) {\n const formatInfo = {};\n const day = 21;\n const exampleDate = new Date(2017, 11, day);\n const localDateString = exampleDate.toLocaleDateString(locale);\n formatInfo.dayFirst = localDateString.slice(0, 2) === day.toString();\n return formatInfo;\n}\nexports.getLocaleDateFormatInfo = getLocaleDateFormatInfo;\n/**\n * Convert the format from the angular-datepicker module to flatpickr format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToFlatpickr(format) {\n return format\n // Remove the Z timezone offset, not supported by flatpickr.\n .replace(/Z/g, '')\n // Year conversion.\n .replace(/y/g, 'Y')\n .replace('YYYY', 'Y')\n .replace('YY', 'y')\n // Month conversion.\n .replace('MMMM', 'F')\n .replace(/M/g, 'n')\n .replace('nnn', 'M')\n .replace('nn', 'm')\n // Day in month.\n .replace(/d/g, 'j')\n .replace(/jj/g, 'd')\n // Day in week.\n .replace('EEEE', 'l')\n .replace('EEE', 'D')\n // Hours, minutes, seconds\n .replace('HH', 'H')\n .replace('hh', 'G')\n .replace('mm', 'i')\n .replace('ss', 'S')\n .replace(/a/g, 'K');\n}\nexports.convertFormatToFlatpickr = convertFormatToFlatpickr;\n/**\n * Convert the format from the angular-datepicker module to moment format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToMoment(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y')\n // Day in month.\n .replace(/d/g, 'D')\n // Day in week.\n .replace(/E/g, 'd')\n // AM/PM marker\n .replace(/a/g, 'A')\n // Unix Timestamp\n .replace(/U/g, 'X');\n}\nexports.convertFormatToMoment = convertFormatToMoment;\nfunction convertFormatToMask(format) {\n return format\n // Long month replacement.\n .replace(/M{4}/g, 'MM')\n // Initial short month conversion.\n .replace(/M{3}/g, '***')\n // Short month conversion if input as text.\n .replace(/e/g, 'Q')\n // Month number conversion.\n .replace(/W/g, '99')\n // Year conversion.\n .replace(/[ydhmswHMG]/g, '9')\n // AM/PM conversion.\n .replace(/a/g, 'AA');\n}\nexports.convertFormatToMask = convertFormatToMask;\n/**\n * Returns an input mask that is compatible with the input mask library.\n * @param {string} mask - The Form.io input mask.\n * @param {string} placeholderChar - Char which is used as a placeholder.\n * @returns {Array} - The input mask for the mask library.\n */\nfunction getInputMask(mask, placeholderChar) {\n if (mask instanceof Array) {\n return mask;\n }\n const maskArray = [];\n maskArray.numeric = true;\n for (let i = 0; i < mask.length; i++) {\n switch (mask[i]) {\n case '9':\n maskArray.push(/\\d/);\n break;\n case 'A':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z]/);\n break;\n case 'a':\n maskArray.numeric = false;\n maskArray.push(/[a-z]/);\n break;\n case '*':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z0-9]/);\n break;\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n case placeholderChar:\n maskArray.numeric = false;\n maskArray.push(' ');\n break;\n default:\n maskArray.numeric = false;\n maskArray.push(mask[i]);\n break;\n }\n }\n return maskArray;\n}\nexports.getInputMask = getInputMask;\nfunction unmaskValue(value, mask, placeholderChar) {\n if (!mask || !value || value.length > mask.length) {\n return value;\n }\n let unmaskedValue = value.split('');\n for (let i = 0; i < mask.length; i++) {\n const char = value[i] || '';\n const charPart = mask[i];\n if (!lodash_1.default.isRegExp(charPart) && char === charPart) {\n unmaskedValue[i] = '';\n }\n }\n unmaskedValue = unmaskedValue.join('').replace(placeholderChar, '');\n return unmaskedValue;\n}\nexports.unmaskValue = unmaskValue;\nfunction matchInputMask(value, inputMask) {\n if (!inputMask) {\n return true;\n }\n // If value is longer than mask, it isn't valid.\n if (value.length > inputMask.length) {\n return false;\n }\n for (let i = 0; i < inputMask.length; i++) {\n const char = value[i] || '';\n const charPart = inputMask[i];\n if (!(lodash_1.default.isRegExp(charPart) && charPart.test(char) || charPart === char)) {\n return false;\n }\n }\n return true;\n}\nexports.matchInputMask = matchInputMask;\nfunction getNumberSeparators(lang = 'en') {\n const formattedNumberString = (12345.6789).toLocaleString(lang);\n const delimeters = formattedNumberString.match(/..(.)...(.)../);\n if (!delimeters) {\n return {\n delimiter: ',',\n decimalSeparator: '.'\n };\n }\n return {\n delimiter: (delimeters.length > 1) ? delimeters[1] : ',',\n decimalSeparator: (delimeters.length > 2) ? delimeters[2] : '.',\n };\n}\nexports.getNumberSeparators = getNumberSeparators;\nfunction getNumberDecimalLimit(component, defaultLimit) {\n if (lodash_1.default.has(component, 'decimalLimit')) {\n return lodash_1.default.get(component, 'decimalLimit');\n }\n // Determine the decimal limit. Defaults to 20 but can be overridden by validate.step or decimalLimit settings.\n let decimalLimit = defaultLimit || 20;\n const step = lodash_1.default.get(component, 'validate.step', 'any');\n if (step !== 'any') {\n const parts = step.toString().split('.');\n if (parts.length > 1) {\n decimalLimit = parts[1].length;\n }\n }\n return decimalLimit;\n}\nexports.getNumberDecimalLimit = getNumberDecimalLimit;\nfunction getCurrencyAffixes({ currency, decimalLimit, decimalSeparator, lang, }) {\n // Get the prefix and suffix from the localized string.\n let regex = `(.*)?${(100).toLocaleString(lang)}`;\n if (decimalLimit) {\n regex += `${decimalSeparator === '.' ? '\\\\.' : decimalSeparator}${(0).toLocaleString(lang)}{${decimalLimit}}`;\n }\n regex += '(.*)?';\n const parts = (100).toLocaleString(lang, {\n style: 'currency',\n currency: currency ? currency : 'USD',\n useGrouping: true,\n maximumFractionDigits: decimalLimit || 0,\n minimumFractionDigits: decimalLimit || 0\n }).replace('.', decimalSeparator).match(new RegExp(regex));\n return {\n prefix: (parts === null || parts === void 0 ? void 0 : parts[1]) || '',\n suffix: (parts === null || parts === void 0 ? void 0 : parts[2]) || ''\n };\n}\nexports.getCurrencyAffixes = getCurrencyAffixes;\n/**\n * Fetch the field data provided a component.\n *\n * @param data\n * @param component\n * @return {*}\n */\nfunction fieldData(data, component) {\n if (!data) {\n return '';\n }\n if (!component || !component.key) {\n return data;\n }\n if (component.key.includes('.')) {\n let value = data;\n const parts = component.key.split('.');\n let key = '';\n for (let i = 0; i < parts.length; i++) {\n key = parts[i];\n // Handle nested resources\n if (value.hasOwnProperty('_id')) {\n value = value.data;\n }\n // Return if the key is not found on the value.\n if (!value.hasOwnProperty(key)) {\n return;\n }\n // Convert old single field data in submissions to multiple\n if (key === parts[parts.length - 1] && component.multiple && !Array.isArray(value[key])) {\n value[key] = [value[key]];\n }\n // Set the value of this key.\n value = value[key];\n }\n return value;\n }\n else {\n // Convert old single field data in submissions to multiple\n if (component.multiple && !Array.isArray(data[component.key])) {\n data[component.key] = [data[component.key]];\n }\n // Fix for checkbox type radio submission values in tableView\n if (component.type === 'checkbox' && component.inputType === 'radio') {\n return data[component.name] === component.value;\n }\n return data[component.key];\n }\n}\nexports.fieldData = fieldData;\n/**\n * Delays function execution with possibility to execute function synchronously or cancel it.\n *\n * @param fn Function to delay\n * @param delay Delay time\n * @return {*}\n */\nfunction delay(fn, delay = 0, ...args) {\n const timer = setTimeout(fn, delay, ...args);\n function cancel() {\n clearTimeout(timer);\n }\n function earlyCall() {\n cancel();\n return fn(...args);\n }\n earlyCall.timer = timer;\n earlyCall.cancel = cancel;\n return earlyCall;\n}\nexports.delay = delay;\n/**\n * Iterate the given key to make it unique.\n *\n * @param {String} key\n * Modify the component key to be unique.\n *\n * @returns {String}\n * The new component key.\n */\nfunction iterateKey(key) {\n if (!key.match(/(\\d+)$/)) {\n return `${key}1`;\n }\n return key.replace(/(\\d+)$/, function (suffix) {\n return Number(suffix) + 1;\n });\n}\nexports.iterateKey = iterateKey;\n/**\n * Determines a unique key within a map provided the base key.\n *\n * @param map\n * @param base\n * @return {*}\n */\nfunction uniqueKey(map, base) {\n let newKey = base;\n while (map.hasOwnProperty(newKey)) {\n newKey = iterateKey(newKey);\n }\n return newKey;\n}\nexports.uniqueKey = uniqueKey;\n/**\n * Determines the major version number of bootstrap.\n *\n * @return {number}\n */\nfunction bootstrapVersion(options) {\n if (options.bootstrap) {\n return options.bootstrap;\n }\n if ((typeof jQuery === 'function') && (typeof jQuery().collapse === 'function')) {\n return parseInt(jQuery.fn.collapse.Constructor.VERSION.split('.')[0], 10);\n }\n if (window.bootstrap && window.bootstrap.Collapse) {\n return parseInt(window.bootstrap.Collapse.VERSION.split('.')[0], 10);\n }\n return 0;\n}\nexports.bootstrapVersion = bootstrapVersion;\n/**\n * Retrun provided argument.\n * If argument is a function, returns the result of a function call.\n * @param {*} e;\n *\n * @return {*}\n */\nfunction unfold(e) {\n if (typeof e === 'function') {\n return e();\n }\n return e;\n}\nexports.unfold = unfold;\n/**\n * Map values through unfold and return first non-nil value.\n * @param {Array<T>} collection;\n *\n * @return {T}\n */\nexports.firstNonNil = lodash_1.default.flow([\n lodash_1.default.partialRight(lodash_1.default.map, unfold),\n lodash_1.default.partialRight(lodash_1.default.find, v => !lodash_1.default.isUndefined(v))\n]);\n/*\n * Create enclosed state.\n * Returns functions to getting and cycling between states.\n * @param {*} a - initial state.\n * @param {*} b - next state.\n * @return {Functions[]} -- [get, toggle];\n */\nfunction withSwitch(a, b) {\n let state = a;\n let next = b;\n function get() {\n return state;\n }\n function toggle() {\n const prev = state;\n state = next;\n next = prev;\n }\n return [get, toggle];\n}\nexports.withSwitch = withSwitch;\nfunction observeOverload(callback, options = {}) {\n const { limit = 50, delay = 500 } = options;\n let callCount = 0;\n let timeoutID = 0;\n const reset = () => callCount = 0;\n return () => {\n if (timeoutID !== 0) {\n clearTimeout(timeoutID);\n timeoutID = 0;\n }\n timeoutID = setTimeout(reset, delay);\n callCount += 1;\n if (callCount >= limit) {\n clearTimeout(timeoutID);\n reset();\n return callback();\n }\n };\n}\nexports.observeOverload = observeOverload;\nfunction getContextComponents(context, excludeNested, excludedTypes = []) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component, path) => {\n const addToContextComponents = excludeNested ? !component.tree : true;\n if (component.key !== context.data.key && addToContextComponents && !lodash_1.default.includes(excludedTypes, component.type)) {\n values.push({\n label: `${component.label || component.key} (${path})`,\n value: path,\n });\n }\n });\n return values;\n}\nexports.getContextComponents = getContextComponents;\nfunction getContextButtons(context) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component) => {\n if (component.type === 'button') {\n values.push({\n label: `${component.key} (${component.label})`,\n value: component.key,\n });\n }\n });\n return values;\n}\nexports.getContextButtons = getContextButtons;\n// Tags that could be in text, that should be ommited or handled in a special way\nconst inTextTags = ['#text', 'A', 'B', 'EM', 'I', 'SMALL', 'STRONG', 'SUB', 'SUP', 'INS', 'DEL', 'MARK', 'CODE'];\n/**\n * Helper function for 'translateHTMLTemplate'. Translates text value of the passed html element.\n *\n * @param {HTMLElement} elem\n * @param {Function} translate\n *\n * @returns {String}\n * Translated element template.\n */\nfunction translateElemValue(elem, translate) {\n if (!elem.innerText) {\n return elem.innerHTML;\n }\n const elemValue = elem.innerText.replace(Evaluator_1.default.templateSettings.interpolate, '').replace(/\\s\\s+/g, ' ').trim();\n const translatedValue = translate(elemValue);\n if (elemValue !== translatedValue) {\n const links = elem.innerHTML.match(/<a[^>]*>(.*?)<\\/a>/g);\n if (links && links.length) {\n if (links.length === 1 && links[0].length === elem.innerHTML.length) {\n return elem.innerHTML.replace(elemValue, translatedValue);\n }\n const translatedLinks = links.map(link => {\n const linkElem = document.createElement('a');\n linkElem.innerHTML = link;\n return translateElemValue(linkElem, translate);\n });\n return `${translatedValue} (${translatedLinks.join(', ')})`;\n }\n else {\n return elem.innerText.replace(elemValue, translatedValue);\n }\n }\n else {\n return elem.innerHTML;\n }\n}\n/**\n * Helper function for 'translateHTMLTemplate'. Goes deep through html tag children and calls function to translate their text values.\n *\n * @param {HTMLElement} tag\n * @param {Function} translate\n *\n * @returns {void}\n */\nfunction translateDeepTag(tag, translate) {\n const children = tag.children.length && [...tag.children];\n const shouldTranslateEntireContent = children && children.every(child => child.children.length === 0\n && inTextTags.some(tag => child.nodeName === tag));\n if (!children || shouldTranslateEntireContent) {\n tag.innerHTML = translateElemValue(tag, translate);\n }\n else {\n children.forEach(child => translateDeepTag(child, translate));\n }\n}\n/**\n * Translates text values in html template.\n *\n * @param {String} template\n * @param {Function} translate\n *\n * @returns {String}\n * Html template with translated values.\n */\nfunction translateHTMLTemplate(template, translate) {\n const isHTML = /<[^>]*>/.test(template);\n if (!isHTML) {\n return translate(template);\n }\n const tempElem = document.createElement('div');\n tempElem.innerHTML = template;\n if (tempElem.innerText && tempElem.children.length) {\n translateDeepTag(tempElem, translate);\n return tempElem.innerHTML;\n }\n return template;\n}\nexports.translateHTMLTemplate = translateHTMLTemplate;\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n if (typeof dompurify_1.default.sanitize !== 'function') {\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target'],\n USE_PROFILES: { html: true }\n };\n // Use profiles\n if (options.sanitizeConfig && options.sanitizeConfig.useProfiles) {\n Object.keys(options.sanitizeConfig.useProfiles).forEach(key => {\n sanitizeOptions.USE_PROFILES[key] = options.sanitizeConfig.useProfiles[key];\n });\n }\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n const allowedUriRegex = options.sanitizeConfig.allowedUriRegex;\n sanitizeOptions.ALLOWED_URI_REGEXP = lodash_1.default.isString(allowedUriRegex) ? new RegExp(allowedUriRegex) : allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify_1.default.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n/**\n * Fast cloneDeep for JSON objects only.\n */\nfunction fastCloneDeep(obj) {\n return obj ? JSON.parse(JSON.stringify(obj)) : obj;\n}\nexports.fastCloneDeep = fastCloneDeep;\nfunction isInputComponent(componentJson) {\n if (componentJson.input === false || componentJson.input === true) {\n return componentJson.input;\n }\n switch (componentJson.type) {\n case 'htmlelement':\n case 'content':\n case 'columns':\n case 'fieldset':\n case 'panel':\n case 'table':\n case 'tabs':\n case 'well':\n case 'button':\n return false;\n default:\n return true;\n }\n}\nexports.isInputComponent = isInputComponent;\nfunction getArrayFromComponentPath(pathStr) {\n if (!pathStr || !lodash_1.default.isString(pathStr)) {\n if (!lodash_1.default.isArray(pathStr)) {\n return [pathStr];\n }\n return pathStr;\n }\n return pathStr.replace(/[[\\]]/g, '.')\n .replace(/\\.\\./g, '.')\n .replace(/(^\\.)|(\\.$)/g, '')\n .split('.')\n .map(part => lodash_1.default.defaultTo(lodash_1.default.toNumber(part), part));\n}\nexports.getArrayFromComponentPath = getArrayFromComponentPath;\nfunction isChildOf(child, parent) {\n while (child && child.parent) {\n if (child.parent === parent) {\n return true;\n }\n child = child.parent;\n }\n return false;\n}\nexports.isChildOf = isChildOf;\nfunction getStringFromComponentPath(path) {\n if (!lodash_1.default.isArray(path)) {\n return path;\n }\n let strPath = '';\n path.forEach((part, i) => {\n if (lodash_1.default.isNumber(part)) {\n strPath += `[${part}]`;\n }\n else {\n strPath += i === 0 ? part : `.${part}`;\n }\n });\n return strPath;\n}\nexports.getStringFromComponentPath = getStringFromComponentPath;\nfunction round(number, precision) {\n if (lodash_1.default.isNumber(number)) {\n return number.toFixed(precision);\n }\n return number;\n}\nexports.round = round;\n/**\n * Check for Internet Explorer browser version\n *\n * @return {(number|null)}\n */\nfunction getIEBrowserVersion() {\n const { ie, version } = getBrowserInfo();\n return ie ? version : null;\n}\nexports.getIEBrowserVersion = getIEBrowserVersion;\n/**\n * Get browser name and version (modified from 'jquery-browser-plugin')\n *\n * @return {Object} -- {{browser name, version, isWebkit?}}\n * Possible browser names: chrome, safari, ie, edge, opera, mozilla, yabrowser\n */\nfunction getBrowserInfo() {\n const browser = {};\n if (typeof window === 'undefined') {\n return browser;\n }\n const ua = window.navigator.userAgent.toLowerCase();\n const match = /(edge|edg)\\/([\\w.]+)/.exec(ua) ||\n /(opr)[/]([\\w.]+)/.exec(ua) ||\n /(yabrowser)[ /]([\\w.]+)/.exec(ua) ||\n /(chrome)[ /]([\\w.]+)/.exec(ua) ||\n /(iemobile)[/]([\\w.]+)/.exec(ua) ||\n /(version)(applewebkit)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+).*(version)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+)/.exec(ua) ||\n /(opera)(?:.*version|)[ /]([\\w.]+)/.exec(ua) ||\n /(msie) ([\\w.]+)/.exec(ua) ||\n ua.indexOf('trident') >= 0 && /(rv)(?::| )([\\w.]+)/.exec(ua) ||\n ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n [];\n const matched = {\n browser: match[5] || match[3] || match[1] || '',\n version: match[4] || match[2] || '0'\n };\n if (matched.browser) {\n browser[matched.browser] = true;\n browser.version = parseInt(matched.version, 10);\n }\n // Chrome, Opera 15+, Safari and Yandex.Browser are webkit based browsers\n if (browser.chrome || browser.opr || browser.safari || browser.edg || browser.yabrowser) {\n browser.isWebkit = true;\n }\n // IE11 has a new token so we will assign it ie to avoid breaking changes\n if (browser.rv || browser.iemobile) {\n browser.ie = true;\n }\n // Edge has a new token since it became webkit based\n if (browser.edg) {\n browser.edge = true;\n }\n // Opera 15+ are identified as opr\n if (browser.opr) {\n browser.opera = true;\n }\n return browser;\n}\nexports.getBrowserInfo = getBrowserInfo;\nfunction getComponentPathWithoutIndicies(path = '') {\n return path.replace(/\\[\\d+\\]/, '');\n}\nexports.getComponentPathWithoutIndicies = getComponentPathWithoutIndicies;\n/**\n * Returns a path to the component which based on its schema\n * @param {*} component is a component's schema containing link to its parent's schema in the 'parent' property\n */\nfunction getComponentPath(component, path = '') {\n var _a;\n if (!component || !component.key || ((_a = component === null || component === void 0 ? void 0 : component._form) === null || _a === void 0 ? void 0 : _a.display) === 'wizard') { // unlike the Webform, the Wizard has the key and it is a duplicate of the panel key\n return path;\n }\n path = component.isInputComponent || component.input === true ? `${component.key}${path ? '.' : ''}${path}` : path;\n return getComponentPath(component.parent, path);\n}\nexports.getComponentPath = getComponentPath;\n/**\n * Returns a parent component of the passed component instance skipping all the Layout components\n * @param {*} componentInstance\n * @return {(Component|undefined)}\n */\nfunction getDataParentComponent(componentInstance) {\n if (!componentInstance) {\n return;\n }\n const { parent } = componentInstance;\n if (parent && (parent.isInputComponent || parent.input)) {\n return parent;\n }\n else {\n return getDataParentComponent(parent);\n }\n}\nexports.getDataParentComponent = getDataParentComponent;\n/**\n * Returns whether the value is a promise\n * @param value\n * @return {boolean}\n */\nfunction isPromise(value) {\n return value\n && value.then\n && typeof value.then === 'function'\n && Object.prototype.toString.call(value) === '[object Promise]';\n}\nexports.isPromise = isPromise;\n/**\n * Determines if the component has a scoping parent in tree (a component which scopes its children and manages its\n * changes by itself, e.g. EditGrid)\n * @param componentInstance\n * @param firstPass\n * @returns {boolean|boolean|*}\n */\nfunction isInsideScopingComponent(componentInstance, firstPass = true) {\n if (!firstPass && (componentInstance === null || componentInstance === void 0 ? void 0 : componentInstance.hasScopedChildren)) {\n return true;\n }\n const dataParent = getDataParentComponent(componentInstance);\n if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.hasScopedChildren) {\n return true;\n }\n else if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.parent) {\n return isInsideScopingComponent(dataParent.parent, false);\n }\n return false;\n}\nexports.isInsideScopingComponent = isInsideScopingComponent;\nfunction getFocusableElements(element) {\n const focusableSelector = `button:not([disabled]), input:not([disabled]), select:not([disabled]),\n textarea:not([disabled]), button:not([disabled]), [href]`;\n return element.querySelectorAll(focusableSelector);\n}\nexports.getFocusableElements = getFocusableElements;\nexports.componentValueTypes = {\n number: 'number',\n string: 'string',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n date: 'date',\n any: 'any',\n};\nfunction getComponentSavedTypes(fullSchema) {\n const schema = fullSchema || {};\n if (schema.persistent !== true) {\n return [];\n }\n if (schema.multiple) {\n return [exports.componentValueTypes.array];\n }\n return null;\n}\nexports.getComponentSavedTypes = getComponentSavedTypes;\n/**\n * Interpolates @formio/core errors so that they are compatible with the renderer\n * @param {FieldError[]} errors\n * @param firstPass\n * @returns {[]}\n */\nconst interpolateErrors = (component, errors, interpolateFn) => {\n return errors.map((error) => {\n error.component = component;\n const { errorKeyOrMessage, context } = error;\n const toInterpolate = component.errors && component.errors[errorKeyOrMessage] ? component.errors[errorKeyOrMessage] : errorKeyOrMessage;\n return Object.assign(Object.assign({}, error), { message: unescapeHTML(interpolateFn(toInterpolate, context)), context: Object.assign({}, context) });\n });\n};\nexports.interpolateErrors = interpolateErrors;\nfunction getItemTemplateKeys(template) {\n const templateKeys = [];\n if (!template) {\n return templateKeys;\n }\n const keys = template.match(/({{\\s*(.*?)\\s*}})/g);\n if (keys) {\n keys.forEach((key) => {\n const propKey = key.match(/{{\\s*item\\.(.*?)\\s*}}/);\n if (propKey && propKey.length > 1) {\n templateKeys.push(propKey[1]);\n }\n });\n }\n return templateKeys;\n}\nexports.getItemTemplateKeys = getItemTemplateKeys;\nfunction isSelectResourceWithObjectValue(comp = {}) {\n const { reference, dataSrc, valueProperty } = comp;\n return reference || (dataSrc === 'resource' && (!valueProperty || valueProperty === 'data'));\n}\nexports.isSelectResourceWithObjectValue = isSelectResourceWithObjectValue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/utils.js?");
|
|
6572
|
+
eval("\n/* global jQuery */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.removeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.moment = exports.ConditionOperators = exports.jsonLogic = void 0;\nexports.isSelectResourceWithObjectValue = exports.getItemTemplateKeys = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isInsideScopingComponent = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = exports.withSwitch = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nexports._ = lodash_1.default;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst json_logic_js_1 = __importDefault(__webpack_require__(/*! json-logic-js */ \"./node_modules/json-logic-js/logic.js\"));\nexports.jsonLogic = json_logic_js_1.default;\nconst moment_timezone_1 = __importDefault(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nconst jstimezonedetect_1 = __importDefault(__webpack_require__(/*! jstimezonedetect */ \"./node_modules/jstimezonedetect/dist/jstz.min.js\"));\nconst operators_1 = __webpack_require__(/*! ./jsonlogic/operators */ \"./lib/cjs/utils/jsonlogic/operators.js\");\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.js\"));\nconst formUtils_1 = __webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nexports.Evaluator = Evaluator_1.default;\nconst conditionOperators_1 = __importDefault(__webpack_require__(/*! ./conditionOperators */ \"./lib/cjs/utils/conditionOperators/index.js\"));\nexports.ConditionOperators = conditionOperators_1.default;\nconst interpolate = Evaluator_1.default.interpolate;\nexports.interpolate = interpolate;\nconst { fetch } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\n__exportStar(__webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\"), exports);\n// Configure JsonLogic\noperators_1.lodashOperators.forEach((name) => json_logic_js_1.default.add_operation(`_${name}`, lodash_1.default[name]));\n// Retrieve Any Date\njson_logic_js_1.default.add_operation('getDate', (date) => {\n return (0, moment_timezone_1.default)(date).toISOString();\n});\n// Set Relative Minimum Date\njson_logic_js_1.default.add_operation('relativeMinDate', (relativeMinDate) => {\n return (0, moment_timezone_1.default)().subtract(relativeMinDate, 'days').toISOString();\n});\n// Set Relative Maximum Date\njson_logic_js_1.default.add_operation('relativeMaxDate', (relativeMaxDate) => {\n return (0, moment_timezone_1.default)().add(relativeMaxDate, 'days').toISOString();\n});\nexports.moment = __importStar(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nfunction setPathToComponentAndPerentSchema(component) {\n component.path = getComponentPath(component);\n const dataParent = getDataParentComponent(component);\n if (dataParent && typeof dataParent === 'object') {\n dataParent.path = getComponentPath(dataParent);\n }\n}\n/**\n * Evaluate a method.\n *\n * @param func\n * @param args\n * @return {*}\n */\nfunction evaluate(func, args, ret, tokenize) {\n let returnVal = null;\n const component = args.component ? args.component : { key: 'unknown' };\n if (!args.form && args.instance) {\n args.form = lodash_1.default.get(args.instance, 'root._form', {});\n }\n const componentKey = component.key;\n if (typeof func === 'string') {\n if (ret) {\n func += `;return ${ret}`;\n }\n if (tokenize) {\n // Replace all {{ }} references with actual data.\n func = func.replace(/({{\\s+(.*)\\s+}})/, (match, $1, $2) => {\n if ($2.indexOf('data.') === 0) {\n return lodash_1.default.get(args.data, $2.replace('data.', ''));\n }\n else if ($2.indexOf('row.') === 0) {\n return lodash_1.default.get(args.row, $2.replace('row.', ''));\n }\n // Support legacy...\n return lodash_1.default.get(args.data, $2);\n });\n }\n try {\n func = Evaluator_1.default.evaluator(func, args);\n args = lodash_1.default.values(args);\n }\n catch (err) {\n console.warn(`An error occured within the custom function for ${componentKey}`, err);\n returnVal = null;\n func = false;\n }\n }\n if (typeof func === 'function') {\n try {\n returnVal = Evaluator_1.default.evaluate(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (typeof func === 'object') {\n try {\n returnVal = json_logic_js_1.default.apply(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (func) {\n console.warn(`Unknown function type for ${componentKey}`);\n }\n return returnVal;\n}\nexports.evaluate = evaluate;\nfunction getRandomComponentId() {\n return `e${Math.random().toString(36).substring(7)}`;\n}\nexports.getRandomComponentId = getRandomComponentId;\n/**\n * Get a property value of an element.\n *\n * @param style\n * @param prop\n * @return {number}\n */\nfunction getPropertyValue(style, prop) {\n let value = style.getPropertyValue(prop);\n value = value ? value.replace(/[^0-9.]/g, '') : '0';\n return parseFloat(value);\n}\nexports.getPropertyValue = getPropertyValue;\n/**\n * Get an elements bounding rectagle.\n *\n * @param element\n * @return {{x: string, y: string, width: string, height: string}}\n */\nfunction getElementRect(element) {\n const style = window.getComputedStyle(element, null);\n return {\n x: getPropertyValue(style, 'left'),\n y: getPropertyValue(style, 'top'),\n width: getPropertyValue(style, 'width'),\n height: getPropertyValue(style, 'height')\n };\n}\nexports.getElementRect = getElementRect;\n/**\n * Get non HTMLElement property in the window object\n * @param {String} property\n * @return {any || undefined}\n */\nfunction getScriptPlugin(property) {\n const obj = window[property];\n if (typeof HTMLElement === 'object' ? obj instanceof HTMLElement : //DOM2\n obj && typeof obj === 'object' && true && obj.nodeType === 1 && typeof obj.nodeName === 'string') {\n return undefined;\n }\n return obj;\n}\nexports.getScriptPlugin = getScriptPlugin;\n/**\n * Determines the boolean value of a setting.\n *\n * @param value\n * @return {boolean}\n */\nfunction boolValue(value) {\n if (lodash_1.default.isBoolean(value)) {\n return value;\n }\n else if (lodash_1.default.isString(value)) {\n return (value.toLowerCase() === 'true');\n }\n else {\n return !!value;\n }\n}\nexports.boolValue = boolValue;\n/**\n * Check to see if an ID is a mongoID.\n * @param text\n * @return {Array|{index: number, input: string}|Boolean|*}\n */\nfunction isMongoId(text) {\n return text.toString().match(/^[0-9a-fA-F]{24}$/);\n}\nexports.isMongoId = isMongoId;\n/**\n * Checks the calculated value for a provided component and data.\n *\n * @param {Object} component\n * The component to check for the calculated value.\n * @param {Object} submission\n * A submission object.\n * @param data\n * The full submission data.\n */\nfunction checkCalculated(component, submission, rowData) {\n // Process calculated value stuff if present.\n if (component.calculateValue) {\n lodash_1.default.set(rowData, component.key, evaluate(component.calculateValue, {\n value: undefined,\n data: submission ? submission.data : rowData,\n row: rowData,\n util: this,\n component\n }, 'value'));\n }\n}\nexports.checkCalculated = checkCalculated;\n/**\n * Check if a simple conditional evaluates to true.\n *\n * @param condition\n * @param condition\n * @param row\n * @param data\n * @param instance\n * @returns {boolean}\n */\nfunction checkSimpleConditional(component, condition, row, data, instance) {\n if (condition.when) {\n const value = getComponentActualValue(condition.when, data, row);\n const eq = String(condition.eq);\n const show = String(condition.show);\n // Special check for selectboxes component.\n if (lodash_1.default.isObject(value) && lodash_1.default.has(value, condition.eq)) {\n return String(value[condition.eq]) === show;\n }\n // FOR-179 - Check for multiple values.\n if (Array.isArray(value) && value.map(String).includes(eq)) {\n return show === 'true';\n }\n return (String(value) === eq) === (show === 'true');\n }\n else {\n const { conditions = [], conjunction = 'all', show = true } = condition;\n if (!conditions.length) {\n return true;\n }\n const conditionsResult = lodash_1.default.map(conditions, (cond) => {\n const { value: comparedValue, operator, component: conditionComponentPath } = cond;\n if (!conditionComponentPath) {\n return true;\n }\n const value = getComponentActualValue(conditionComponentPath, data, row);\n const ConditionOperator = conditionOperators_1.default[operator];\n return ConditionOperator\n ? new ConditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath })\n : true;\n });\n let result = false;\n switch (conjunction) {\n case 'any':\n result = lodash_1.default.some(conditionsResult, res => !!res);\n break;\n default:\n result = lodash_1.default.every(conditionsResult, res => !!res);\n }\n return show ? result : !result;\n }\n}\nexports.checkSimpleConditional = checkSimpleConditional;\nfunction getComponentActualValue(compPath, data, row) {\n let value = null;\n if (row) {\n value = (0, formUtils_1.getValue)({ data: row }, compPath);\n }\n if (data && lodash_1.default.isNil(value)) {\n value = (0, formUtils_1.getValue)({ data }, compPath);\n }\n // FOR-400 - Fix issue where falsey values were being evaluated as show=true\n if (lodash_1.default.isNil(value) || (lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value))) {\n value = '';\n }\n return value;\n}\nexports.getComponentActualValue = getComponentActualValue;\n/**\n * Check custom javascript conditional.\n *\n * @param component\n * @param custom\n * @param row\n * @param data\n * @returns {*}\n */\nfunction checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {\n if (typeof custom === 'string') {\n custom = `var ${variable} = true; ${custom}; return ${variable};`;\n }\n const value = (instance && instance.evaluate) ?\n instance.evaluate(custom, { row, data, form }) :\n evaluate(custom, { row, data, form });\n if (value === null) {\n return onError;\n }\n return value;\n}\nexports.checkCustomConditional = checkCustomConditional;\nfunction checkJsonConditional(component, json, row, data, form, onError) {\n try {\n return json_logic_js_1.default.apply(json, {\n data,\n row,\n form,\n _: lodash_1.default,\n });\n }\n catch (err) {\n console.warn(`An error occurred in jsonLogic advanced condition for ${component.key}`, err);\n return onError;\n }\n}\nexports.checkJsonConditional = checkJsonConditional;\nfunction getRow(component, row, instance, conditional) {\n var _a;\n const condition = conditional || component.conditional;\n // If no component's instance passed (happens only in 6.x server), calculate its path based on the schema\n if (!instance) {\n instance = lodash_1.default.cloneDeep(component);\n setPathToComponentAndPerentSchema(instance);\n }\n const dataParent = getDataParentComponent(instance);\n const parentPath = dataParent ? getComponentPath(dataParent) : null;\n const isTriggerCondtionComponentPath = condition.when || !condition.conditions\n ? (_a = condition.when) === null || _a === void 0 ? void 0 : _a.startsWith(parentPath)\n : lodash_1.default.some(condition.conditions, cond => cond.component.startsWith(parentPath));\n if (dataParent && isTriggerCondtionComponentPath) {\n const newRow = {};\n lodash_1.default.set(newRow, parentPath, row);\n row = newRow;\n }\n return row;\n}\n/**\n * Checks the conditions for a provided component and data.\n *\n * @param component\n * The component to check for the condition.\n * @param row\n * The data within a row\n * @param data\n * The full submission data.\n *\n * @returns {boolean}\n */\nfunction checkCondition(component, row, data, form, instance) {\n const { customConditional, conditional } = component;\n if (customConditional) {\n return checkCustomConditional(component, customConditional, row, data, form, 'show', true, instance);\n }\n else if (conditional && (conditional.when || lodash_1.default.some(conditional.conditions || [], condition => condition.component && condition.operator))) {\n row = getRow(component, row, instance);\n return checkSimpleConditional(component, conditional, row, data, instance);\n }\n else if (conditional && conditional.json) {\n return checkJsonConditional(component, conditional.json, row, data, form, true);\n }\n // Default to show.\n return true;\n}\nexports.checkCondition = checkCondition;\n/**\n * Test a trigger on a component.\n *\n * @param component\n * @param action\n * @param data\n * @param row\n * @returns {mixed}\n */\nfunction checkTrigger(component, trigger, row, data, form, instance) {\n // If trigger is empty, don't fire it\n if (!trigger || !trigger[trigger.type]) {\n return false;\n }\n switch (trigger.type) {\n case 'simple':\n row = getRow(component, row, instance, trigger.simple);\n return checkSimpleConditional(component, trigger.simple, row, data, instance);\n case 'javascript':\n return checkCustomConditional(component, trigger.javascript, row, data, form, 'result', false, instance);\n case 'json':\n return checkJsonConditional(component, trigger.json, row, data, form, false);\n }\n // If none of the types matched, don't fire the trigger.\n return false;\n}\nexports.checkTrigger = checkTrigger;\nfunction setActionProperty(component, action, result, row, data, instance) {\n const property = action.property.value;\n switch (action.property.type) {\n case 'boolean': {\n const currentValue = lodash_1.default.get(component, property, false).toString();\n const newValue = action.state.toString();\n if (currentValue !== newValue) {\n lodash_1.default.set(component, property, newValue === 'true');\n }\n break;\n }\n case 'string': {\n const evalData = {\n data,\n row,\n component,\n result,\n };\n const textValue = action.property.component ? action[action.property.component] : action.text;\n const currentValue = lodash_1.default.get(component, property, '');\n const newValue = (instance && instance.interpolate)\n ? instance.interpolate(textValue, evalData)\n : Evaluator_1.default.interpolate(textValue, evalData);\n if (newValue !== currentValue) {\n lodash_1.default.set(component, property, newValue);\n }\n break;\n }\n }\n return component;\n}\nexports.setActionProperty = setActionProperty;\n/**\n * Removes HTML tags from string e.g. <div>Hello World</div> => Hello World\n * @param {string} str\n * @returns {string}\n */\nfunction removeHTML(str) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return (doc.body.textContent || '').trim();\n}\nexports.removeHTML = removeHTML;\n/**\n * Unescape HTML characters like <, >, & and etc.\n * @param str\n * @returns {string}\n */\nfunction unescapeHTML(str) {\n if (typeof window === 'undefined' || !('DOMParser' in window)) {\n return str;\n }\n const elem = document.createElement('textarea');\n elem.innerHTML = str;\n return elem.value;\n}\nexports.unescapeHTML = unescapeHTML;\n/**\n * Make HTML element from string\n * @param str\n * @param selector\n * @returns {HTMLElement}\n */\nfunction convertStringToHTMLElement(str, selector) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.body.querySelector(selector);\n}\nexports.convertStringToHTMLElement = convertStringToHTMLElement;\n/**\n * Make a filename guaranteed to be unique.\n * @param name\n * @param template\n * @param evalContext\n * @returns {string}\n */\nfunction uniqueName(name, template, evalContext) {\n template = template || '{{fileName}}-{{guid}}';\n //include guid in template anyway, to prevent overwriting issue if filename matches existing file\n if (!template.includes('{{guid}}')) {\n template = `${template}-{{guid}}`;\n }\n const parts = name.split('.');\n let fileName = parts.slice(0, parts.length - 1).join('.');\n const extension = parts.length > 1\n ? `.${lodash_1.default.last(parts)}`\n : '';\n //allow only 100 characters from original name to avoid issues with filename length restrictions\n fileName = fileName.substr(0, 100);\n evalContext = Object.assign(evalContext || {}, {\n fileName,\n guid: guid()\n });\n //only letters, numbers, dots, dashes, underscores and spaces are allowed. Anything else will be replaced with dash\n const uniqueName = `${Evaluator_1.default.interpolate(template, evalContext)}${extension}`.replace(/[^0-9a-zA-Z.\\-_ ]/g, '-');\n return uniqueName;\n}\nexports.uniqueName = uniqueName;\nfunction guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x'\n ? r\n : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\nexports.guid = guid;\n/**\n * Return a translated date setting.\n *\n * @param date\n * @return {(null|Date)}\n */\nfunction getDateSetting(date) {\n if (lodash_1.default.isNil(date) || lodash_1.default.isNaN(date) || date === '') {\n return null;\n }\n if (date instanceof Date) {\n return date;\n }\n else if (typeof date.toDate === 'function') {\n return date.isValid() ? date.toDate() : null;\n }\n let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? (0, moment_timezone_1.default)(date) : null;\n if (dateSetting && dateSetting.isValid()) {\n return dateSetting.toDate();\n }\n dateSetting = null;\n try {\n const value = Evaluator_1.default.evaluator(`return ${date};`, 'moment')(moment_timezone_1.default);\n if (typeof value === 'string') {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n else if (typeof value.toDate === 'function') {\n dateSetting = (0, moment_timezone_1.default)(value.toDate().toUTCString());\n }\n else if (value instanceof Date) {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n }\n catch (e) {\n return null;\n }\n if (!dateSetting) {\n return null;\n }\n // Ensure this is a date.\n if (!dateSetting.isValid()) {\n return null;\n }\n return dateSetting.toDate();\n}\nexports.getDateSetting = getDateSetting;\nfunction isValidDate(date) {\n return lodash_1.default.isDate(date) && !lodash_1.default.isNaN(date.getDate());\n}\nexports.isValidDate = isValidDate;\n/**\n * Get the current timezone string.\n *\n * @return {string}\n */\nfunction currentTimezone() {\n if (moment_timezone_1.default.currentTimezone) {\n return moment_timezone_1.default.currentTimezone;\n }\n moment_timezone_1.default.currentTimezone = jstimezonedetect_1.default.determine().name();\n return moment_timezone_1.default.currentTimezone;\n}\nexports.currentTimezone = currentTimezone;\n/**\n * Get an offset date provided a date object and timezone object.\n *\n * @param date\n * @param timezone\n * @return {Date}\n */\nfunction offsetDate(date, timezone) {\n if (timezone === 'UTC') {\n return {\n date: new Date(date.getTime() + (date.getTimezoneOffset() * 60000)),\n abbr: 'UTC'\n };\n }\n const dateMoment = (0, moment_timezone_1.default)(date).tz(timezone);\n return {\n date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)),\n abbr: dateMoment.format('z')\n };\n}\nexports.offsetDate = offsetDate;\n/**\n * Returns if the zones are loaded.\n *\n * @return {boolean}\n */\nfunction zonesLoaded() {\n return moment_timezone_1.default.zonesLoaded;\n}\nexports.zonesLoaded = zonesLoaded;\n/**\n * Returns if we should load the zones.\n *\n * @param timezone\n * @return {boolean}\n */\nfunction shouldLoadZones(timezone) {\n if (timezone === currentTimezone() || timezone === 'UTC') {\n return false;\n }\n return true;\n}\nexports.shouldLoadZones = shouldLoadZones;\n/**\n * Externally load the timezone data.\n *\n * @return {Promise<any> | *}\n */\nfunction loadZones(url, timezone) {\n if (timezone && !shouldLoadZones(timezone)) {\n // Return non-resolving promise.\n return new Promise(lodash_1.default.noop);\n }\n if (moment_timezone_1.default.zonesPromise) {\n return moment_timezone_1.default.zonesPromise;\n }\n return moment_timezone_1.default.zonesPromise = fetch(url)\n .then(resp => resp.json().then(zones => {\n moment_timezone_1.default.tz.load(zones);\n moment_timezone_1.default.zonesLoaded = true;\n // Trigger a global event that the timezones have finished loading.\n if (document && document.createEvent && document.body && document.body.dispatchEvent) {\n var event = document.createEvent('Event');\n event.initEvent('zonesLoaded', true, true);\n document.body.dispatchEvent(event);\n }\n }));\n}\nexports.loadZones = loadZones;\n/**\n * Get the moment date object for translating dates with timezones.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {*}\n */\nfunction momentDate(value, format, timezone) {\n const momentDate = (0, moment_timezone_1.default)(value);\n if (!timezone) {\n return momentDate;\n }\n if (timezone === 'UTC') {\n timezone = 'Etc/UTC';\n }\n if ((timezone !== currentTimezone() || (format && format.match(/\\s(z$|z\\s)/))) && moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone);\n }\n return momentDate;\n}\nexports.momentDate = momentDate;\n/**\n * Format a date provided a value, format, and timezone object.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) {\n const momentDate = (0, moment_timezone_1.default)(value, flatPickrInputFormat || undefined);\n if (timezone === currentTimezone()) {\n // See if our format contains a \"z\" timezone character.\n if (format.match(/\\s(z$|z\\s)/)) {\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone).format(convertFormatToMoment(format));\n }\n else {\n return momentDate.format(convertFormatToMoment(format.replace(/\\s(z$|z\\s)/, '')));\n }\n }\n // Return the standard format.\n return momentDate.format(convertFormatToMoment(format));\n }\n if (timezone === 'UTC') {\n const offset = offsetDate(momentDate.toDate(), 'UTC');\n return `${(0, moment_timezone_1.default)(offset.date).format(convertFormatToMoment(format))} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded && timezone) {\n return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`);\n }\n else {\n return momentDate.format(convertFormatToMoment(format));\n }\n}\nexports.formatDate = formatDate;\n/**\n * Pass a format function to format within a timezone.\n *\n * @param formatFn\n * @param date\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatOffset(timezonesUrl, formatFn, date, format, timezone) {\n if (timezone === currentTimezone()) {\n return formatFn(date, format);\n }\n if (timezone === 'UTC') {\n return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n const offset = offsetDate(date, timezone);\n return `${formatFn(offset.date, format)} ${offset.abbr}`;\n }\n else {\n return formatFn(date, format);\n }\n}\nexports.formatOffset = formatOffset;\nfunction getLocaleDateFormatInfo(locale) {\n const formatInfo = {};\n const day = 21;\n const exampleDate = new Date(2017, 11, day);\n const localDateString = exampleDate.toLocaleDateString(locale);\n formatInfo.dayFirst = localDateString.slice(0, 2) === day.toString();\n return formatInfo;\n}\nexports.getLocaleDateFormatInfo = getLocaleDateFormatInfo;\n/**\n * Convert the format from the angular-datepicker module to flatpickr format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToFlatpickr(format) {\n return format\n // Remove the Z timezone offset, not supported by flatpickr.\n .replace(/Z/g, '')\n // Year conversion.\n .replace(/y/g, 'Y')\n .replace('YYYY', 'Y')\n .replace('YY', 'y')\n // Month conversion.\n .replace('MMMM', 'F')\n .replace(/M/g, 'n')\n .replace('nnn', 'M')\n .replace('nn', 'm')\n // Day in month.\n .replace(/d/g, 'j')\n .replace(/jj/g, 'd')\n // Day in week.\n .replace('EEEE', 'l')\n .replace('EEE', 'D')\n // Hours, minutes, seconds\n .replace('HH', 'H')\n .replace('hh', 'G')\n .replace('mm', 'i')\n .replace('ss', 'S')\n .replace(/a/g, 'K');\n}\nexports.convertFormatToFlatpickr = convertFormatToFlatpickr;\n/**\n * Convert the format from the angular-datepicker module to moment format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToMoment(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y')\n // Day in month.\n .replace(/d/g, 'D')\n // Day in week.\n .replace(/E/g, 'd')\n // AM/PM marker\n .replace(/a/g, 'A')\n // Unix Timestamp\n .replace(/U/g, 'X');\n}\nexports.convertFormatToMoment = convertFormatToMoment;\nfunction convertFormatToMask(format) {\n return format\n // Long month replacement.\n .replace(/M{4}/g, 'MM')\n // Initial short month conversion.\n .replace(/M{3}/g, '***')\n // Short month conversion if input as text.\n .replace(/e/g, 'Q')\n // Month number conversion.\n .replace(/W/g, '99')\n // Year conversion.\n .replace(/[ydhmswHMG]/g, '9')\n // AM/PM conversion.\n .replace(/a/g, 'AA');\n}\nexports.convertFormatToMask = convertFormatToMask;\n/**\n * Returns an input mask that is compatible with the input mask library.\n * @param {string} mask - The Form.io input mask.\n * @param {string} placeholderChar - Char which is used as a placeholder.\n * @returns {Array} - The input mask for the mask library.\n */\nfunction getInputMask(mask, placeholderChar) {\n if (mask instanceof Array) {\n return mask;\n }\n const maskArray = [];\n maskArray.numeric = true;\n for (let i = 0; i < mask.length; i++) {\n switch (mask[i]) {\n case '9':\n maskArray.push(/\\d/);\n break;\n case 'A':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z]/);\n break;\n case 'a':\n maskArray.numeric = false;\n maskArray.push(/[a-z]/);\n break;\n case '*':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z0-9]/);\n break;\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n case placeholderChar:\n maskArray.numeric = false;\n maskArray.push(' ');\n break;\n default:\n maskArray.numeric = false;\n maskArray.push(mask[i]);\n break;\n }\n }\n return maskArray;\n}\nexports.getInputMask = getInputMask;\nfunction unmaskValue(value, mask, placeholderChar) {\n if (!mask || !value || value.length > mask.length) {\n return value;\n }\n let unmaskedValue = value.split('');\n for (let i = 0; i < mask.length; i++) {\n const char = value[i] || '';\n const charPart = mask[i];\n if (!lodash_1.default.isRegExp(charPart) && char === charPart) {\n unmaskedValue[i] = '';\n }\n }\n unmaskedValue = unmaskedValue.join('').replace(placeholderChar, '');\n return unmaskedValue;\n}\nexports.unmaskValue = unmaskValue;\nfunction matchInputMask(value, inputMask) {\n if (!inputMask) {\n return true;\n }\n // If value is longer than mask, it isn't valid.\n if (value.length > inputMask.length) {\n return false;\n }\n for (let i = 0; i < inputMask.length; i++) {\n const char = value[i] || '';\n const charPart = inputMask[i];\n if (!(lodash_1.default.isRegExp(charPart) && charPart.test(char) || charPart === char)) {\n return false;\n }\n }\n return true;\n}\nexports.matchInputMask = matchInputMask;\nfunction getNumberSeparators(lang = 'en') {\n const formattedNumberString = (12345.6789).toLocaleString(lang);\n const delimeters = formattedNumberString.match(/..(.)...(.)../);\n if (!delimeters) {\n return {\n delimiter: ',',\n decimalSeparator: '.'\n };\n }\n return {\n delimiter: (delimeters.length > 1) ? delimeters[1] : ',',\n decimalSeparator: (delimeters.length > 2) ? delimeters[2] : '.',\n };\n}\nexports.getNumberSeparators = getNumberSeparators;\nfunction getNumberDecimalLimit(component, defaultLimit) {\n if (lodash_1.default.has(component, 'decimalLimit')) {\n return lodash_1.default.get(component, 'decimalLimit');\n }\n // Determine the decimal limit. Defaults to 20 but can be overridden by validate.step or decimalLimit settings.\n let decimalLimit = defaultLimit || 20;\n const step = lodash_1.default.get(component, 'validate.step', 'any');\n if (step !== 'any') {\n const parts = step.toString().split('.');\n if (parts.length > 1) {\n decimalLimit = parts[1].length;\n }\n }\n return decimalLimit;\n}\nexports.getNumberDecimalLimit = getNumberDecimalLimit;\nfunction getCurrencyAffixes({ currency, decimalLimit, decimalSeparator, lang, }) {\n // Get the prefix and suffix from the localized string.\n let regex = `(.*)?${(100).toLocaleString(lang)}`;\n if (decimalLimit) {\n regex += `${decimalSeparator === '.' ? '\\\\.' : decimalSeparator}${(0).toLocaleString(lang)}{${decimalLimit}}`;\n }\n regex += '(.*)?';\n const parts = (100).toLocaleString(lang, {\n style: 'currency',\n currency: currency ? currency : 'USD',\n useGrouping: true,\n maximumFractionDigits: decimalLimit || 0,\n minimumFractionDigits: decimalLimit || 0\n }).replace('.', decimalSeparator).match(new RegExp(regex));\n return {\n prefix: (parts === null || parts === void 0 ? void 0 : parts[1]) || '',\n suffix: (parts === null || parts === void 0 ? void 0 : parts[2]) || ''\n };\n}\nexports.getCurrencyAffixes = getCurrencyAffixes;\n/**\n * Fetch the field data provided a component.\n *\n * @param data\n * @param component\n * @return {*}\n */\nfunction fieldData(data, component) {\n if (!data) {\n return '';\n }\n if (!component || !component.key) {\n return data;\n }\n if (component.key.includes('.')) {\n let value = data;\n const parts = component.key.split('.');\n let key = '';\n for (let i = 0; i < parts.length; i++) {\n key = parts[i];\n // Handle nested resources\n if (value.hasOwnProperty('_id')) {\n value = value.data;\n }\n // Return if the key is not found on the value.\n if (!value.hasOwnProperty(key)) {\n return;\n }\n // Convert old single field data in submissions to multiple\n if (key === parts[parts.length - 1] && component.multiple && !Array.isArray(value[key])) {\n value[key] = [value[key]];\n }\n // Set the value of this key.\n value = value[key];\n }\n return value;\n }\n else {\n // Convert old single field data in submissions to multiple\n if (component.multiple && !Array.isArray(data[component.key])) {\n data[component.key] = [data[component.key]];\n }\n // Fix for checkbox type radio submission values in tableView\n if (component.type === 'checkbox' && component.inputType === 'radio') {\n return data[component.name] === component.value;\n }\n return data[component.key];\n }\n}\nexports.fieldData = fieldData;\n/**\n * Delays function execution with possibility to execute function synchronously or cancel it.\n *\n * @param fn Function to delay\n * @param delay Delay time\n * @return {*}\n */\nfunction delay(fn, delay = 0, ...args) {\n const timer = setTimeout(fn, delay, ...args);\n function cancel() {\n clearTimeout(timer);\n }\n function earlyCall() {\n cancel();\n return fn(...args);\n }\n earlyCall.timer = timer;\n earlyCall.cancel = cancel;\n return earlyCall;\n}\nexports.delay = delay;\n/**\n * Iterate the given key to make it unique.\n *\n * @param {String} key\n * Modify the component key to be unique.\n *\n * @returns {String}\n * The new component key.\n */\nfunction iterateKey(key) {\n if (!key.match(/(\\d+)$/)) {\n return `${key}1`;\n }\n return key.replace(/(\\d+)$/, function (suffix) {\n return Number(suffix) + 1;\n });\n}\nexports.iterateKey = iterateKey;\n/**\n * Determines a unique key within a map provided the base key.\n *\n * @param map\n * @param base\n * @return {*}\n */\nfunction uniqueKey(map, base) {\n let newKey = base;\n while (map.hasOwnProperty(newKey)) {\n newKey = iterateKey(newKey);\n }\n return newKey;\n}\nexports.uniqueKey = uniqueKey;\n/**\n * Determines the major version number of bootstrap.\n *\n * @return {number}\n */\nfunction bootstrapVersion(options) {\n if (options.bootstrap) {\n return options.bootstrap;\n }\n if ((typeof jQuery === 'function') && (typeof jQuery().collapse === 'function')) {\n return parseInt(jQuery.fn.collapse.Constructor.VERSION.split('.')[0], 10);\n }\n if (window.bootstrap && window.bootstrap.Collapse) {\n return parseInt(window.bootstrap.Collapse.VERSION.split('.')[0], 10);\n }\n return 0;\n}\nexports.bootstrapVersion = bootstrapVersion;\n/**\n * Retrun provided argument.\n * If argument is a function, returns the result of a function call.\n * @param {*} e;\n *\n * @return {*}\n */\nfunction unfold(e) {\n if (typeof e === 'function') {\n return e();\n }\n return e;\n}\nexports.unfold = unfold;\n/**\n * Map values through unfold and return first non-nil value.\n * @param {Array<T>} collection;\n *\n * @return {T}\n */\nexports.firstNonNil = lodash_1.default.flow([\n lodash_1.default.partialRight(lodash_1.default.map, unfold),\n lodash_1.default.partialRight(lodash_1.default.find, v => !lodash_1.default.isUndefined(v))\n]);\n/*\n * Create enclosed state.\n * Returns functions to getting and cycling between states.\n * @param {*} a - initial state.\n * @param {*} b - next state.\n * @return {Functions[]} -- [get, toggle];\n */\nfunction withSwitch(a, b) {\n let state = a;\n let next = b;\n function get() {\n return state;\n }\n function toggle() {\n const prev = state;\n state = next;\n next = prev;\n }\n return [get, toggle];\n}\nexports.withSwitch = withSwitch;\nfunction observeOverload(callback, options = {}) {\n const { limit = 50, delay = 500 } = options;\n let callCount = 0;\n let timeoutID = 0;\n const reset = () => callCount = 0;\n return () => {\n if (timeoutID !== 0) {\n clearTimeout(timeoutID);\n timeoutID = 0;\n }\n timeoutID = setTimeout(reset, delay);\n callCount += 1;\n if (callCount >= limit) {\n clearTimeout(timeoutID);\n reset();\n return callback();\n }\n };\n}\nexports.observeOverload = observeOverload;\nfunction getContextComponents(context, excludeNested, excludedTypes = []) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component, path) => {\n const addToContextComponents = excludeNested ? !component.tree : true;\n if (component.key !== context.data.key && addToContextComponents && !lodash_1.default.includes(excludedTypes, component.type)) {\n values.push({\n label: `${component.label || component.key} (${path})`,\n value: path,\n });\n }\n });\n return values;\n}\nexports.getContextComponents = getContextComponents;\nfunction getContextButtons(context) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component) => {\n if (component.type === 'button') {\n values.push({\n label: `${component.key} (${component.label})`,\n value: component.key,\n });\n }\n });\n return values;\n}\nexports.getContextButtons = getContextButtons;\n// Tags that could be in text, that should be ommited or handled in a special way\nconst inTextTags = ['#text', 'A', 'B', 'EM', 'I', 'SMALL', 'STRONG', 'SUB', 'SUP', 'INS', 'DEL', 'MARK', 'CODE'];\n/**\n * Helper function for 'translateHTMLTemplate'. Translates text value of the passed html element.\n *\n * @param {HTMLElement} elem\n * @param {Function} translate\n *\n * @returns {String}\n * Translated element template.\n */\nfunction translateElemValue(elem, translate) {\n if (!elem.innerText) {\n return elem.innerHTML;\n }\n const elemValue = elem.innerText.replace(Evaluator_1.default.templateSettings.interpolate, '').replace(/\\s\\s+/g, ' ').trim();\n const translatedValue = translate(elemValue);\n if (elemValue !== translatedValue) {\n const links = elem.innerHTML.match(/<a[^>]*>(.*?)<\\/a>/g);\n if (links && links.length) {\n if (links.length === 1 && links[0].length === elem.innerHTML.length) {\n return elem.innerHTML.replace(elemValue, translatedValue);\n }\n const translatedLinks = links.map(link => {\n const linkElem = document.createElement('a');\n linkElem.innerHTML = link;\n return translateElemValue(linkElem, translate);\n });\n return `${translatedValue} (${translatedLinks.join(', ')})`;\n }\n else {\n return elem.innerText.replace(elemValue, translatedValue);\n }\n }\n else {\n return elem.innerHTML;\n }\n}\n/**\n * Helper function for 'translateHTMLTemplate'. Goes deep through html tag children and calls function to translate their text values.\n *\n * @param {HTMLElement} tag\n * @param {Function} translate\n *\n * @returns {void}\n */\nfunction translateDeepTag(tag, translate) {\n const children = tag.children.length && [...tag.children];\n const shouldTranslateEntireContent = children && children.every(child => child.children.length === 0\n && inTextTags.some(tag => child.nodeName === tag));\n if (!children || shouldTranslateEntireContent) {\n tag.innerHTML = translateElemValue(tag, translate);\n }\n else {\n children.forEach(child => translateDeepTag(child, translate));\n }\n}\n/**\n * Translates text values in html template.\n *\n * @param {String} template\n * @param {Function} translate\n *\n * @returns {String}\n * Html template with translated values.\n */\nfunction translateHTMLTemplate(template, translate) {\n const isHTML = /<[^>]*>/.test(template);\n if (!isHTML) {\n return translate(template);\n }\n const tempElem = document.createElement('div');\n tempElem.innerHTML = template;\n if (tempElem.innerText && tempElem.children.length) {\n translateDeepTag(tempElem, translate);\n return tempElem.innerHTML;\n }\n return template;\n}\nexports.translateHTMLTemplate = translateHTMLTemplate;\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n if (typeof dompurify_1.default.sanitize !== 'function') {\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target'],\n USE_PROFILES: { html: true }\n };\n // Use profiles\n if (options.sanitizeConfig && options.sanitizeConfig.useProfiles) {\n Object.keys(options.sanitizeConfig.useProfiles).forEach(key => {\n sanitizeOptions.USE_PROFILES[key] = options.sanitizeConfig.useProfiles[key];\n });\n }\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n const allowedUriRegex = options.sanitizeConfig.allowedUriRegex;\n sanitizeOptions.ALLOWED_URI_REGEXP = lodash_1.default.isString(allowedUriRegex) ? new RegExp(allowedUriRegex) : allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify_1.default.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n/**\n * Fast cloneDeep for JSON objects only.\n */\nfunction fastCloneDeep(obj) {\n return obj ? JSON.parse(JSON.stringify(obj)) : obj;\n}\nexports.fastCloneDeep = fastCloneDeep;\nfunction isInputComponent(componentJson) {\n if (componentJson.input === false || componentJson.input === true) {\n return componentJson.input;\n }\n switch (componentJson.type) {\n case 'htmlelement':\n case 'content':\n case 'columns':\n case 'fieldset':\n case 'panel':\n case 'table':\n case 'tabs':\n case 'well':\n case 'button':\n return false;\n default:\n return true;\n }\n}\nexports.isInputComponent = isInputComponent;\nfunction getArrayFromComponentPath(pathStr) {\n if (!pathStr || !lodash_1.default.isString(pathStr)) {\n if (!lodash_1.default.isArray(pathStr)) {\n return [pathStr];\n }\n return pathStr;\n }\n return pathStr.replace(/[[\\]]/g, '.')\n .replace(/\\.\\./g, '.')\n .replace(/(^\\.)|(\\.$)/g, '')\n .split('.')\n .map(part => lodash_1.default.defaultTo(lodash_1.default.toNumber(part), part));\n}\nexports.getArrayFromComponentPath = getArrayFromComponentPath;\nfunction isChildOf(child, parent) {\n while (child && child.parent) {\n if (child.parent === parent) {\n return true;\n }\n child = child.parent;\n }\n return false;\n}\nexports.isChildOf = isChildOf;\nfunction getStringFromComponentPath(path) {\n if (!lodash_1.default.isArray(path)) {\n return path;\n }\n let strPath = '';\n path.forEach((part, i) => {\n if (lodash_1.default.isNumber(part)) {\n strPath += `[${part}]`;\n }\n else {\n strPath += i === 0 ? part : `.${part}`;\n }\n });\n return strPath;\n}\nexports.getStringFromComponentPath = getStringFromComponentPath;\nfunction round(number, precision) {\n if (lodash_1.default.isNumber(number)) {\n return number.toFixed(precision);\n }\n return number;\n}\nexports.round = round;\n/**\n * Check for Internet Explorer browser version\n *\n * @return {(number|null)}\n */\nfunction getIEBrowserVersion() {\n const { ie, version } = getBrowserInfo();\n return ie ? version : null;\n}\nexports.getIEBrowserVersion = getIEBrowserVersion;\n/**\n * Get browser name and version (modified from 'jquery-browser-plugin')\n *\n * @return {Object} -- {{browser name, version, isWebkit?}}\n * Possible browser names: chrome, safari, ie, edge, opera, mozilla, yabrowser\n */\nfunction getBrowserInfo() {\n const browser = {};\n if (typeof window === 'undefined') {\n return browser;\n }\n const ua = window.navigator.userAgent.toLowerCase();\n const match = /(edge|edg)\\/([\\w.]+)/.exec(ua) ||\n /(opr)[/]([\\w.]+)/.exec(ua) ||\n /(yabrowser)[ /]([\\w.]+)/.exec(ua) ||\n /(chrome)[ /]([\\w.]+)/.exec(ua) ||\n /(iemobile)[/]([\\w.]+)/.exec(ua) ||\n /(version)(applewebkit)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+).*(version)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+)/.exec(ua) ||\n /(opera)(?:.*version|)[ /]([\\w.]+)/.exec(ua) ||\n /(msie) ([\\w.]+)/.exec(ua) ||\n ua.indexOf('trident') >= 0 && /(rv)(?::| )([\\w.]+)/.exec(ua) ||\n ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n [];\n const matched = {\n browser: match[5] || match[3] || match[1] || '',\n version: match[4] || match[2] || '0'\n };\n if (matched.browser) {\n browser[matched.browser] = true;\n browser.version = parseInt(matched.version, 10);\n }\n // Chrome, Opera 15+, Safari and Yandex.Browser are webkit based browsers\n if (browser.chrome || browser.opr || browser.safari || browser.edg || browser.yabrowser) {\n browser.isWebkit = true;\n }\n // IE11 has a new token so we will assign it ie to avoid breaking changes\n if (browser.rv || browser.iemobile) {\n browser.ie = true;\n }\n // Edge has a new token since it became webkit based\n if (browser.edg) {\n browser.edge = true;\n }\n // Opera 15+ are identified as opr\n if (browser.opr) {\n browser.opera = true;\n }\n return browser;\n}\nexports.getBrowserInfo = getBrowserInfo;\nfunction getComponentPathWithoutIndicies(path = '') {\n return path.replace(/\\[\\d+\\]/, '');\n}\nexports.getComponentPathWithoutIndicies = getComponentPathWithoutIndicies;\n/**\n * Returns a path to the component which based on its schema\n * @param {*} component is a component's schema containing link to its parent's schema in the 'parent' property\n */\nfunction getComponentPath(component, path = '') {\n var _a;\n if (!component || !component.key || ((_a = component === null || component === void 0 ? void 0 : component._form) === null || _a === void 0 ? void 0 : _a.display) === 'wizard') { // unlike the Webform, the Wizard has the key and it is a duplicate of the panel key\n return path;\n }\n path = component.isInputComponent || component.input === true ? `${component.key}${path ? '.' : ''}${path}` : path;\n return getComponentPath(component.parent, path);\n}\nexports.getComponentPath = getComponentPath;\n/**\n * Returns a parent component of the passed component instance skipping all the Layout components\n * @param {*} componentInstance\n * @return {(Component|undefined)}\n */\nfunction getDataParentComponent(componentInstance) {\n if (!componentInstance) {\n return;\n }\n const { parent } = componentInstance;\n if (parent && (parent.isInputComponent || parent.input)) {\n return parent;\n }\n else {\n return getDataParentComponent(parent);\n }\n}\nexports.getDataParentComponent = getDataParentComponent;\n/**\n * Returns whether the value is a promise\n * @param value\n * @return {boolean}\n */\nfunction isPromise(value) {\n return value\n && value.then\n && typeof value.then === 'function'\n && Object.prototype.toString.call(value) === '[object Promise]';\n}\nexports.isPromise = isPromise;\n/**\n * Determines if the component has a scoping parent in tree (a component which scopes its children and manages its\n * changes by itself, e.g. EditGrid)\n * @param componentInstance\n * @param firstPass\n * @returns {boolean|boolean|*}\n */\nfunction isInsideScopingComponent(componentInstance, firstPass = true) {\n if (!firstPass && (componentInstance === null || componentInstance === void 0 ? void 0 : componentInstance.hasScopedChildren)) {\n return true;\n }\n const dataParent = getDataParentComponent(componentInstance);\n if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.hasScopedChildren) {\n return true;\n }\n else if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.parent) {\n return isInsideScopingComponent(dataParent.parent, false);\n }\n return false;\n}\nexports.isInsideScopingComponent = isInsideScopingComponent;\nfunction getFocusableElements(element) {\n const focusableSelector = `button:not([disabled]), input:not([disabled]), select:not([disabled]),\n textarea:not([disabled]), button:not([disabled]), [href]`;\n return element.querySelectorAll(focusableSelector);\n}\nexports.getFocusableElements = getFocusableElements;\nexports.componentValueTypes = {\n number: 'number',\n string: 'string',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n date: 'date',\n any: 'any',\n};\nfunction getComponentSavedTypes(fullSchema) {\n const schema = fullSchema || {};\n if (schema.persistent !== true) {\n return [];\n }\n if (schema.multiple) {\n return [exports.componentValueTypes.array];\n }\n return null;\n}\nexports.getComponentSavedTypes = getComponentSavedTypes;\n/**\n * Interpolates @formio/core errors so that they are compatible with the renderer\n * @param {FieldError[]} errors\n * @param firstPass\n * @returns {[]}\n */\nconst interpolateErrors = (component, errors, interpolateFn) => {\n return errors.map((error) => {\n error.component = component;\n const { errorKeyOrMessage, context } = error;\n const toInterpolate = component.errors && component.errors[errorKeyOrMessage] ? component.errors[errorKeyOrMessage] : errorKeyOrMessage;\n return Object.assign(Object.assign({}, error), { message: unescapeHTML(interpolateFn(toInterpolate, context)), context: Object.assign({}, context) });\n });\n};\nexports.interpolateErrors = interpolateErrors;\nfunction getItemTemplateKeys(template) {\n const templateKeys = [];\n if (!template) {\n return templateKeys;\n }\n const keys = template.match(/({{\\s*(.*?)\\s*}})/g);\n if (keys) {\n keys.forEach((key) => {\n const propKey = key.match(/{{\\s*item\\.(.*?)\\s*}}/);\n if (propKey && propKey.length > 1) {\n templateKeys.push(propKey[1]);\n }\n });\n }\n return templateKeys;\n}\nexports.getItemTemplateKeys = getItemTemplateKeys;\nfunction isSelectResourceWithObjectValue(comp = {}) {\n const { reference, dataSrc, valueProperty } = comp;\n return reference || (dataSrc === 'resource' && (!valueProperty || valueProperty === 'data'));\n}\nexports.isSelectResourceWithObjectValue = isSelectResourceWithObjectValue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/utils.js?");
|
|
6572
6573
|
|
|
6573
6574
|
/***/ }),
|
|
6574
6575
|
|