@formio/js 5.0.0-bb.dev.3 → 5.0.0-bb.dev.6
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.embed.js +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.embed.min.js.LICENSE.txt +1 -1
- package/dist/formio.form.js +12 -12
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +1 -1
- package/dist/formio.full.js +12 -12
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +1 -1
- package/dist/formio.js +1 -1
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +1 -1
- package/lib/cjs/Form.js +0 -15
- package/lib/cjs/components/_classes/component/Component.js +10 -4
- package/lib/cjs/components/_classes/component/editForm/Component.edit.validation.js +8 -0
- package/lib/cjs/components/_classes/nested/NestedComponent.js +2 -2
- package/lib/cjs/components/datagrid/DataGrid.js +2 -1
- package/lib/cjs/components/datagrid/fixtures/comp-with-allow-calculate-override.js +1 -1
- package/lib/cjs/components/datagrid/fixtures/index.d.ts +2 -1
- package/lib/cjs/components/datagrid/fixtures/index.js +3 -1
- package/lib/cjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.d.ts +53 -0
- package/lib/cjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.js +104 -0
- package/lib/cjs/components/editgrid/EditGrid.js +7 -4
- package/lib/cjs/components/editgrid/fixtures/formsWithEditGridAndConditions.d.ts +910 -0
- package/lib/cjs/components/editgrid/fixtures/formsWithEditGridAndConditions.js +923 -0
- package/lib/cjs/components/html/HTML.d.ts +1 -0
- package/lib/cjs/components/html/HTML.js +9 -0
- package/lib/cjs/components/recaptcha/ReCaptcha.js +3 -3
- package/lib/cjs/formio.form.js +14 -0
- package/lib/cjs/translations/en.d.ts +2 -0
- package/lib/cjs/translations/en.js +2 -0
- package/lib/cjs/validator/Validator.js +1 -1
- package/lib/mjs/Form.js +0 -15
- package/lib/mjs/components/_classes/component/Component.js +10 -4
- package/lib/mjs/components/_classes/component/editForm/Component.edit.validation.js +8 -0
- package/lib/mjs/components/_classes/nested/NestedComponent.js +2 -2
- package/lib/mjs/components/datagrid/DataGrid.js +2 -1
- package/lib/mjs/components/datagrid/fixtures/comp-with-allow-calculate-override.js +1 -1
- package/lib/mjs/components/datagrid/fixtures/index.d.ts +2 -1
- package/lib/mjs/components/datagrid/fixtures/index.js +2 -1
- package/lib/mjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.d.ts +53 -0
- package/lib/mjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.js +102 -0
- package/lib/mjs/components/editgrid/EditGrid.js +7 -4
- package/lib/mjs/components/editgrid/fixtures/formsWithEditGridAndConditions.d.ts +910 -0
- package/lib/mjs/components/editgrid/fixtures/formsWithEditGridAndConditions.js +921 -0
- package/lib/mjs/components/html/HTML.d.ts +1 -0
- package/lib/mjs/components/html/HTML.js +8 -0
- package/lib/mjs/components/recaptcha/ReCaptcha.js +3 -3
- package/lib/mjs/formio.form.js +14 -0
- package/lib/mjs/translations/en.d.ts +2 -0
- package/lib/mjs/translations/en.js +2 -0
- package/lib/mjs/validator/Validator.js +1 -1
- package/package.json +2 -2
package/dist/formio.form.js
CHANGED
|
@@ -4822,7 +4822,7 @@ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ?
|
|
|
4822
4822
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
4823
4823
|
|
|
4824
4824
|
"use strict";
|
|
4825
|
-
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 __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 __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 }));\nconst Element_1 = __importDefault(__webpack_require__(/*! ./Element */ \"./lib/cjs/Element.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst displays_1 = __importDefault(__webpack_require__(/*! ./displays */ \"./lib/cjs/displays/index.js\"));\nconst templates_1 = __importDefault(__webpack_require__(/*! ./templates */ \"./lib/cjs/templates/index.js\"));\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nclass Form extends Element_1.default {\n /**\n * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n *\n * @param {Object} element - The DOM element you wish to render this form within.\n * @param {Object | string} form - Either a Form JSON schema or the URL of a hosted form via. form.io.\n * @param {Object} options - The options to create a new form instance.\n * @param {boolean} options.readOnly - Set this form to readOnly\n * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog.\n * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js\n * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form.\n *\n * @example\n * import Form from '@formio/js/Form';\n * const form = new Form(document.getElementById('formio'), 'https://examples.form.io/example');\n * form.build();\n */\n constructor(...args) {\n let options = args[0] instanceof HTMLElement ? args[2] : args[1];\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n options = Object.assign(options, Formio_1.Formio.options.form);\n }\n super(options);\n if (this.options.useSessionToken) {\n Formio_1.Formio.useSessionToken(this.options);\n }\n this.ready = new Promise((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n this.instance = null;\n if (args[0] instanceof HTMLElement) {\n if (this.element) {\n delete this.element.component;\n }\n this.element = args[0];\n this.options = args[2] || {};\n this.options.events = this.events;\n this.setForm(args[1])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else if (args[0]) {\n this.element = null;\n this.options = args[1] || {};\n this.options.events = this.events;\n this.setForm(args[0])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else {\n this.element = null;\n this.options = {};\n this.options.events = this.events;\n }\n this.display = '';\n }\n createElement(tag, attrs, children) {\n const element = document.createElement(tag);\n for (const attr in attrs) {\n if (attrs.hasOwnProperty(attr)) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n (children || []).forEach(child => {\n element.appendChild(this.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n set loading(load) {\n if (!this.element || this.options.noLoader) {\n return;\n }\n if (load) {\n if (this.loader) {\n return;\n }\n this.loader = this.createElement('div', {\n 'class': 'formio-loader'\n }, [{\n tag: 'div',\n attrs: {\n class: 'loader-wrapper'\n },\n children: [{\n tag: 'div',\n attrs: {\n class: 'loader text-center'\n }\n }]\n }]);\n this.element.appendChild(this.loader);\n }\n else if (this.loader) {\n if (this.element.contains(this.loader)) {\n this.element.removeChild(this.loader);\n }\n this.loader = null;\n }\n }\n /**\n * Create a new form instance provided the display of the form.\n *\n * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @return {*}\n */\n create(display) {\n if (this.options && (this.options.flatten || this.options.renderMode === 'flat')) {\n display = 'form';\n }\n this.display = display;\n if (displays_1.default.displays[display]) {\n return new displays_1.default.displays[display](this.element, this.options);\n }\n else {\n // eslint-disable-next-line new-cap\n return new displays_1.default.displays['webform'](this.element, this.options);\n }\n }\n /**\n * Sets the form. Either as JSON or a URL to a form JSON schema.\n *\n * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @return {*}\n */\n set form(formParam) {\n this.setForm(formParam);\n }\n errorForm(err) {\n return {\n components: [\n {\n 'label': 'HTML',\n 'tag': 'div',\n 'className': 'error error-message alert alert-danger ui red message',\n 'attrs': [\n {\n 'attr': 'role',\n 'value': 'alert'\n }\n ],\n 'key': 'errorMessage',\n 'type': 'htmlelement',\n 'input': false,\n 'content': typeof err === 'string' ? err : err.message,\n }\n ]\n };\n }\n setForm(formParam) {\n let result;\n formParam = formParam || this.form;\n if (typeof formParam === 'string') {\n const formio = new Formio_1.Formio(formParam);\n let error;\n this.loading = true;\n result = this.getSubmission(formio, this.options)\n .catch((err) => {\n error = err;\n })\n .then((submission) => {\n return formio.loadForm()\n // If the form returned an error, show it instead of the form.\n .catch(err => {\n error = err;\n })\n .then((form) => {\n // If the submission returned an error, show it instead of the form.\n if (error) {\n form = this.errorForm(error);\n }\n this.loading = false;\n this.instance = this.instance || this.create(form.display);\n this.instance.url = formParam;\n this.instance.nosubmit = false;\n this._form = this.instance.form = form;\n if (submission) {\n this.instance.submission = submission;\n }\n if (error) {\n throw error;\n }\n return this.instance;\n });\n });\n }\n else {\n this.instance = this.instance || this.create(formParam.display);\n this._form = this.instance.form = formParam;\n result = this.instance.ready;\n }\n // A redraw has occurred so save off the new element in case of a setDisplay causing a rebuild.\n return result.then(() => {\n if (this.element) {\n delete this.element.component;\n }\n this.element = this.instance.element;\n return this.instance;\n });\n }\n getSubmission(formio, opts) {\n if (formio.submissionId) {\n return formio.loadSubmission(null, opts);\n }\n return Promise.resolve();\n }\n /**\n * Returns the loaded forms JSON.\n *\n * @return {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n *\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @return {Promise<T>}\n */\n setDisplay(display) {\n if ((this.display === display) && this.instance) {\n return Promise.resolve(this.instance);\n }\n this.form.display = display;\n this.instance.destroy();\n this.instance = this.create(display);\n return this.setForm(this.form);\n }\n empty() {\n if (this.element) {\n while (this.element.firstChild) {\n this.element.removeChild(this.element.firstChild);\n }\n }\n }\n static embed(embed) {\n return new Promise((resolve) => {\n if (!embed || !embed.src) {\n resolve();\n }\n const id = this.id || `formio-${Math.random().toString(36).substring(7)}`;\n const className = embed.class || 'formio-form-wrapper';\n let code = embed.styles ? `<link rel=\"stylesheet\" href=\"${embed.styles}\">` : '';\n code += `<div id=\"${id}\" class=\"${className}\"></div>`;\n document.write(code);\n let attempts = 0;\n const wait = setInterval(() => {\n attempts++;\n const formElement = document.getElementById(id);\n if (formElement || attempts > 10) {\n resolve(new Form(formElement, embed.src).ready);\n clearInterval(wait);\n }\n }, 10);\n });\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize) {\n // If Sanitize is turned off\n if (this.options.sanitize === false && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, this.options);\n }\n setContent(element, content, forceSanitize) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize);\n return true;\n }\n return false;\n }\n /**\n * Build a new form.\n *\n * @return {Promise<T>}\n */\n build() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (!this.element) {\n return Promise.reject('No DOM element for form.');\n }\n // Add temporary loader.\n const template = (this.options && this.options.template) ? this.options.template : 'bootstrap';\n const loader = templates_1.default[template].loader || templates_1.default.bootstrap.loader;\n this.setContent(this.element, loader.form);\n return this.render().then(html => {\n this.setContent(this.element, html);\n return this.attach(this.element).then(() => this.instance);\n })\n .then((param) => {\n this.emit('build', param);\n return param;\n });\n }\n render() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n return Promise.resolve(this.instance.render())\n .then((param) => {\n this.emit('render', param);\n return param;\n });\n }\n attach(element) {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (this.element) {\n delete this.element.component;\n }\n this.element = element;\n return this.instance.attach(this.element)\n .then((param) => {\n this.emit('attach', param);\n return param;\n });\n }\n teardown() {\n super.teardown();\n delete this.instance;\n delete this.ready;\n }\n}\nexports[\"default\"] = Form;\n// Allow simple embedding.\nFormio_1.Formio.embedForm = (embed) => Form.embed(embed);\n/**\n * Factory that creates a new form based on the form parameters.\n *\n * @param element {HMTLElement} - The HTML Element to add this form to.\n * @param form {string|Object} - The src of the form, or a form object.\n * @param options {Object} - The options to create this form.\n *\n * @return {Promise} - When the form is instance is ready.\n */\nFormio_1.Formio.createForm = (...args) => {\n return (new Form(...args)).ready;\n};\nFormio_1.Formio.Form = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
|
|
4825
|
+
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 __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 __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 }));\nconst Element_1 = __importDefault(__webpack_require__(/*! ./Element */ \"./lib/cjs/Element.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst displays_1 = __importDefault(__webpack_require__(/*! ./displays */ \"./lib/cjs/displays/index.js\"));\nconst templates_1 = __importDefault(__webpack_require__(/*! ./templates */ \"./lib/cjs/templates/index.js\"));\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nclass Form extends Element_1.default {\n /**\n * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n *\n * @param {Object} element - The DOM element you wish to render this form within.\n * @param {Object | string} form - Either a Form JSON schema or the URL of a hosted form via. form.io.\n * @param {Object} options - The options to create a new form instance.\n * @param {boolean} options.readOnly - Set this form to readOnly\n * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog.\n * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js\n * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form.\n *\n * @example\n * import Form from '@formio/js/Form';\n * const form = new Form(document.getElementById('formio'), 'https://examples.form.io/example');\n * form.build();\n */\n constructor(...args) {\n let options = args[0] instanceof HTMLElement ? args[2] : args[1];\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n options = Object.assign(options, Formio_1.Formio.options.form);\n }\n super(options);\n if (this.options.useSessionToken) {\n Formio_1.Formio.useSessionToken(this.options);\n }\n this.ready = new Promise((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n this.instance = null;\n if (args[0] instanceof HTMLElement) {\n if (this.element) {\n delete this.element.component;\n }\n this.element = args[0];\n this.options = args[2] || {};\n this.options.events = this.events;\n this.setForm(args[1])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else if (args[0]) {\n this.element = null;\n this.options = args[1] || {};\n this.options.events = this.events;\n this.setForm(args[0])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else {\n this.element = null;\n this.options = {};\n this.options.events = this.events;\n }\n this.display = '';\n }\n createElement(tag, attrs, children) {\n const element = document.createElement(tag);\n for (const attr in attrs) {\n if (attrs.hasOwnProperty(attr)) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n (children || []).forEach(child => {\n element.appendChild(this.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n set loading(load) {\n if (!this.element || this.options.noLoader) {\n return;\n }\n if (load) {\n if (this.loader) {\n return;\n }\n this.loader = this.createElement('div', {\n 'class': 'formio-loader'\n }, [{\n tag: 'div',\n attrs: {\n class: 'loader-wrapper'\n },\n children: [{\n tag: 'div',\n attrs: {\n class: 'loader text-center'\n }\n }]\n }]);\n this.element.appendChild(this.loader);\n }\n else if (this.loader) {\n if (this.element.contains(this.loader)) {\n this.element.removeChild(this.loader);\n }\n this.loader = null;\n }\n }\n /**\n * Create a new form instance provided the display of the form.\n *\n * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @return {*}\n */\n create(display) {\n if (this.options && (this.options.flatten || this.options.renderMode === 'flat')) {\n display = 'form';\n }\n this.display = display;\n if (displays_1.default.displays[display]) {\n return new displays_1.default.displays[display](this.element, this.options);\n }\n else {\n // eslint-disable-next-line new-cap\n return new displays_1.default.displays['webform'](this.element, this.options);\n }\n }\n /**\n * Sets the form. Either as JSON or a URL to a form JSON schema.\n *\n * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @return {*}\n */\n set form(formParam) {\n this.setForm(formParam);\n }\n errorForm(err) {\n return {\n components: [\n {\n 'label': 'HTML',\n 'tag': 'div',\n 'className': 'error error-message alert alert-danger ui red message',\n 'attrs': [\n {\n 'attr': 'role',\n 'value': 'alert'\n }\n ],\n 'key': 'errorMessage',\n 'type': 'htmlelement',\n 'input': false,\n 'content': typeof err === 'string' ? err : err.message,\n }\n ]\n };\n }\n setForm(formParam) {\n let result;\n formParam = formParam || this.form;\n if (typeof formParam === 'string') {\n const formio = new Formio_1.Formio(formParam);\n let error;\n this.loading = true;\n result = this.getSubmission(formio, this.options)\n .catch((err) => {\n error = err;\n })\n .then((submission) => {\n return formio.loadForm()\n // If the form returned an error, show it instead of the form.\n .catch(err => {\n error = err;\n })\n .then((form) => {\n // If the submission returned an error, show it instead of the form.\n if (error) {\n form = this.errorForm(error);\n }\n this.loading = false;\n this.instance = this.instance || this.create(form.display);\n this.instance.url = formParam;\n this.instance.nosubmit = false;\n this._form = this.instance.form = form;\n if (submission) {\n this.instance.submission = submission;\n }\n if (error) {\n throw error;\n }\n return this.instance;\n });\n });\n }\n else {\n this.instance = this.instance || this.create(formParam.display);\n this._form = this.instance.form = formParam;\n result = this.instance.ready;\n }\n // A redraw has occurred so save off the new element in case of a setDisplay causing a rebuild.\n return result.then(() => {\n if (this.element) {\n delete this.element.component;\n }\n this.element = this.instance.element;\n return this.instance;\n });\n }\n getSubmission(formio, opts) {\n if (formio.submissionId) {\n return formio.loadSubmission(null, opts);\n }\n return Promise.resolve();\n }\n /**\n * Returns the loaded forms JSON.\n *\n * @return {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n *\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @return {Promise<T>}\n */\n setDisplay(display) {\n if ((this.display === display) && this.instance) {\n return Promise.resolve(this.instance);\n }\n this.form.display = display;\n this.instance.destroy();\n this.instance = this.create(display);\n return this.setForm(this.form);\n }\n empty() {\n if (this.element) {\n while (this.element.firstChild) {\n this.element.removeChild(this.element.firstChild);\n }\n }\n }\n static embed(embed) {\n return new Promise((resolve) => {\n if (!embed || !embed.src) {\n resolve();\n }\n const id = this.id || `formio-${Math.random().toString(36).substring(7)}`;\n const className = embed.class || 'formio-form-wrapper';\n let code = embed.styles ? `<link rel=\"stylesheet\" href=\"${embed.styles}\">` : '';\n code += `<div id=\"${id}\" class=\"${className}\"></div>`;\n document.write(code);\n let attempts = 0;\n const wait = setInterval(() => {\n attempts++;\n const formElement = document.getElementById(id);\n if (formElement || attempts > 10) {\n resolve(new Form(formElement, embed.src).ready);\n clearInterval(wait);\n }\n }, 10);\n });\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize) {\n // If Sanitize is turned off\n if (this.options.sanitize === false && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, this.options);\n }\n setContent(element, content, forceSanitize) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize);\n return true;\n }\n return false;\n }\n /**\n * Build a new form.\n *\n * @return {Promise<T>}\n */\n build() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (!this.element) {\n return Promise.reject('No DOM element for form.');\n }\n // Add temporary loader.\n const template = (this.options && this.options.template) ? this.options.template : 'bootstrap';\n const loader = templates_1.default[template].loader || templates_1.default.bootstrap.loader;\n this.setContent(this.element, loader.form);\n return this.render().then(html => {\n this.setContent(this.element, html);\n return this.attach(this.element).then(() => this.instance);\n })\n .then((param) => {\n this.emit('build', param);\n return param;\n });\n }\n render() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n return Promise.resolve(this.instance.render())\n .then((param) => {\n this.emit('render', param);\n return param;\n });\n }\n attach(element) {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (this.element) {\n delete this.element.component;\n }\n this.element = element;\n return this.instance.attach(this.element)\n .then((param) => {\n this.emit('attach', param);\n return param;\n });\n }\n teardown() {\n super.teardown();\n delete this.instance;\n delete this.ready;\n }\n}\nexports[\"default\"] = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
|
|
4826
4826
|
|
|
4827
4827
|
/***/ }),
|
|
4828
4828
|
|
|
@@ -4932,7 +4932,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4932
4932
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
4933
4933
|
|
|
4934
4934
|
"use strict";
|
|
4935
|
-
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 __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 __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 }));\n/* globals Quill, ClassicEditor, CKEDITOR */\nconst vanilla_text_mask_1 = __webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\");\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst ismobilejs_1 = __importDefault(__webpack_require__(/*! ismobilejs */ \"./node_modules/ismobilejs/esm/index.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../../Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst Validator_1 = __importDefault(__webpack_require__(/*! ../../../validator/Validator */ \"./lib/cjs/validator/Validator.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Element_1 = __importDefault(__webpack_require__(/*! ../../../Element */ \"./lib/cjs/Element.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst addons_1 = __importDefault(__webpack_require__(/*! ../../../addons */ \"./lib/cjs/addons/index.js\"));\nconst uploadAdapter_1 = __webpack_require__(/*! ../../../providers/storage/uploadAdapter */ \"./lib/cjs/providers/storage/uploadAdapter.js\");\nconst en_1 = __importDefault(__webpack_require__(/*! ../../../translations/en */ \"./lib/cjs/translations/en.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ../../../templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nconst isIEBrowser = FormioUtils.getBrowserInfo().ie;\n/**\n * This is the Component class\n which all elements within the FormioForm derive from.\n */\nclass Component extends Element_1.default {\n static schema(...sources) {\n return lodash_1.default.merge({\n /**\n * Determines if this component provides an input.\n */\n input: true,\n /**\n * The data key for this component (how the data is stored in the database).\n */\n key: '',\n /**\n * The input placeholder for this component.\n */\n placeholder: '',\n /**\n * The input prefix\n */\n prefix: '',\n /**\n * The custom CSS class to provide to this component.\n */\n customClass: '',\n /**\n * The input suffix.\n */\n suffix: '',\n /**\n * If this component should allow an array of values to be captured.\n */\n multiple: false,\n /**\n * The default value of this component.\n */\n defaultValue: null,\n /**\n * If the data of this component should be protected (no GET api requests can see the data)\n */\n protected: false,\n /**\n * Validate if the value of this component should be unique within the form.\n */\n unique: false,\n /**\n * If the value of this component should be persisted within the backend api database.\n */\n persistent: true,\n /**\n * Determines if the component should be within the form, but not visible.\n */\n hidden: false,\n /**\n * If the component should be cleared when hidden.\n */\n clearOnHide: true,\n /**\n * This will refresh this component options when this field changes.\n */\n refreshOn: '',\n /**\n * This will redraw the component when this field changes.\n */\n redrawOn: '',\n /**\n * If this component should be included as a column within a submission table.\n */\n tableView: false,\n /**\n * If this component should be rendering in modal.\n */\n modalEdit: false,\n /**\n * The input label provided to this component.\n */\n label: '',\n dataGridLabel: false,\n labelPosition: 'top',\n description: '',\n errorLabel: '',\n tooltip: '',\n hideLabel: false,\n tabindex: '',\n disabled: false,\n autofocus: false,\n dbIndex: false,\n customDefaultValue: '',\n calculateValue: '',\n calculateServer: false,\n widget: null,\n /**\n * Attributes that will be assigned to the input elements of this component.\n */\n attributes: {},\n /**\n * This will perform the validation on either \"change\" or \"blur\" of the input element.\n */\n validateOn: 'change',\n /**\n * The validation criteria for this component.\n */\n validate: {\n /**\n * If this component is required.\n */\n required: false,\n /**\n * Custom JavaScript validation.\n */\n custom: '',\n /**\n * If the custom validation should remain private (only the backend will see it and execute it).\n */\n customPrivate: false,\n /**\n * If this component should implement a strict date validation if the Calendar widget is implemented.\n */\n strictDateValidation: false,\n multiple: false,\n unique: false\n },\n /**\n * The simple conditional settings for a component.\n */\n conditional: {\n show: null,\n when: null,\n eq: ''\n },\n overlay: {\n style: '',\n left: '',\n top: '',\n width: '',\n height: '',\n },\n allowCalculateOverride: false,\n encrypted: false,\n showCharCount: false,\n showWordCount: false,\n properties: {},\n allowMultipleMasks: false,\n addons: [],\n }, ...sources);\n }\n /**\n * Return the validator as part of the component.\n *\n * @return {ValidationChecker}\n * @constructor\n */\n static get Validator() {\n return Validator_1.default;\n }\n /**\n * Return the simple condition settings as part of the component.\n *\n * @return {Object}\n *\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n *\n * @param schema\n * @return {Array}\n *\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n *\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n *\n * @param {Object} component - The component JSON you wish to initialize.\n * @param {Object} options - The options for this component.\n * @param {Object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * Set the validator instance.\n */\n this.validator = Validator_1.default;\n /**\n * The data path to this specific component instance.\n *\n * @type {string}\n */\n this.path = '';\n /**\n * The Form.io component JSON schema.\n * @type {*}\n */\n this.component = this.mergeSchema(component || {});\n // Add the id to the component.\n this.component.id = this.id;\n this.afterComponentAssign();\n // Save off the original component to be used in logic.\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n /**\n * If the component has been attached\n */\n this.attached = false;\n /**\n * If the component has been rendered\n */\n this.rendered = false;\n /**\n * The data object in which this component resides.\n * @type {*}\n */\n this._data = data || {};\n /**\n * The existing error that this component has.\n * @type {string}\n */\n this.error = '';\n /**\n * Tool tip text after processing\n * @type {string}\n */\n this.tooltip = '';\n /**\n * The row path of this component.\n * @type {number}\n */\n this.row = this.options.row;\n /**\n * Determines if this component is disabled, or not.\n *\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n *\n * @type {Component}\n */\n this.root = this.options.root;\n this.localRoot = this.options.localRoot;\n /**\n * If this input has been input and provided value.\n *\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n *\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n /**\n * The validators that are assigned to this component.\n * @type {[string]}\n */\n this.validators = ['required', 'minLength', 'maxLength', 'minWords', 'maxWords', 'custom', 'pattern', 'json', 'mask'];\n this._path = '';\n // Nested forms don't have parents so we need to pass their path in.\n this._parentPath = this.options.parentPath || '';\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n /**\n * Determines if this component is visible, or not.\n */\n this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;\n this._visible = this._parentVisible && this.conditionallyVisible(null, data);\n this._parentDisabled = false;\n /**\n * Used to trigger a new change in this component.\n * @type {function} - Call to trigger a change in this component.\n */\n let changes = [];\n let lastChanged = null;\n let triggerArgs = [];\n const _triggerChange = lodash_1.default.debounce((...args) => {\n if (this.root) {\n this.root.changing = false;\n }\n triggerArgs = [];\n if (!args[1] && lastChanged) {\n // Set the changed component if one isn't provided.\n args[1] = lastChanged;\n }\n if (lodash_1.default.isEmpty(args[0]) && lastChanged) {\n // Set the flags if it is empty and lastChanged exists.\n args[0] = lastChanged.flags;\n }\n lastChanged = null;\n args[3] = changes;\n const retVal = this.onChange(...args);\n changes = [];\n return retVal;\n }, 100);\n this.triggerChange = (...args) => {\n if (args[1]) {\n // Make sure that during the debounce that we always track lastChanged component, even if they\n // don't provide one later.\n lastChanged = args[1];\n changes.push(lastChanged);\n }\n if (this.root) {\n this.root.changing = true;\n }\n if (args.length) {\n triggerArgs = args;\n }\n return _triggerChange(...triggerArgs);\n };\n /**\n * Used to trigger a redraw event within this component.\n *\n * @type {Function}\n */\n this.triggerRedraw = lodash_1.default.debounce(this.redraw.bind(this), 100);\n /**\n * list of attached tooltips\n * @type {Array}\n */\n this.tooltips = [];\n /**\n * List of attached addons\n * @type {Array}\n */\n this.addons = [];\n // To force this component to be invalid.\n this.invalid = false;\n if (this.component) {\n this.type = this.component.type;\n if (this.allowData && this.key) {\n this.options.name += `[${this.key}]`;\n // If component is visible or not set to clear on hide, set the default value.\n if (this.visible || !this.component.clearOnHide) {\n if (!this.hasValue()) {\n if (this.shouldAddDefaultValue) {\n this.dataValue = this.defaultValue;\n }\n }\n else {\n // Ensure the dataValue is set.\n /* eslint-disable no-self-assign */\n this.dataValue = this.dataValue;\n /* eslint-enable no-self-assign */\n }\n }\n }\n /**\n * The element information for creating the input element.\n * @type {*}\n */\n this.info = this.elementInfo();\n }\n // Allow anyone to hook into the component creation.\n this.hook('component');\n if (!this.options.skipInit) {\n this.init();\n }\n }\n /* eslint-enable max-statements */\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n }\n mergeSchema(component = {}) {\n return lodash_1.default.defaultsDeep(component, this.defaultSchema);\n }\n // Allow componets to notify when ready.\n get ready() {\n return Promise.resolve(this);\n }\n get isPDFReadOnlyMode() {\n return this.parent &&\n this.parent.form &&\n (this.parent.form.display === 'pdf') &&\n this.options.readOnly;\n }\n get labelInfo() {\n const label = {};\n label.hidden = this.labelIsHidden();\n label.className = '';\n label.labelPosition = this.component.labelPosition;\n label.tooltipClass = `${this.iconClass('question-sign')} text-muted`;\n const isPDFReadOnlyMode = this.isPDFReadOnlyMode;\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required) && !isPDFReadOnlyMode) {\n label.className += ' field-required';\n }\n if (label.hidden) {\n label.className += ' control-label--hidden';\n }\n if (this.info.attr.id) {\n label.for = this.info.attr.id;\n }\n return label;\n }\n init() {\n var _a;\n this.disabled = this.shouldDisabled;\n this._visible = this.conditionallyVisible(null, null);\n if ((_a = this.component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n this.component.addons.forEach((addon) => this.createAddon(addon));\n }\n }\n afterComponentAssign() {\n //implement in extended classes\n }\n createAddon(addonConfiguration) {\n var _a;\n const name = addonConfiguration.name;\n if (!name) {\n return;\n }\n const settings = ((_a = addonConfiguration.settings) === null || _a === void 0 ? void 0 : _a.data) || {};\n const Addon = addons_1.default[name.value];\n let addon = null;\n if (Addon) {\n const supportedComponents = Addon.info.supportedComponents;\n const supportsThisComponentType = !(supportedComponents === null || supportedComponents === void 0 ? void 0 : supportedComponents.length) ||\n supportedComponents.indexOf(this.component.type) !== -1;\n if (supportsThisComponentType) {\n addon = new Addon(settings, this);\n this.addons.push(addon);\n }\n else {\n console.warn(`Addon ${name.label} does not support component of type ${this.component.type}.`);\n }\n }\n return addon;\n }\n teardown() {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n delete this._currentForm;\n delete this.parent;\n delete this.root;\n delete this.triggerChange;\n delete this.triggerRedraw;\n if (this.options) {\n delete this.options.root;\n delete this.options.parent;\n delete this.options.i18next;\n }\n super.teardown();\n }\n destroy(all = false) {\n super.destroy(all);\n this.detach();\n this.addons.forEach((addon) => addon.destroy());\n if (all) {\n this.teardown();\n }\n }\n get shouldDisabled() {\n return this.options.readOnly || this.component.disabled || (this.options.hasOwnProperty('disabled') && this.options.disabled[this.key]);\n }\n get isInputComponent() {\n return !this.component.hasOwnProperty('input') || this.component.input;\n }\n get allowData() {\n return this.hasInput;\n }\n get hasInput() {\n return this.isInputComponent || (this.refs.input && this.refs.input.length);\n }\n get defaultSchema() {\n return Component.schema();\n }\n get key() {\n return lodash_1.default.get(this.component, 'key', '');\n }\n set parentVisible(value) {\n this._parentVisible = value;\n }\n get parentVisible() {\n return this._parentVisible;\n }\n set parentDisabled(value) {\n this._parentDisabled = value;\n }\n get parentDisabled() {\n return this._parentDisabled;\n }\n shouldForceVisibility(component, visibility) {\n if (!this.options[visibility]) {\n return false;\n }\n if (!component) {\n component = this.component;\n }\n if (lodash_1.default.isArray(this.options[visibility])) {\n return this.options[visibility].includes(component.key);\n }\n return this.options[visibility][component.key];\n }\n shouldForceHide(component) {\n return this.shouldForceVisibility(component, 'hide');\n }\n shouldForceShow(component) {\n return this.shouldForceVisibility(component, 'show');\n }\n /**\n *\n * @param value {boolean}\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n *\n * @returns {boolean}\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n *\n * @param schema\n * @param defaultSchema\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = this.rootValue;\n params.row = this.data;\n params.component = this.component;\n return super.t(text, params, ...args);\n }\n labelIsHidden() {\n return !this.component.label ||\n ((!this.isInDataGrid && this.component.hideLabel) ||\n (this.isInDataGrid && !this.component.dataGridLabel) ||\n this.options.floatingLabels ||\n this.options.inputsOnly) && !this.builderMode;\n }\n transform(type, value) {\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n return frameworkTemplates.hasOwnProperty('transform')\n ? frameworkTemplates.transform(type, value, this)\n : (type, value) => value;\n }\n getTemplate(names, modes) {\n modes = Array.isArray(modes) ? modes : [modes];\n names = Array.isArray(names) ? names : [names];\n if (!modes.includes('form')) {\n modes.push('form');\n }\n let result = null;\n if (this.options.templates) {\n result = this.checkTemplate(this.options.templates, names, modes);\n if (result) {\n return result;\n }\n }\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n result = this.checkTemplate(frameworkTemplates, names, modes);\n if (result) {\n return result;\n }\n // Default back to bootstrap if not defined.\n const name = names[names.length - 1];\n const templatesByName = Templates_1.default.defaultTemplates[name];\n if (!templatesByName) {\n return `Unknown template: ${name}`;\n }\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return templateByMode;\n }\n return templatesByName.form;\n }\n checkTemplate(templates, names, modes) {\n for (const name of names) {\n const templatesByName = templates[name];\n if (templatesByName) {\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return templateByMode;\n }\n }\n }\n return null;\n }\n checkTemplateMode(templatesByName, modes) {\n for (const mode of modes) {\n const templateByMode = templatesByName[mode];\n if (templateByMode) {\n return templateByMode;\n }\n }\n return null;\n }\n getFormattedAttribute(attr) {\n return attr ? this.t(attr, { _userInput: true }).replace(/\"/g, '"') : '';\n }\n getFormattedTooltip(tooltipValue) {\n const tooltip = this.interpolate(tooltipValue || '').replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n return this.getFormattedAttribute(tooltip);\n }\n isHtmlRenderMode() {\n return this.options.renderMode === 'html';\n }\n renderTemplate(name, data = {}, modeOption) {\n // Need to make this fall back to form if renderMode is not found similar to how we search templates.\n const mode = modeOption || this.options.renderMode || 'form';\n data.component = this.component;\n data.self = this;\n data.options = this.options;\n data.readOnly = this.options.readOnly;\n data.iconClass = this.iconClass.bind(this);\n data.size = this.size.bind(this);\n data.t = this.t.bind(this);\n data.transform = this.transform.bind(this);\n data.id = data.id || this.id;\n data.key = data.key || this.key;\n data.value = data.value || this.dataValue;\n data.disabled = this.disabled;\n data.builder = this.builderMode;\n data.render = (...args) => {\n console.warn(`Form.io 'render' template function is deprecated.\n If you need to render template (template A) inside of another template (template B),\n pass pre-compiled template A (use this.renderTemplate('template_A_name') as template context variable for template B`);\n return this.renderTemplate(...args);\n };\n data.label = data.labelInfo || this.labelInfo;\n data.tooltip = this.getFormattedTooltip(this.component.tooltip);\n // Allow more specific template names\n const names = [\n `${name}-${this.component.type}-${this.key}`,\n `${name}-${this.component.type}`,\n `${name}-${this.key}`,\n `${name}`,\n ];\n // Allow template alters.\n return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(this.getTemplate(names, mode), data), data, mode);\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize, options) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n *\n * @param template\n * @param data\n * @param actions\n *\n * @return {HTMLElement|String} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n performInputMapping(input) {\n return input;\n }\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components\n * to perform special functions.\n *\n * @return {*}\n */\n beforePage() {\n return Promise.resolve(true);\n }\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components\n * to perform special async functions.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n *\n * @return {*}\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n get timezone() {\n return this.getTimezone(this.component);\n }\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n loadRefs(element, refs) {\n for (const ref in refs) {\n const refType = refs[ref];\n const isString = typeof refType === 'string';\n const selector = isString && refType.includes('scope') ? `:scope > [ref=\"${ref}\"]` : `[ref=\"${ref}\"]`;\n if (isString && refType.startsWith('single')) {\n this.refs[ref] = element.querySelector(selector);\n }\n else {\n this.refs[ref] = element.querySelectorAll(selector);\n }\n }\n }\n setOpenModalElement(template) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n const message = this.error ? {\n level: 'error',\n message: this.error.message,\n } : '';\n let modalLabel;\n if (this.hasInput && ((_a = this.component.validate) === null || _a === void 0 ? void 0 : _a.required) && !this.isPDFReadOnlyMode) {\n modalLabel = { className: 'field-required' };\n }\n return this.renderTemplate('modalPreview', {\n previewText: this.getValueAsString(dataValue, { modalPreview: true }) || this.t('Click to set value'),\n messages: message && this.renderTemplate('message', message),\n labelInfo: modalLabel,\n });\n }\n build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue);\n }\n attach(element) {\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n const openModalTemplate = this.componentModal && modalShouldBeOpened\n ? this.componentModal.openModalTemplate\n : null;\n this.componentModal = this.createComponentModal(element, modalShouldBeOpened, currentValue);\n this.setOpenModalElement(openModalTemplate);\n }\n this.attached = true;\n this.setElement(element);\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n // First iterate through each ref and delete the component so there are no dangling component references.\n lodash_1.default.each(this.refs, (ref) => {\n if (typeof ref === NodeList) {\n ref.forEach((elem) => {\n delete elem.component;\n });\n }\n else if (ref) {\n delete ref.component;\n }\n });\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n *\n * @param value\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n *\n * @param component\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n setElement(element) {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n this.element = element;\n }\n createViewOnlyElement() {\n this.setElement(this.ce('dl', {\n id: this.id\n }));\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n *\n * @param value\n * @return {*}\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * @param {*} data\n * @param {boolean} [forceUseValue=false] - if true, return 'value' property of the data\n * @return {*}\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @return {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement}\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n *\n * @param pristine {boolean} - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n get isPristine() {\n return this.pristine;\n }\n setDirty(dirty) {\n this.dirty = dirty;\n }\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n /**\n * Returns the error label for this component.\n * @return {*}\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param type\n * @return {*}\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.setElement(parent.children[index]);\n return this.attach(this.element);\n }\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n *\n * @return {null}\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n *\n * @param data\n * @return {boolean}\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n *\n * @param row - The row contextual data.\n * @param data - The global data object.\n * @return {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param args\n * @return {boolean}\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n *\n * @param data\n */\n fieldLogic(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n *\n * @param message\n * @param dirty\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n if (message.message && typeof message.message === 'string') {\n message.message = message.message.replaceAll('<', '<').replaceAll('>', '>');\n }\n return this.renderTemplate('message', message);\n }).join(''));\n }\n }\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root) {\n this.root.triggerChange(...args);\n }\n }\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur' && !this.errors.length) {\n flags.noValidate = true;\n }\n if (this.component.onChange) {\n this.evaluate(this.component.onChange, {\n flags\n });\n }\n // Set the changed variable.\n const changed = {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: flags\n };\n // Emit the change.\n this.emit('componentChange', changed);\n // Do not propogate the modified flag.\n let modified = false;\n if (flags.modified) {\n modified = true;\n delete flags.modified;\n }\n // Bubble this change up to the top.\n if (!fromRoot) {\n this.triggerRootChange(flags, changed, modified);\n }\n return changed;\n }\n get wysiwygDefault() {\n return {\n quill: {\n theme: 'snow',\n placeholder: this.t(this.component.placeholder, { _userInput: true }),\n modules: {\n toolbar: [\n [{ 'size': ['small', false, 'large', 'huge'] }],\n [{ 'header': [1, 2, 3, 4, 5, 6, false] }],\n [{ 'font': [] }],\n ['bold', 'italic', 'underline', 'strike', { 'script': 'sub' }, { 'script': 'super' }, 'clean'],\n [{ 'color': [] }, { 'background': [] }],\n [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }, { 'align': [] }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video', 'formula', 'source']\n ]\n }\n },\n ace: {\n theme: 'ace/theme/xcode',\n maxLines: 12,\n minLines: 12,\n tabSize: 2,\n mode: 'ace/mode/javascript',\n placeholder: this.t(this.component.placeholder, { _userInput: true })\n },\n ckeditor: {\n image: {\n toolbar: [\n 'imageTextAlternative',\n '|',\n 'imageStyle:full',\n 'imageStyle:alignLeft',\n 'imageStyle:alignCenter',\n 'imageStyle:alignRight'\n ],\n styles: [\n 'full',\n 'alignLeft',\n 'alignCenter',\n 'alignRight'\n ]\n },\n extraPlugins: []\n },\n default: {}\n };\n }\n addCKE(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? {} : settings;\n settings.base64Upload = this.component.isUploadEnabled ? false : true;\n settings.mediaEmbed = { previewsInData: true };\n settings = lodash_1.default.merge(this.wysiwygDefault.ckeditor, lodash_1.default.get(this.options, 'editors.ckeditor.settings', {}), settings);\n if (this.component.isUploadEnabled) {\n settings.extraPlugins.push((0, uploadAdapter_1.getFormioUploadAdapterPlugin)(this.fileService, this));\n }\n return Formio_1.Formio.requireLibrary('ckeditor', isIEBrowser ? 'CKEDITOR' : 'ClassicEditor', lodash_1.default.get(this.options, 'editors.ckeditor.src', `${Formio_1.Formio.cdn.ckeditor}/ckeditor.js`), true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n if (isIEBrowser) {\n const editor = CKEDITOR.replace(element);\n editor.on('change', () => onChange(editor.getData()));\n return Promise.resolve(editor);\n }\n else {\n return ClassicEditor.create(element, settings).then(editor => {\n editor.model.document.on('change', () => onChange(editor.data.get()));\n return editor;\n });\n }\n });\n }\n addQuill(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? this.wysiwygDefault.quill : settings;\n settings = lodash_1.default.merge(this.wysiwygDefault.quill, lodash_1.default.get(this.options, 'editors.quill.settings', {}), settings);\n settings = Object.assign(Object.assign({}, settings), { modules: Object.assign({ table: true }, settings.modules) });\n // Lazy load the quill css.\n Formio_1.Formio.requireLibrary(`quill-css-${settings.theme}`, 'Quill', [\n { type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` }\n ], true);\n // Lazy load the quill library.\n return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.min.js`), true)\n .then(() => {\n return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);\n /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ **/\n const txtArea = document.createElement('textarea');\n txtArea.setAttribute('class', 'quill-source-code');\n this.quill.addContainer('ql-custom').appendChild(txtArea);\n const qlSource = element.parentNode.querySelector('.ql-source');\n if (qlSource) {\n this.addEventListener(qlSource, 'click', (event) => {\n event.preventDefault();\n if (txtArea.style.display === 'inherit') {\n this.quill.setContents(this.quill.clipboard.convert({ html: txtArea.value }));\n }\n txtArea.style.display = (txtArea.style.display === 'none') ? 'inherit' : 'none';\n });\n }\n /** END CODEBLOCK **/\n // Make sure to select cursor when they click on the element.\n this.addEventListener(element, 'click', () => this.quill.focus());\n // Allows users to skip toolbar items when tabbing though form\n const elm = document.querySelectorAll('.ql-formats > button');\n for (let i = 0; i < elm.length; i++) {\n elm[i].setAttribute('tabindex', '-1');\n }\n this.quill.on('text-change', () => {\n txtArea.value = this.quill.root.innerHTML;\n onChange(txtArea);\n });\n return this.quill;\n });\n });\n }\n get shouldSanitizeValue() {\n var _a;\n // Sanitize value if sanitizing for thw whole content is turned off\n return (((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitize) !== false);\n }\n addAce(element, settings, onChange) {\n if (!settings || (settings.theme === 'snow')) {\n const mode = settings ? settings.mode : '';\n settings = {};\n if (mode) {\n settings.mode = mode;\n }\n }\n settings = lodash_1.default.merge(this.wysiwygDefault.ace, lodash_1.default.get(this.options, 'editors.ace.settings', {}), settings || {});\n return Formio_1.Formio.requireLibrary('ace', 'ace', lodash_1.default.get(this.options, 'editors.ace.src', `${Formio_1.Formio.cdn.ace}/ace.js`), true)\n .then((editor) => {\n editor = editor.edit(element);\n editor.removeAllListeners('change');\n editor.setOptions(settings);\n editor.getSession().setMode(settings.mode);\n editor.on('change', () => onChange(editor.getValue()));\n if (settings.isUseWorkerDisabled) {\n editor.session.setUseWorker(false);\n }\n return editor;\n });\n }\n get tree() {\n return this.component.tree || false;\n }\n /**\n * The empty value for this component.\n *\n * @return {null}\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n *\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n *\n * @return {*}\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @return {*}\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n *\n * @param value\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n *\n * @param index\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n *\n * @return {*}\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n *\n * @param index\n * @returns {*}\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n *\n * @return {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n *\n * @param index\n * @param value\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && !Array.isArray(value)) {\n value = value ? [value] : [];\n }\n return value;\n }\n /**\n * Update a value of this component.\n *\n * @param flags\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n *\n * @param args\n * @return {boolean}\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n *\n * @param newValue\n * @param oldValue\n * @return {boolean}\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n *\n * @param flags\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n this.triggerChange(flags);\n return true;\n }\n return false;\n }\n /**\n * Perform a calculated value operation.\n *\n * @param data - The global data object.\n *\n * @return {boolean} - If the value changed during calculation.\n */\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set\n if (lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n *\n * @param args\n * @return {boolean}\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n *\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n *\n * @param value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n *\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n return lodash_1.default.map(Validator_1.default.checkComponent(this, data), 'message').join('\\n\\n');\n }\n /**\n * Returns if the component is valid or not.\n *\n * @param data\n * @param dirty\n * @return {boolean}\n */\n isValid(data, dirty) {\n return !this.invalidMessage(data, dirty);\n }\n setComponentValidity(messages, dirty, silentCheck) {\n const hasErrors = !!messages.filter(message => message.level === 'error' && !message.fromServer).length;\n if (messages.length && (!silentCheck || this.error) && (!this.isEmpty(this.defaultValue) || dirty || !this.pristine)) {\n this.setCustomValidity(messages, dirty);\n }\n else if (!silentCheck) {\n this.setCustomValidity('');\n }\n return !hasErrors;\n }\n /**\n * Checks the validity of this component and sets the error message if it is invalid.\n *\n * @param data\n * @param dirty\n * @param row\n * @return {boolean}\n */\n checkComponentValidity(data, dirty, row, options = {}) {\n var _a;\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false, silentCheck = false } = options;\n if (this.shouldSkipValidation(data, dirty, row)) {\n this.setCustomValidity('');\n return async ? Promise.resolve(true) : true;\n }\n const check = Validator_1.default.checkComponent(this, data, row, true, async);\n let validations = check;\n if ((_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.length) {\n validations = check.concat(this.serverErrors);\n }\n return async ?\n validations.then((messages) => this.setComponentValidity(messages, dirty, silentCheck)) :\n this.setComponentValidity(validations, dirty, silentCheck);\n }\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n const isValid = this.checkComponentValidity(data, dirty, row, { silentCheck });\n this.checkModal();\n return isValid;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n return Promise.resolve(this.checkComponentValidity(data, dirty, row, { async: true, silentCheck }));\n }\n /**\n * Check the conditions, calculations, and validity of a single component and triggers an update if\n * something changed.\n *\n * @param data - The root data of the change event.\n * @param flags - The flags from this change event.\n *\n * @return boolean - If component is valid or not.\n */\n checkData(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n if (flags.noValidate && !flags.validateOnInit && !flags.fromIframe) {\n if (flags.fromSubmission && this.rootPristine && this.pristine && this.error && flags.changed) {\n this.checkComponentValidity(data, !!this.options.alwaysDirty, row, true);\n }\n return true;\n }\n let isDirty = false;\n // We need to set dirty if they explicitly set noValidate to false.\n if (this.options.alwaysDirty || flags.dirty) {\n isDirty = true;\n }\n // See if they explicitely set the values with setSubmission.\n if (flags.fromSubmission && this.hasValue(data)) {\n isDirty = true;\n }\n this.setDirty(isDirty);\n if (this.component.validateOn === 'blur' && flags.fromSubmission) {\n return true;\n }\n const isValid = this.checkComponentValidity(data, isDirty, row, flags);\n this.checkModal();\n return isValid;\n }\n checkModal(isValid = true, dirty = false) {\n if (!this.component.modalEdit || !this.componentModal) {\n return;\n }\n if (dirty && !isValid) {\n this.setErrorClasses([this.refs.openModal], dirty, !isValid, !!this.errors.length, this.refs.openModalWrapper);\n }\n else {\n this.clearErrorClasses(this.refs.openModalWrapper);\n }\n }\n get validationValue() {\n return this.dataValue;\n }\n isEmpty(value = this.dataValue) {\n const isEmptyArray = (lodash_1.default.isArray(value) && value.length === 1) ? lodash_1.default.isEqual(value[0], this.emptyValue) : false;\n return value == null || value.length === 0 || lodash_1.default.isEqual(value, this.emptyValue) || isEmptyArray;\n }\n isEqual(valueA, valueB = this.dataValue) {\n return (this.isEmpty(valueA) && this.isEmpty(valueB)) || lodash_1.default.isEqual(valueA, valueB);\n }\n /**\n * Check if a component is eligible for multiple validation\n *\n * @return {boolean}\n */\n validateMultiple() {\n return true;\n }\n get errors() {\n return this.error ? [this.error] : [];\n }\n clearErrorClasses(element = this.element) {\n this.removeClass(element, this.options.componentErrorClass);\n this.removeClass(element, 'alert alert-danger');\n this.removeClass(element, 'has-error');\n this.removeClass(element, 'has-message');\n }\n setInputWidgetErrorClasses(inputRefs, hasErrors) {\n if (!this.isInputComponent || !this.component.widget || !(inputRefs === null || inputRefs === void 0 ? void 0 : inputRefs.length)) {\n return;\n }\n inputRefs.forEach((input) => {\n if ((input === null || input === void 0 ? void 0 : input.widget) && input.widget.setErrorClasses) {\n input.widget.setErrorClasses(hasErrors);\n }\n });\n }\n addFocusBlurEvents(element) {\n this.addEventListener(element, 'focus', () => {\n if (this.root.focusedComponent !== this) {\n if (this.root.pendingBlur) {\n this.root.pendingBlur();\n }\n this.root.focusedComponent = this;\n this.emit('focus', this);\n }\n else if (this.root.focusedComponent === this && this.root.pendingBlur) {\n this.root.pendingBlur.cancel();\n this.root.pendingBlur = null;\n }\n });\n this.addEventListener(element, 'blur', () => {\n this.root.pendingBlur = FormioUtils.delay(() => {\n this.emit('blur', this);\n if (this.component.validateOn === 'blur') {\n this.root.triggerChange({ fromBlur: true }, {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: { fromBlur: true }\n });\n }\n this.root.focusedComponent = null;\n this.root.pendingBlur = null;\n });\n });\n }\n setCustomValidity(messages, dirty, external) {\n const inputRefs = this.isInputComponent ? this.refs.input || [] : null;\n if (typeof messages === 'string' && messages) {\n messages = {\n level: 'error',\n message: messages,\n };\n }\n if (!Array.isArray(messages)) {\n if (messages) {\n messages = [messages];\n }\n else {\n messages = [];\n }\n }\n const hasErrors = !!messages.filter(message => message.level === 'error').length;\n let invalidInputRefs = inputRefs;\n if (this.component.multiple) {\n const inputRefsArray = Array.from(inputRefs);\n inputRefsArray.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), false);\n });\n this.setInputWidgetErrorClasses(inputRefsArray, false);\n invalidInputRefs = inputRefsArray.filter((ref) => {\n var _a;\n return (_a = messages.some) === null || _a === void 0 ? void 0 : _a.call(messages, (msg) => {\n var _a;\n return ((_a = msg === null || msg === void 0 ? void 0 : msg.context) === null || _a === void 0 ? void 0 : _a.input) === ref;\n });\n });\n }\n if (messages.length) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n this.error = {\n component: this.component,\n message: messages[0].message,\n messages,\n external: !!external,\n };\n this.emit('componentError', this.error);\n this.addMessages(messages, dirty, invalidInputRefs);\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, hasErrors, !!messages.length);\n }\n }\n else if (!this.error || (this.error && this.error.external === !!external)) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n if (this.refs.modalMessageContainer) {\n this.empty(this.refs.modalMessageContainer);\n }\n this.error = null;\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, hasErrors, !!messages.length);\n }\n this.clearErrorClasses();\n }\n // if (!this.refs.input) {\n // return;\n // }\n // this.refs.input.forEach(input => {\n // input = this.performInputMapping(input);\n // if (typeof input.setCustomValidity === 'function') {\n // input.setCustomValidity(message, dirty);\n // }\n // });\n }\n /**\n * Determines if the value of this component is hidden from the user as if it is coming from the server, but is\n * protected.\n *\n * @return {boolean|*}\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, dirty, row) {\n const rules = [\n // Force valid if component is read-only\n () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !this.hasInput,\n // Check to see if we are editing and if so, check component persistence.\n () => this.isValueHidden(),\n // Force valid if component is hidden.\n () => !this.visible,\n // Force valid if component is conditionally hidden.\n () => !this.checkCondition(row, data)\n ];\n return rules.some(pred => pred());\n }\n // Maintain reverse compatibility.\n whenReady() {\n console.warn('The whenReady() method has been deprecated. Please use the dataReady property instead.');\n return this.dataReady;\n }\n get dataReady() {\n return Promise.resolve();\n }\n /**\n * Prints out the value of this component as a string value.\n */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @return {boolean}\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n *\n * @param {boolean} disabled\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = typeof index === 'number' && this.refs.input[index]\n ? this.refs.input[index]\n : this.refs.input[this.refs.input.length - 1];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[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 };\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 page.\n const script = document.createElement(elementType);\n for (const attr in attrs) {\n script.setAttribute(attr, attrs[attr]);\n }\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n setTimeout(function checkLibrary() {\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n // check again after 200 ms.\n setTimeout(checkLibrary, 200);\n }\n }, 200);\n }\n }\n }\n return Component.externalLibraries[name].ready;\n};\nComponent.libraryReady = function (name) {\n if (Component.externalLibraries.hasOwnProperty(name) &&\n Component.externalLibraries[name].ready) {\n return Component.externalLibraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/Component.js?");
|
|
4935
|
+
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 __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 __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 }));\n/* globals Quill, ClassicEditor, CKEDITOR */\nconst vanilla_text_mask_1 = __webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\");\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst ismobilejs_1 = __importDefault(__webpack_require__(/*! ismobilejs */ \"./node_modules/ismobilejs/esm/index.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../../Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst Validator_1 = __importDefault(__webpack_require__(/*! ../../../validator/Validator */ \"./lib/cjs/validator/Validator.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Element_1 = __importDefault(__webpack_require__(/*! ../../../Element */ \"./lib/cjs/Element.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst addons_1 = __importDefault(__webpack_require__(/*! ../../../addons */ \"./lib/cjs/addons/index.js\"));\nconst uploadAdapter_1 = __webpack_require__(/*! ../../../providers/storage/uploadAdapter */ \"./lib/cjs/providers/storage/uploadAdapter.js\");\nconst en_1 = __importDefault(__webpack_require__(/*! ../../../translations/en */ \"./lib/cjs/translations/en.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ../../../templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nconst isIEBrowser = FormioUtils.getBrowserInfo().ie;\n/**\n * This is the Component class\n which all elements within the FormioForm derive from.\n */\nclass Component extends Element_1.default {\n static schema(...sources) {\n return lodash_1.default.merge({\n /**\n * Determines if this component provides an input.\n */\n input: true,\n /**\n * The data key for this component (how the data is stored in the database).\n */\n key: '',\n /**\n * The input placeholder for this component.\n */\n placeholder: '',\n /**\n * The input prefix\n */\n prefix: '',\n /**\n * The custom CSS class to provide to this component.\n */\n customClass: '',\n /**\n * The input suffix.\n */\n suffix: '',\n /**\n * If this component should allow an array of values to be captured.\n */\n multiple: false,\n /**\n * The default value of this component.\n */\n defaultValue: null,\n /**\n * If the data of this component should be protected (no GET api requests can see the data)\n */\n protected: false,\n /**\n * Validate if the value of this component should be unique within the form.\n */\n unique: false,\n /**\n * If the value of this component should be persisted within the backend api database.\n */\n persistent: true,\n /**\n * Determines if the component should be within the form, but not visible.\n */\n hidden: false,\n /**\n * If the component should be cleared when hidden.\n */\n clearOnHide: true,\n /**\n * This will refresh this component options when this field changes.\n */\n refreshOn: '',\n /**\n * This will redraw the component when this field changes.\n */\n redrawOn: '',\n /**\n * If this component should be included as a column within a submission table.\n */\n tableView: false,\n /**\n * If this component should be rendering in modal.\n */\n modalEdit: false,\n /**\n * The input label provided to this component.\n */\n label: '',\n dataGridLabel: false,\n labelPosition: 'top',\n description: '',\n errorLabel: '',\n tooltip: '',\n hideLabel: false,\n tabindex: '',\n disabled: false,\n autofocus: false,\n dbIndex: false,\n customDefaultValue: '',\n calculateValue: '',\n calculateServer: false,\n widget: null,\n /**\n * Attributes that will be assigned to the input elements of this component.\n */\n attributes: {},\n /**\n * This will perform the validation on either \"change\" or \"blur\" of the input element.\n */\n validateOn: 'change',\n /**\n * The validation criteria for this component.\n */\n validate: {\n /**\n * If this component is required.\n */\n required: false,\n /**\n * Custom JavaScript validation.\n */\n custom: '',\n /**\n * If the custom validation should remain private (only the backend will see it and execute it).\n */\n customPrivate: false,\n /**\n * If this component should implement a strict date validation if the Calendar widget is implemented.\n */\n strictDateValidation: false,\n multiple: false,\n unique: false\n },\n /**\n * The simple conditional settings for a component.\n */\n conditional: {\n show: null,\n when: null,\n eq: ''\n },\n overlay: {\n style: '',\n left: '',\n top: '',\n width: '',\n height: '',\n },\n allowCalculateOverride: false,\n encrypted: false,\n showCharCount: false,\n showWordCount: false,\n properties: {},\n allowMultipleMasks: false,\n addons: [],\n }, ...sources);\n }\n /**\n * Return the validator as part of the component.\n *\n * @return {ValidationChecker}\n * @constructor\n */\n static get Validator() {\n return Validator_1.default;\n }\n /**\n * Return the simple condition settings as part of the component.\n *\n * @return {Object}\n *\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n *\n * @param schema\n * @return {Array}\n *\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n *\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n *\n * @param {Object} component - The component JSON you wish to initialize.\n * @param {Object} options - The options for this component.\n * @param {Object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * Set the validator instance.\n */\n this.validator = Validator_1.default;\n /**\n * The data path to this specific component instance.\n *\n * @type {string}\n */\n this.path = '';\n /**\n * The Form.io component JSON schema.\n * @type {*}\n */\n this.component = this.mergeSchema(component || {});\n // Add the id to the component.\n this.component.id = this.id;\n this.afterComponentAssign();\n // Save off the original component to be used in logic.\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n /**\n * If the component has been attached\n */\n this.attached = false;\n /**\n * If the component has been rendered\n */\n this.rendered = false;\n /**\n * The data object in which this component resides.\n * @type {*}\n */\n this._data = data || {};\n /**\n * The existing error that this component has.\n * @type {string}\n */\n this.error = '';\n /**\n * Tool tip text after processing\n * @type {string}\n */\n this.tooltip = '';\n /**\n * The row path of this component.\n * @type {number}\n */\n this.row = this.options.row;\n /**\n * Determines if this component is disabled, or not.\n *\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n *\n * @type {Component}\n */\n this.root = this.options.root;\n this.localRoot = this.options.localRoot;\n /**\n * If this input has been input and provided value.\n *\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n *\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n /**\n * The validators that are assigned to this component.\n * @type {[string]}\n */\n this.validators = ['required', 'minLength', 'maxLength', 'minWords', 'maxWords', 'custom', 'pattern', 'json', 'mask'];\n this._path = '';\n // Nested forms don't have parents so we need to pass their path in.\n this._parentPath = this.options.parentPath || '';\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n /**\n * Determines if this component is visible, or not.\n */\n this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;\n this._visible = this._parentVisible && this.conditionallyVisible(null, data);\n this._parentDisabled = false;\n /**\n * Used to trigger a new change in this component.\n * @type {function} - Call to trigger a change in this component.\n */\n let changes = [];\n let lastChanged = null;\n let triggerArgs = [];\n const _triggerChange = lodash_1.default.debounce((...args) => {\n if (this.root) {\n this.root.changing = false;\n }\n triggerArgs = [];\n if (!args[1] && lastChanged) {\n // Set the changed component if one isn't provided.\n args[1] = lastChanged;\n }\n if (lodash_1.default.isEmpty(args[0]) && lastChanged) {\n // Set the flags if it is empty and lastChanged exists.\n args[0] = lastChanged.flags;\n }\n lastChanged = null;\n args[3] = changes;\n const retVal = this.onChange(...args);\n changes = [];\n return retVal;\n }, 100);\n this.triggerChange = (...args) => {\n if (args[1]) {\n // Make sure that during the debounce that we always track lastChanged component, even if they\n // don't provide one later.\n lastChanged = args[1];\n changes.push(lastChanged);\n }\n if (this.root) {\n this.root.changing = true;\n }\n if (args.length) {\n triggerArgs = args;\n }\n return _triggerChange(...triggerArgs);\n };\n /**\n * Used to trigger a redraw event within this component.\n *\n * @type {Function}\n */\n this.triggerRedraw = lodash_1.default.debounce(this.redraw.bind(this), 100);\n /**\n * list of attached tooltips\n * @type {Array}\n */\n this.tooltips = [];\n /**\n * List of attached addons\n * @type {Array}\n */\n this.addons = [];\n // To force this component to be invalid.\n this.invalid = false;\n if (this.component) {\n this.type = this.component.type;\n if (this.allowData && this.key) {\n this.options.name += `[${this.key}]`;\n // If component is visible or not set to clear on hide, set the default value.\n if (this.visible || !this.component.clearOnHide) {\n if (!this.hasValue()) {\n if (this.shouldAddDefaultValue) {\n this.dataValue = this.defaultValue;\n }\n }\n else {\n // Ensure the dataValue is set.\n /* eslint-disable no-self-assign */\n this.dataValue = this.dataValue;\n /* eslint-enable no-self-assign */\n }\n }\n }\n /**\n * The element information for creating the input element.\n * @type {*}\n */\n this.info = this.elementInfo();\n }\n // Allow anyone to hook into the component creation.\n this.hook('component');\n if (!this.options.skipInit) {\n this.init();\n }\n }\n /* eslint-enable max-statements */\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n }\n mergeSchema(component = {}) {\n return lodash_1.default.defaultsDeep(component, this.defaultSchema);\n }\n // Allow componets to notify when ready.\n get ready() {\n return Promise.resolve(this);\n }\n get isPDFReadOnlyMode() {\n return this.parent &&\n this.parent.form &&\n (this.parent.form.display === 'pdf') &&\n this.options.readOnly;\n }\n get labelInfo() {\n const label = {};\n label.hidden = this.labelIsHidden();\n label.className = '';\n label.labelPosition = this.component.labelPosition;\n label.tooltipClass = `${this.iconClass('question-sign')} text-muted`;\n const isPDFReadOnlyMode = this.isPDFReadOnlyMode;\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required) && !isPDFReadOnlyMode) {\n label.className += ' field-required';\n }\n if (label.hidden) {\n label.className += ' control-label--hidden';\n }\n if (this.info.attr.id) {\n label.for = this.info.attr.id;\n }\n return label;\n }\n init() {\n var _a;\n this.disabled = this.shouldDisabled;\n this._visible = this.conditionallyVisible(null, null);\n if ((_a = this.component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n this.component.addons.forEach((addon) => this.createAddon(addon));\n }\n }\n afterComponentAssign() {\n //implement in extended classes\n }\n createAddon(addonConfiguration) {\n var _a;\n const name = addonConfiguration.name;\n if (!name) {\n return;\n }\n const settings = ((_a = addonConfiguration.settings) === null || _a === void 0 ? void 0 : _a.data) || {};\n const Addon = addons_1.default[name.value];\n let addon = null;\n if (Addon) {\n const supportedComponents = Addon.info.supportedComponents;\n const supportsThisComponentType = !(supportedComponents === null || supportedComponents === void 0 ? void 0 : supportedComponents.length) ||\n supportedComponents.indexOf(this.component.type) !== -1;\n if (supportsThisComponentType) {\n addon = new Addon(settings, this);\n this.addons.push(addon);\n }\n else {\n console.warn(`Addon ${name.label} does not support component of type ${this.component.type}.`);\n }\n }\n return addon;\n }\n teardown() {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n delete this._currentForm;\n delete this.parent;\n delete this.root;\n delete this.triggerChange;\n delete this.triggerRedraw;\n if (this.options) {\n delete this.options.root;\n delete this.options.parent;\n delete this.options.i18next;\n }\n super.teardown();\n }\n destroy(all = false) {\n super.destroy(all);\n this.detach();\n this.addons.forEach((addon) => addon.destroy());\n if (all) {\n this.teardown();\n }\n }\n get shouldDisabled() {\n return this.options.readOnly || this.component.disabled || (this.options.hasOwnProperty('disabled') && this.options.disabled[this.key]);\n }\n get isInputComponent() {\n return !this.component.hasOwnProperty('input') || this.component.input;\n }\n get allowData() {\n return this.hasInput;\n }\n get hasInput() {\n return this.isInputComponent || (this.refs.input && this.refs.input.length);\n }\n get defaultSchema() {\n return Component.schema();\n }\n get key() {\n return lodash_1.default.get(this.component, 'key', '');\n }\n set parentVisible(value) {\n this._parentVisible = value;\n }\n get parentVisible() {\n return this._parentVisible;\n }\n set parentDisabled(value) {\n this._parentDisabled = value;\n }\n get parentDisabled() {\n return this._parentDisabled;\n }\n shouldForceVisibility(component, visibility) {\n if (!this.options[visibility]) {\n return false;\n }\n if (!component) {\n component = this.component;\n }\n if (lodash_1.default.isArray(this.options[visibility])) {\n return this.options[visibility].includes(component.key);\n }\n return this.options[visibility][component.key];\n }\n shouldForceHide(component) {\n return this.shouldForceVisibility(component, 'hide');\n }\n shouldForceShow(component) {\n return this.shouldForceVisibility(component, 'show');\n }\n /**\n *\n * @param value {boolean}\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n *\n * @returns {boolean}\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n *\n * @param schema\n * @param defaultSchema\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = this.rootValue;\n params.row = this.data;\n params.component = this.component;\n return super.t(text, params, ...args);\n }\n labelIsHidden() {\n return !this.component.label ||\n ((!this.isInDataGrid && this.component.hideLabel) ||\n (this.isInDataGrid && !this.component.dataGridLabel) ||\n this.options.floatingLabels ||\n this.options.inputsOnly) && !this.builderMode;\n }\n transform(type, value) {\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n return frameworkTemplates.hasOwnProperty('transform')\n ? frameworkTemplates.transform(type, value, this)\n : (type, value) => value;\n }\n getTemplate(names, modes) {\n modes = Array.isArray(modes) ? modes : [modes];\n names = Array.isArray(names) ? names : [names];\n if (!modes.includes('form')) {\n modes.push('form');\n }\n let result = null;\n if (this.options.templates) {\n result = this.checkTemplate(this.options.templates, names, modes);\n if (result) {\n return result;\n }\n }\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n result = this.checkTemplate(frameworkTemplates, names, modes);\n if (result) {\n return result;\n }\n // Default back to bootstrap if not defined.\n const name = names[names.length - 1];\n const templatesByName = Templates_1.default.defaultTemplates[name];\n if (!templatesByName) {\n return `Unknown template: ${name}`;\n }\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return templateByMode;\n }\n return templatesByName.form;\n }\n checkTemplate(templates, names, modes) {\n for (const name of names) {\n const templatesByName = templates[name];\n if (templatesByName) {\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return templateByMode;\n }\n }\n }\n return null;\n }\n checkTemplateMode(templatesByName, modes) {\n for (const mode of modes) {\n const templateByMode = templatesByName[mode];\n if (templateByMode) {\n return templateByMode;\n }\n }\n return null;\n }\n getFormattedAttribute(attr) {\n return attr ? this.t(attr, { _userInput: true }).replace(/\"/g, '"') : '';\n }\n getFormattedTooltip(tooltipValue) {\n const tooltip = this.interpolate(tooltipValue || '').replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n return this.getFormattedAttribute(tooltip);\n }\n isHtmlRenderMode() {\n return this.options.renderMode === 'html';\n }\n renderTemplate(name, data = {}, modeOption) {\n // Need to make this fall back to form if renderMode is not found similar to how we search templates.\n const mode = modeOption || this.options.renderMode || 'form';\n data.component = this.component;\n data.self = this;\n data.options = this.options;\n data.readOnly = this.options.readOnly;\n data.iconClass = this.iconClass.bind(this);\n data.size = this.size.bind(this);\n data.t = this.t.bind(this);\n data.transform = this.transform.bind(this);\n data.id = data.id || this.id;\n data.key = data.key || this.key;\n data.value = data.value || this.dataValue;\n data.disabled = this.disabled;\n data.builder = this.builderMode;\n data.render = (...args) => {\n console.warn(`Form.io 'render' template function is deprecated.\n If you need to render template (template A) inside of another template (template B),\n pass pre-compiled template A (use this.renderTemplate('template_A_name') as template context variable for template B`);\n return this.renderTemplate(...args);\n };\n data.label = data.labelInfo || this.labelInfo;\n data.tooltip = this.getFormattedTooltip(this.component.tooltip);\n // Allow more specific template names\n const names = [\n `${name}-${this.component.type}-${this.key}`,\n `${name}-${this.component.type}`,\n `${name}-${this.key}`,\n `${name}`,\n ];\n // Allow template alters.\n return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(this.getTemplate(names, mode), data), data, mode);\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize, options) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n *\n * @param template\n * @param data\n * @param actions\n *\n * @return {HTMLElement|String} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n performInputMapping(input) {\n return input;\n }\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components\n * to perform special functions.\n *\n * @return {*}\n */\n beforePage() {\n return Promise.resolve(true);\n }\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components\n * to perform special async functions.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n *\n * @return {*}\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n get timezone() {\n return this.getTimezone(this.component);\n }\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n loadRefs(element, refs) {\n for (const ref in refs) {\n const refType = refs[ref];\n const isString = typeof refType === 'string';\n const selector = isString && refType.includes('scope') ? `:scope > [ref=\"${ref}\"]` : `[ref=\"${ref}\"]`;\n if (isString && refType.startsWith('single')) {\n this.refs[ref] = element.querySelector(selector);\n }\n else {\n this.refs[ref] = element.querySelectorAll(selector);\n }\n }\n }\n setOpenModalElement(template) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n const message = this.error ? {\n level: 'error',\n message: this.error.message,\n } : '';\n let modalLabel;\n if (this.hasInput && ((_a = this.component.validate) === null || _a === void 0 ? void 0 : _a.required) && !this.isPDFReadOnlyMode) {\n modalLabel = { className: 'field-required' };\n }\n return this.renderTemplate('modalPreview', {\n previewText: this.getValueAsString(dataValue, { modalPreview: true }) || this.t('Click to set value'),\n messages: message && this.renderTemplate('message', message),\n labelInfo: modalLabel,\n });\n }\n build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue);\n }\n attach(element) {\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n const openModalTemplate = this.componentModal && modalShouldBeOpened\n ? this.componentModal.openModalTemplate\n : null;\n this.componentModal = this.createComponentModal(element, modalShouldBeOpened, currentValue);\n this.setOpenModalElement(openModalTemplate);\n }\n this.attached = true;\n this.setElement(element);\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n // First iterate through each ref and delete the component so there are no dangling component references.\n lodash_1.default.each(this.refs, (ref) => {\n if (typeof ref === NodeList) {\n ref.forEach((elem) => {\n delete elem.component;\n });\n }\n else if (ref) {\n delete ref.component;\n }\n });\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n *\n * @param value\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n *\n * @param component\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n setElement(element) {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n this.element = element;\n }\n createViewOnlyElement() {\n this.setElement(this.ce('dl', {\n id: this.id\n }));\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n *\n * @param value\n * @return {*}\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * @param {*} data\n * @param {boolean} [forceUseValue=false] - if true, return 'value' property of the data\n * @return {*}\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @return {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement}\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n *\n * @param pristine {boolean} - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n get isPristine() {\n return this.pristine;\n }\n setDirty(dirty) {\n this.dirty = dirty;\n }\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n /**\n * Returns the error label for this component.\n * @return {*}\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param type\n * @return {*}\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.setElement(parent.children[index]);\n return this.attach(this.element);\n }\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n *\n * @return {null}\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n *\n * @param data\n * @return {boolean}\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n *\n * @param row - The row contextual data.\n * @param data - The global data object.\n * @return {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param args\n * @return {boolean}\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n *\n * @param data\n */\n fieldLogic(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n *\n * @param message\n * @param dirty\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n if (message.message && typeof message.message === 'string') {\n message.message = message.message.replaceAll('<', '<').replaceAll('>', '>');\n }\n return this.renderTemplate('message', message);\n }).join(''));\n }\n }\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n // do not set error classes for hidden components\n if (!this.visible) {\n return;\n }\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root) {\n this.root.triggerChange(...args);\n }\n }\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur' && !this.errors.length) {\n flags.noValidate = true;\n }\n if (this.component.onChange) {\n this.evaluate(this.component.onChange, {\n flags\n });\n }\n // Set the changed variable.\n const changed = {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: flags\n };\n // Emit the change.\n this.emit('componentChange', changed);\n // Do not propogate the modified flag.\n let modified = false;\n if (flags.modified) {\n modified = true;\n delete flags.modified;\n }\n // Bubble this change up to the top.\n if (!fromRoot) {\n this.triggerRootChange(flags, changed, modified);\n }\n return changed;\n }\n get wysiwygDefault() {\n return {\n quill: {\n theme: 'snow',\n placeholder: this.t(this.component.placeholder, { _userInput: true }),\n modules: {\n toolbar: [\n [{ 'size': ['small', false, 'large', 'huge'] }],\n [{ 'header': [1, 2, 3, 4, 5, 6, false] }],\n [{ 'font': [] }],\n ['bold', 'italic', 'underline', 'strike', { 'script': 'sub' }, { 'script': 'super' }, 'clean'],\n [{ 'color': [] }, { 'background': [] }],\n [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }, { 'align': [] }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video', 'formula', 'source']\n ]\n }\n },\n ace: {\n theme: 'ace/theme/xcode',\n maxLines: 12,\n minLines: 12,\n tabSize: 2,\n mode: 'ace/mode/javascript',\n placeholder: this.t(this.component.placeholder, { _userInput: true })\n },\n ckeditor: {\n image: {\n toolbar: [\n 'imageTextAlternative',\n '|',\n 'imageStyle:full',\n 'imageStyle:alignLeft',\n 'imageStyle:alignCenter',\n 'imageStyle:alignRight'\n ],\n styles: [\n 'full',\n 'alignLeft',\n 'alignCenter',\n 'alignRight'\n ]\n },\n extraPlugins: []\n },\n default: {}\n };\n }\n addCKE(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? {} : settings;\n settings.base64Upload = this.component.isUploadEnabled ? false : true;\n settings.mediaEmbed = { previewsInData: true };\n settings = lodash_1.default.merge(this.wysiwygDefault.ckeditor, lodash_1.default.get(this.options, 'editors.ckeditor.settings', {}), settings);\n if (this.component.isUploadEnabled) {\n settings.extraPlugins.push((0, uploadAdapter_1.getFormioUploadAdapterPlugin)(this.fileService, this));\n }\n return Formio_1.Formio.requireLibrary('ckeditor', isIEBrowser ? 'CKEDITOR' : 'ClassicEditor', lodash_1.default.get(this.options, 'editors.ckeditor.src', `${Formio_1.Formio.cdn.ckeditor}/ckeditor.js`), true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n if (isIEBrowser) {\n const editor = CKEDITOR.replace(element);\n editor.on('change', () => onChange(editor.getData()));\n return Promise.resolve(editor);\n }\n else {\n return ClassicEditor.create(element, settings).then(editor => {\n editor.model.document.on('change', () => onChange(editor.data.get()));\n return editor;\n });\n }\n });\n }\n addQuill(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? this.wysiwygDefault.quill : settings;\n settings = lodash_1.default.merge(this.wysiwygDefault.quill, lodash_1.default.get(this.options, 'editors.quill.settings', {}), settings);\n settings = Object.assign(Object.assign({}, settings), { modules: Object.assign({ table: true }, settings.modules) });\n // Lazy load the quill css.\n Formio_1.Formio.requireLibrary(`quill-css-${settings.theme}`, 'Quill', [\n { type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` }\n ], true);\n // Lazy load the quill library.\n return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.min.js`), true)\n .then(() => {\n return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);\n /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ **/\n const txtArea = document.createElement('textarea');\n txtArea.setAttribute('class', 'quill-source-code');\n this.quill.addContainer('ql-custom').appendChild(txtArea);\n const qlSource = element.parentNode.querySelector('.ql-source');\n if (qlSource) {\n this.addEventListener(qlSource, 'click', (event) => {\n event.preventDefault();\n if (txtArea.style.display === 'inherit') {\n this.quill.setContents(this.quill.clipboard.convert({ html: txtArea.value }));\n }\n txtArea.style.display = (txtArea.style.display === 'none') ? 'inherit' : 'none';\n });\n }\n /** END CODEBLOCK **/\n // Make sure to select cursor when they click on the element.\n this.addEventListener(element, 'click', () => this.quill.focus());\n // Allows users to skip toolbar items when tabbing though form\n const elm = document.querySelectorAll('.ql-formats > button');\n for (let i = 0; i < elm.length; i++) {\n elm[i].setAttribute('tabindex', '-1');\n }\n this.quill.on('text-change', () => {\n txtArea.value = this.quill.root.innerHTML;\n onChange(txtArea);\n });\n return this.quill;\n });\n });\n }\n get shouldSanitizeValue() {\n var _a;\n // Sanitize value if sanitizing for thw whole content is turned off\n return (((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitize) !== false);\n }\n addAce(element, settings, onChange) {\n if (!settings || (settings.theme === 'snow')) {\n const mode = settings ? settings.mode : '';\n settings = {};\n if (mode) {\n settings.mode = mode;\n }\n }\n settings = lodash_1.default.merge(this.wysiwygDefault.ace, lodash_1.default.get(this.options, 'editors.ace.settings', {}), settings || {});\n return Formio_1.Formio.requireLibrary('ace', 'ace', lodash_1.default.get(this.options, 'editors.ace.src', `${Formio_1.Formio.cdn.ace}/ace.js`), true)\n .then((editor) => {\n editor = editor.edit(element);\n editor.removeAllListeners('change');\n editor.setOptions(settings);\n editor.getSession().setMode(settings.mode);\n editor.on('change', () => onChange(editor.getValue()));\n if (settings.isUseWorkerDisabled) {\n editor.session.setUseWorker(false);\n }\n return editor;\n });\n }\n get tree() {\n return this.component.tree || false;\n }\n /**\n * The empty value for this component.\n *\n * @return {null}\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n *\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n *\n * @return {*}\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @return {*}\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n *\n * @param value\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n *\n * @param index\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n *\n * @return {*}\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n *\n * @param index\n * @returns {*}\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n *\n * @return {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n *\n * @param index\n * @param value\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && !Array.isArray(value)) {\n value = value ? [value] : [];\n }\n return value;\n }\n /**\n * Update a value of this component.\n *\n * @param flags\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n *\n * @param args\n * @return {boolean}\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n *\n * @param newValue\n * @param oldValue\n * @return {boolean}\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n *\n * @param flags\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n this.triggerChange(flags);\n return true;\n }\n return false;\n }\n /**\n * Perform a calculated value operation.\n *\n * @param data - The global data object.\n *\n * @return {boolean} - If the value changed during calculation.\n */\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set or in builder mode\n if (this.builderMode || lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n this.calculatedValue = null;\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n *\n * @param args\n * @return {boolean}\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n *\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n *\n * @param value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n *\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n return lodash_1.default.map(Validator_1.default.checkComponent(this, data), 'message').join('\\n\\n');\n }\n /**\n * Returns if the component is valid or not.\n *\n * @param data\n * @param dirty\n * @return {boolean}\n */\n isValid(data, dirty) {\n return !this.invalidMessage(data, dirty);\n }\n setComponentValidity(messages, dirty, silentCheck) {\n const hasErrors = !!messages.filter(message => message.level === 'error' && !message.fromServer).length;\n if (messages.length && (!silentCheck || this.error) && (!this.isEmpty(this.defaultValue) || dirty || !this.pristine)) {\n this.setCustomValidity(messages, dirty);\n }\n else if (!silentCheck) {\n this.setCustomValidity('');\n }\n return !hasErrors;\n }\n /**\n * Checks the validity of this component and sets the error message if it is invalid.\n *\n * @param data\n * @param dirty\n * @param row\n * @return {boolean}\n */\n checkComponentValidity(data, dirty, row, options = {}) {\n var _a;\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false, silentCheck = false } = options;\n if (this.shouldSkipValidation(data, dirty, row)) {\n this.setCustomValidity('');\n return async ? Promise.resolve(true) : true;\n }\n const check = Validator_1.default.checkComponent(this, data, row, true, async);\n let validations = check;\n if ((_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.length) {\n validations = check.concat(this.serverErrors);\n }\n return async ?\n validations.then((messages) => this.setComponentValidity(messages, dirty, silentCheck)) :\n this.setComponentValidity(validations, dirty, silentCheck);\n }\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n const isValid = this.checkComponentValidity(data, dirty, row, { silentCheck });\n this.checkModal();\n return isValid;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n return Promise.resolve(this.checkComponentValidity(data, dirty, row, { async: true, silentCheck }));\n }\n /**\n * Check the conditions, calculations, and validity of a single component and triggers an update if\n * something changed.\n *\n * @param data - The root data of the change event.\n * @param flags - The flags from this change event.\n *\n * @return boolean - If component is valid or not.\n */\n checkData(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n if (flags.noValidate && !flags.validateOnInit && !flags.fromIframe) {\n if (flags.fromSubmission && this.rootPristine && this.pristine && this.error && flags.changed) {\n this.checkComponentValidity(data, !!this.options.alwaysDirty, row, true);\n }\n return true;\n }\n let isDirty = false;\n // We need to set dirty if they explicitly set noValidate to false.\n if (this.options.alwaysDirty || flags.dirty) {\n isDirty = true;\n }\n // See if they explicitely set the values with setSubmission.\n if (flags.fromSubmission && this.hasValue(data)) {\n isDirty = true;\n }\n this.setDirty(isDirty);\n if (this.component.validateOn === 'blur' && flags.fromSubmission) {\n return true;\n }\n const isValid = this.checkComponentValidity(data, isDirty, row, flags);\n this.checkModal();\n return isValid;\n }\n checkModal(isValid = true, dirty = false) {\n if (!this.component.modalEdit || !this.componentModal) {\n return;\n }\n if (dirty && !isValid) {\n this.setErrorClasses([this.refs.openModal], dirty, !isValid, !!this.errors.length, this.refs.openModalWrapper);\n }\n else {\n this.clearErrorClasses(this.refs.openModalWrapper);\n }\n }\n get validationValue() {\n return this.dataValue;\n }\n isEmpty(value = this.dataValue) {\n const isEmptyArray = (lodash_1.default.isArray(value) && value.length === 1) ? lodash_1.default.isEqual(value[0], this.emptyValue) : false;\n return value == null || value.length === 0 || lodash_1.default.isEqual(value, this.emptyValue) || isEmptyArray;\n }\n isEqual(valueA, valueB = this.dataValue) {\n return (this.isEmpty(valueA) && this.isEmpty(valueB)) || lodash_1.default.isEqual(valueA, valueB);\n }\n /**\n * Check if a component is eligible for multiple validation\n *\n * @return {boolean}\n */\n validateMultiple() {\n return true;\n }\n get errors() {\n return this.error ? [this.error] : [];\n }\n clearErrorClasses(element = this.element) {\n this.removeClass(element, this.options.componentErrorClass);\n this.removeClass(element, 'alert alert-danger');\n this.removeClass(element, 'has-error');\n this.removeClass(element, 'has-message');\n }\n setInputWidgetErrorClasses(inputRefs, hasErrors) {\n if (!this.isInputComponent || !this.component.widget || !(inputRefs === null || inputRefs === void 0 ? void 0 : inputRefs.length)) {\n return;\n }\n inputRefs.forEach((input) => {\n if ((input === null || input === void 0 ? void 0 : input.widget) && input.widget.setErrorClasses) {\n input.widget.setErrorClasses(hasErrors);\n }\n });\n }\n addFocusBlurEvents(element) {\n this.addEventListener(element, 'focus', () => {\n if (this.root.focusedComponent !== this) {\n if (this.root.pendingBlur) {\n this.root.pendingBlur();\n }\n this.root.focusedComponent = this;\n this.emit('focus', this);\n }\n else if (this.root.focusedComponent === this && this.root.pendingBlur) {\n this.root.pendingBlur.cancel();\n this.root.pendingBlur = null;\n }\n });\n this.addEventListener(element, 'blur', () => {\n this.root.pendingBlur = FormioUtils.delay(() => {\n this.emit('blur', this);\n if (this.component.validateOn === 'blur') {\n this.root.triggerChange({ fromBlur: true }, {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: { fromBlur: true }\n });\n }\n this.root.focusedComponent = null;\n this.root.pendingBlur = null;\n });\n });\n }\n setCustomValidity(messages, dirty, external) {\n const inputRefs = this.isInputComponent ? this.refs.input || [] : null;\n if (typeof messages === 'string' && messages) {\n messages = {\n level: 'error',\n message: messages,\n };\n }\n if (!Array.isArray(messages)) {\n if (messages) {\n messages = [messages];\n }\n else {\n messages = [];\n }\n }\n const hasErrors = !!messages.filter(message => message.level === 'error').length;\n let invalidInputRefs = inputRefs;\n if (this.component.multiple) {\n const inputRefsArray = Array.from(inputRefs);\n inputRefsArray.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), false);\n });\n this.setInputWidgetErrorClasses(inputRefsArray, false);\n invalidInputRefs = inputRefsArray.filter((ref) => {\n var _a;\n return (_a = messages.some) === null || _a === void 0 ? void 0 : _a.call(messages, (msg) => {\n var _a;\n return ((_a = msg === null || msg === void 0 ? void 0 : msg.context) === null || _a === void 0 ? void 0 : _a.input) === ref;\n });\n });\n }\n if (messages.length) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n this.error = {\n component: this.component,\n message: messages[0].message,\n messages,\n external: !!external,\n };\n this.emit('componentError', this.error);\n this.addMessages(messages, dirty, invalidInputRefs);\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, hasErrors, !!messages.length);\n }\n }\n else if (!this.error || (this.error && this.error.external === !!external)) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n if (this.refs.modalMessageContainer) {\n this.empty(this.refs.modalMessageContainer);\n }\n this.error = null;\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, hasErrors, !!messages.length);\n }\n this.clearErrorClasses();\n }\n // if (!this.refs.input) {\n // return;\n // }\n // this.refs.input.forEach(input => {\n // input = this.performInputMapping(input);\n // if (typeof input.setCustomValidity === 'function') {\n // input.setCustomValidity(message, dirty);\n // }\n // });\n }\n /**\n * Determines if the value of this component is hidden from the user as if it is coming from the server, but is\n * protected.\n *\n * @return {boolean|*}\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, dirty, row) {\n const { validateWhenHidden = false } = this.component || {};\n const rules = [\n // Force valid if component is read-only\n () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !this.hasInput,\n // Check to see if we are editing and if so, check component persistence.\n () => this.isValueHidden(),\n // Force valid if component is hidden.\n () => !this.visible && !validateWhenHidden,\n // Force valid if component is conditionally hidden.\n () => !this.checkCondition(row, data) && !validateWhenHidden\n ];\n return rules.some(pred => pred());\n }\n // Maintain reverse compatibility.\n whenReady() {\n console.warn('The whenReady() method has been deprecated. Please use the dataReady property instead.');\n return this.dataReady;\n }\n get dataReady() {\n return Promise.resolve();\n }\n /**\n * Prints out the value of this component as a string value.\n */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @return {boolean}\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n *\n * @param {boolean} disabled\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = typeof index === 'number' && this.refs.input[index]\n ? this.refs.input[index]\n : this.refs.input[this.refs.input.length - 1];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[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 };\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 page.\n const script = document.createElement(elementType);\n for (const attr in attrs) {\n script.setAttribute(attr, attrs[attr]);\n }\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n setTimeout(function checkLibrary() {\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n // check again after 200 ms.\n setTimeout(checkLibrary, 200);\n }\n }, 200);\n }\n }\n }\n return Component.externalLibraries[name].ready;\n};\nComponent.libraryReady = function (name) {\n if (Component.externalLibraries.hasOwnProperty(name) &&\n Component.externalLibraries[name].ready) {\n return Component.externalLibraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/Component.js?");
|
|
4936
4936
|
|
|
4937
4937
|
/***/ }),
|
|
4938
4938
|
|
|
@@ -5009,7 +5009,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5009
5009
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5010
5010
|
|
|
5011
5011
|
"use strict";
|
|
5012
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __importDefault(__webpack_require__(/*! ./utils */ \"./lib/cjs/components/_classes/component/editForm/utils.js\"));\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ../../../../utils/Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\n/* eslint-disable quotes, max-len */\nexports[\"default\"] = [\n {\n weight: 10,\n type: 'checkbox',\n label: 'Required',\n tooltip: 'A required field must be filled in before the form can be submitted.',\n key: 'validate.required',\n input: true\n },\n {\n weight: 100,\n type: 'checkbox',\n label: 'Unique',\n tooltip: 'Makes sure the data submitted for this field is unique, and has not been submitted before.',\n key: 'unique',\n input: true\n },\n {\n weight: 0,\n type: 'select',\n key: 'validateOn',\n defaultValue: 'change',\n input: true,\n label: 'Validate On',\n tooltip: 'Determines when this component should trigger front-end validation.',\n dataSrc: 'values',\n data: {\n values: [\n { label: 'Change', value: 'change' },\n { label: 'Blur', value: 'blur' }\n ]\n }\n },\n {\n weight: 190,\n type: 'textfield',\n input: true,\n key: 'errorLabel',\n label: 'Error Label',\n placeholder: 'Error Label',\n tooltip: 'The label for this field when an error occurs.'\n },\n {\n weight: 200,\n key: 'validate.customMessage',\n label: 'Custom Error Message',\n placeholder: 'Custom Error Message',\n type: 'textfield',\n tooltip: 'Error message displayed if any error occurred.',\n input: true\n },\n {\n type: 'panel',\n title: 'Custom Validation',\n collapsible: true,\n collapsed: true,\n style: { 'margin-bottom': '10px' },\n key: 'custom-validation-js',\n weight: 300,\n customConditional() {\n return !Evaluator_1.default.noeval || Evaluator_1.default.protectedEval;\n },\n components: [\n utils_1.default.logicVariablesTable('<tr><th>input</th><td>The value that was input into this component</td></tr>'),\n {\n type: 'textarea',\n key: 'validate.custom',\n rows: 5,\n editor: 'ace',\n hideLabel: true,\n as: 'javascript',\n input: true\n },\n {\n type: 'htmlelement',\n tag: 'div',\n content: `\n <small>\n <p>Enter custom validation code.</p>\n <p>You must assign the <strong>valid</strong> variable as either <strong>true</strong> or an error message if validation fails.</p>\n <h5>Example:</h5>\n <pre>valid = (input === 'Joe') ? true : 'Your name must be \"Joe\"';</pre>\n </small>`\n },\n {\n type: 'well',\n components: [\n {\n weight: 100,\n type: 'checkbox',\n label: 'Secret Validation',\n tooltip: 'Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.',\n description: 'Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.',\n key: 'validate.customPrivate',\n input: true\n }\n ]\n }\n ]\n },\n {\n type: 'panel',\n title: 'JSONLogic Validation',\n collapsible: true,\n collapsed: true,\n key: 'json-validation-json',\n weight: 400,\n components: [\n {\n type: 'htmlelement',\n tag: 'div',\n /* eslint-disable prefer-template */\n content: '<p>Execute custom logic using <a href=\"http://jsonlogic.com/\" target=\"_blank\" rel=\"noopener noreferrer\">JSONLogic</a>.</p>' +\n '<h5>Example:</h5>' +\n '<pre>' + JSON.stringify({\n \"if\": [\n { \"===\": [{ \"var\": \"input\" }, \"Bob\"] },\n true,\n \"Your name must be 'Bob'!\"\n ]\n }, null, 2) + '</pre>'\n /* eslint-enable prefer-template */\n },\n {\n type: 'textarea',\n key: 'validate.json',\n hideLabel: true,\n rows: 5,\n editor: 'ace',\n as: 'json',\n input: true\n }\n ]\n },\n {\n type: 'panel',\n title: 'Custom Errors',\n collapsible: true,\n collapsed: true,\n key: 'errors',\n weight: 400,\n components: [\n {\n type: 'textarea',\n key: 'errors',\n hideLabel: true,\n rows: 5,\n editor: 'ace',\n as: 'json',\n input: true\n },\n {\n type: 'htmlelement',\n tag: 'div',\n content: `\n <p>This allows you to set different custom error messages for different errors\n (in contrast to “Custom Error Message”, which only allows you to set one\n error message for all errors). E.g.</p>\n\n<pre>{\n \"required\": \"{<span/>{ field }} is required. Try again.\",\n \"maxLength\": \"{<span/>{ field }} is too long. Try again.\"\n}</pre>\n\n <p>You can set the following keys (among others):</p>\n <ul>\n <li>r<span/>equired</li>\n <li>m<span/>in</li>\n <li>m<span/>ax</li>\n <li>m<span/>inLength</li>\n <li>m<span/>axLength</li>\n <li>m<span/>inWords</li>\n <li>m<span/>axWords</li>\n <li>i<span/>nvalid_email</li>\n <li>i<span/>nvalid_date</li>\n <li>i<span/>nvalid_day</li>\n <li>i<span/>nvalid_regex</li>\n <li>m<span/>ask</li>\n <li>p<span/>attern</li>\n <li>c<span/>ustom</li>\n </ul>\n\n <p>Depending on the error message some of the following template variables can be used in the script:</p>\n <ul>\n <li><code>{<span/>{ f<span/>ield }}</code> is replaced with the label of the field.</li>\n <li><code>{<span/>{ m<span/>in }}</code></li>\n <li><code>{<span/>{ m<span/>ax }}</code></li>\n <li><code>{<span/>{ l<span/>ength }}</code></li>\n <li><code>{<span/>{ p<span/>attern }}</code></li>\n <li><code>{<span/>{ m<span/>inDate }}</code></li>\n <li><code>{<span/>{ m<span/>axDate }}</code></li>\n <li><code>{<span/>{ m<span/>inYear }}</code></li>\n <li><code>{<span/>{ m<span/>axYear }}</code></li>\n <li><code>{<span/>{ r<span/>egex }}</code></li>\n </ul>\n `\n }\n ]\n }\n];\n/* eslint-enable quotes, max-len */\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/editForm/Component.edit.validation.js?");
|
|
5012
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __importDefault(__webpack_require__(/*! ./utils */ \"./lib/cjs/components/_classes/component/editForm/utils.js\"));\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ../../../../utils/Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\n/* eslint-disable quotes, max-len */\nexports[\"default\"] = [\n {\n weight: 10,\n type: 'checkbox',\n label: 'Required',\n tooltip: 'A required field must be filled in before the form can be submitted.',\n key: 'validate.required',\n input: true\n },\n {\n weight: 100,\n type: 'checkbox',\n label: 'Unique',\n tooltip: 'Makes sure the data submitted for this field is unique, and has not been submitted before.',\n key: 'unique',\n input: true\n },\n {\n weight: 100,\n type: 'checkbox',\n label: 'Validate When Hidden',\n tooltip: 'Validates the component when it is hidden/conditionally hidden. Vaildation errors are displayed in the error alert on the form submission.',\n key: 'validateWhenHidden',\n input: true\n },\n {\n weight: 0,\n type: 'select',\n key: 'validateOn',\n defaultValue: 'change',\n input: true,\n label: 'Validate On',\n tooltip: 'Determines when this component should trigger front-end validation.',\n dataSrc: 'values',\n data: {\n values: [\n { label: 'Change', value: 'change' },\n { label: 'Blur', value: 'blur' }\n ]\n }\n },\n {\n weight: 190,\n type: 'textfield',\n input: true,\n key: 'errorLabel',\n label: 'Error Label',\n placeholder: 'Error Label',\n tooltip: 'The label for this field when an error occurs.'\n },\n {\n weight: 200,\n key: 'validate.customMessage',\n label: 'Custom Error Message',\n placeholder: 'Custom Error Message',\n type: 'textfield',\n tooltip: 'Error message displayed if any error occurred.',\n input: true\n },\n {\n type: 'panel',\n title: 'Custom Validation',\n collapsible: true,\n collapsed: true,\n style: { 'margin-bottom': '10px' },\n key: 'custom-validation-js',\n weight: 300,\n customConditional() {\n return !Evaluator_1.default.noeval || Evaluator_1.default.protectedEval;\n },\n components: [\n utils_1.default.logicVariablesTable('<tr><th>input</th><td>The value that was input into this component</td></tr>'),\n {\n type: 'textarea',\n key: 'validate.custom',\n rows: 5,\n editor: 'ace',\n hideLabel: true,\n as: 'javascript',\n input: true\n },\n {\n type: 'htmlelement',\n tag: 'div',\n content: `\n <small>\n <p>Enter custom validation code.</p>\n <p>You must assign the <strong>valid</strong> variable as either <strong>true</strong> or an error message if validation fails.</p>\n <h5>Example:</h5>\n <pre>valid = (input === 'Joe') ? true : 'Your name must be \"Joe\"';</pre>\n </small>`\n },\n {\n type: 'well',\n components: [\n {\n weight: 100,\n type: 'checkbox',\n label: 'Secret Validation',\n tooltip: 'Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.',\n description: 'Check this if you wish to perform the validation ONLY on the server side. This keeps your validation logic private and secret.',\n key: 'validate.customPrivate',\n input: true\n }\n ]\n }\n ]\n },\n {\n type: 'panel',\n title: 'JSONLogic Validation',\n collapsible: true,\n collapsed: true,\n key: 'json-validation-json',\n weight: 400,\n components: [\n {\n type: 'htmlelement',\n tag: 'div',\n /* eslint-disable prefer-template */\n content: '<p>Execute custom logic using <a href=\"http://jsonlogic.com/\" target=\"_blank\" rel=\"noopener noreferrer\">JSONLogic</a>.</p>' +\n '<h5>Example:</h5>' +\n '<pre>' + JSON.stringify({\n \"if\": [\n { \"===\": [{ \"var\": \"input\" }, \"Bob\"] },\n true,\n \"Your name must be 'Bob'!\"\n ]\n }, null, 2) + '</pre>'\n /* eslint-enable prefer-template */\n },\n {\n type: 'textarea',\n key: 'validate.json',\n hideLabel: true,\n rows: 5,\n editor: 'ace',\n as: 'json',\n input: true\n }\n ]\n },\n {\n type: 'panel',\n title: 'Custom Errors',\n collapsible: true,\n collapsed: true,\n key: 'errors',\n weight: 400,\n components: [\n {\n type: 'textarea',\n key: 'errors',\n hideLabel: true,\n rows: 5,\n editor: 'ace',\n as: 'json',\n input: true\n },\n {\n type: 'htmlelement',\n tag: 'div',\n content: `\n <p>This allows you to set different custom error messages for different errors\n (in contrast to “Custom Error Message”, which only allows you to set one\n error message for all errors). E.g.</p>\n\n<pre>{\n \"required\": \"{<span/>{ field }} is required. Try again.\",\n \"maxLength\": \"{<span/>{ field }} is too long. Try again.\"\n}</pre>\n\n <p>You can set the following keys (among others):</p>\n <ul>\n <li>r<span/>equired</li>\n <li>m<span/>in</li>\n <li>m<span/>ax</li>\n <li>m<span/>inLength</li>\n <li>m<span/>axLength</li>\n <li>m<span/>inWords</li>\n <li>m<span/>axWords</li>\n <li>i<span/>nvalid_email</li>\n <li>i<span/>nvalid_date</li>\n <li>i<span/>nvalid_day</li>\n <li>i<span/>nvalid_regex</li>\n <li>m<span/>ask</li>\n <li>p<span/>attern</li>\n <li>c<span/>ustom</li>\n </ul>\n\n <p>Depending on the error message some of the following template variables can be used in the script:</p>\n <ul>\n <li><code>{<span/>{ f<span/>ield }}</code> is replaced with the label of the field.</li>\n <li><code>{<span/>{ m<span/>in }}</code></li>\n <li><code>{<span/>{ m<span/>ax }}</code></li>\n <li><code>{<span/>{ l<span/>ength }}</code></li>\n <li><code>{<span/>{ p<span/>attern }}</code></li>\n <li><code>{<span/>{ m<span/>inDate }}</code></li>\n <li><code>{<span/>{ m<span/>axDate }}</code></li>\n <li><code>{<span/>{ m<span/>inYear }}</code></li>\n <li><code>{<span/>{ m<span/>axYear }}</code></li>\n <li><code>{<span/>{ r<span/>egex }}</code></li>\n </ul>\n `\n }\n ]\n }\n];\n/* eslint-enable quotes, max-len */\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/editForm/Component.edit.validation.js?");
|
|
5013
5013
|
|
|
5014
5014
|
/***/ }),
|
|
5015
5015
|
|
|
@@ -5086,7 +5086,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5086
5086
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5087
5087
|
|
|
5088
5088
|
"use strict";
|
|
5089
|
-
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 Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ../../Components */ \"./lib/cjs/components/Components.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass NestedComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n tree: false,\n lazyLoad: false,\n }, ...extend);\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.type = 'components';\n this._collapsed = !!this.component.collapsed;\n }\n get defaultSchema() {\n return NestedComponent.schema();\n }\n get schema() {\n const schema = super.schema;\n const components = lodash_1.default.uniqBy(this.getComponents(), 'component.key');\n schema.components = lodash_1.default.map(components, 'schema');\n return schema;\n }\n get collapsed() {\n return this._collapsed;\n }\n collapse(value) {\n const promise = this.redraw();\n if (!value) {\n this.checkValidity(this.data, !this.pristine, null, this.pristine);\n }\n return promise;\n }\n set collapsed(value) {\n this._collapsed = value;\n this.collapse(value);\n }\n set visible(value) {\n // DO NOT CALL super here. There is an issue where clearOnHide was getting triggered with\n // subcomponents because the \"parentVisible\" flag was set to false when it should really be\n // set to true.\n const visibilityChanged = this._visible !== value;\n this._visible = value;\n const isVisible = this.visible;\n const forceShow = this.shouldForceShow();\n const forceHide = this.shouldForceHide();\n this.components.forEach(component => {\n // Set the parent visibility first since we may have nested components within nested components\n // and they need to be able to determine their visibility based on the parent visibility.\n component.parentVisible = isVisible;\n const conditionallyVisible = component.conditionallyVisible();\n if (forceShow || conditionallyVisible) {\n component.visible = true;\n }\n else if (forceHide || !isVisible || !conditionallyVisible) {\n component.visible = false;\n }\n // If hiding a nested component, clear all errors below.\n if (!component.visible) {\n component.error = '';\n }\n });\n if (visibilityChanged) {\n this.clearOnHide();\n this.redraw();\n }\n }\n get visible() {\n return super.visible;\n }\n set parentVisible(value) {\n super.parentVisible = value;\n this.components.forEach(component => component.parentVisible = this.visible);\n }\n get parentVisible() {\n return super.parentVisible;\n }\n get disabled() {\n return super.disabled;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n this.components.forEach((component) => component.parentDisabled = disabled);\n }\n set parentDisabled(value) {\n super.parentDisabled = value;\n this.components.forEach(component => {\n component.parentDisabled = this.disabled;\n });\n }\n get parentDisabled() {\n return super.parentDisabled;\n }\n get ready() {\n return Promise.all(this.getComponents().map(component => component.ready));\n }\n get currentForm() {\n return super.currentForm;\n }\n set currentForm(instance) {\n super.currentForm = instance;\n this.getComponents().forEach(component => {\n component.currentForm = instance;\n });\n }\n get rowIndex() {\n return this._rowIndex;\n }\n set rowIndex(value) {\n this._rowIndex = value;\n this.eachComponent((component) => {\n component.rowIndex = value;\n });\n }\n componentContext() {\n return this._data;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n this.eachComponent((component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.components || [];\n }\n /**\n * Perform a deep iteration over every component, including those\n * within other container based components.\n *\n * @param {function} fn - Called for every component.\n */\n everyComponent(fn, options) {\n const components = this.getComponents();\n lodash_1.default.each(components, (component, index) => {\n if (fn(component, components, index) === false) {\n return false;\n }\n if (typeof component.everyComponent === 'function') {\n if (component.everyComponent(fn, options) === false) {\n return false;\n }\n }\n });\n }\n hasComponent(component) {\n let result = false;\n this.everyComponent((comp) => {\n if (comp === component) {\n result = true;\n return false;\n }\n });\n return result;\n }\n flattenComponents() {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n });\n return result;\n }\n /**\n * Perform an iteration over each component within this container component.\n *\n * @param {function} fn - Called for each component\n */\n eachComponent(fn) {\n lodash_1.default.each(this.getComponents(), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n /**\n * Returns a component provided a key. This performs a deep search within the\n * component tree.\n *\n * @param {string} key - The key of the component to retrieve.\n * @param {function} fn - Called with the component once found.\n * @return {Object} - The component that is located.\n */\n getComponent(path, fn, originalPath) {\n originalPath = originalPath || (0, utils_1.getStringFromComponentPath)(path);\n path = (0, utils_1.getArrayFromComponentPath)(path);\n const pathStr = originalPath;\n const newPath = lodash_1.default.clone(path);\n let key = newPath.shift();\n const remainingPath = newPath;\n let comp = null;\n let possibleComp = null;\n if (lodash_1.default.isNumber(key)) {\n key = remainingPath.shift();\n }\n if (!lodash_1.default.isString(key)) {\n return comp;\n }\n this.everyComponent((component, components) => {\n const matchPath = component.hasInput && component.path ? pathStr.includes(component.path) : true;\n if (component.component.key === key) {\n possibleComp = component;\n if (matchPath) {\n comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn, originalPath);\n }\n else if (fn) {\n fn(component, components);\n }\n return false;\n }\n }\n });\n if (!comp) {\n comp = possibleComp;\n }\n return comp;\n }\n /**\n * Return a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component.\n * @param {function} fn - Called with the component once it is retrieved.\n * @return {Object} - The component retrieved.\n */\n getComponentById(id, fn) {\n let comp = null;\n this.everyComponent((component, components) => {\n if (component.id === id) {\n comp = component;\n if (fn) {\n fn(component, components);\n }\n return false;\n }\n });\n return comp;\n }\n /**\n * Return a path of component's value.\n *\n * @param {Object} component - The component instance.\n * @return {string} - The component's value path.\n */\n calculateComponentPath(component) {\n let path = '';\n if (component.component.key) {\n let thisPath = this;\n while (thisPath && !thisPath.allowData && thisPath.parent) {\n thisPath = thisPath.parent;\n }\n const rowIndex = component.row ? `[${Number.parseInt(component.row)}]` : '';\n path = thisPath.path ? `${thisPath.path}${rowIndex}.` : '';\n path += component._parentPath && component.component.shouldIncludeSubFormPath ? component._parentPath : '';\n path += component.component.key;\n return path;\n }\n }\n /**\n * Create a new component and add it to the components array.\n *\n * @param component\n * @param data\n */\n createComponent(component, options, data, before, replacedComp) {\n if (!component) {\n return;\n }\n options = options || this.options;\n data = data || this.data;\n options.parent = this;\n options.parentVisible = this.visible;\n options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;\n options.localRoot = this.localRoot;\n options.skipInit = true;\n if (!(options.display === 'pdf' && this.builderMode)) {\n component.id = (0, utils_1.getRandomComponentId)();\n }\n if (!this.isInputComponent && this.component.shouldIncludeSubFormPath) {\n component.shouldIncludeSubFormPath = true;\n }\n const comp = Components_1.default.create(component, options, data, true);\n const path = this.calculateComponentPath(comp);\n if (path) {\n comp.path = path;\n }\n comp.init();\n if (component.internal) {\n return comp;\n }\n if (before) {\n const index = lodash_1.default.findIndex(this.components, { id: before.id });\n if (index !== -1) {\n this.components.splice(index, 0, comp);\n }\n else {\n this.components.push(comp);\n }\n }\n else if (replacedComp) {\n const index = lodash_1.default.findIndex(this.components, { id: replacedComp.id });\n if (index !== -1) {\n this.components[index] = comp;\n }\n else {\n this.components.push(comp);\n }\n }\n else {\n this.components.push(comp);\n }\n return comp;\n }\n getContainer() {\n return this.element;\n }\n get componentComponents() {\n return this.component.components || [];\n }\n get nestedKey() {\n return `nested-${this.key}`;\n }\n get templateName() {\n return 'container';\n }\n init() {\n this.components = this.components || [];\n this.addComponents();\n return super.init();\n }\n /**\n *\n * @param element\n * @param data\n */\n addComponents(data, options) {\n data = data || this.data;\n this.components = this.components || [];\n options = options || this.options;\n if (options.components) {\n this.components = options.components;\n }\n else {\n const components = this.hook('addComponents', this.componentComponents, this) || [];\n components.forEach((component) => this.addComponent(component, data));\n }\n }\n /**\n * Add a new component to the components array.\n *\n * @param {Object} component - The component JSON schema to add.\n * @param {Object} data - The submission data object to house the data for this component.\n * @param {HTMLElement} before - A DOM element to insert this element before.\n * @return {Component} - The created component instance.\n */\n addComponent(component, data, before, noAdd) {\n data = data || this.data;\n this.components = this.components || [];\n if (this.options.parentPath) {\n component.shouldIncludeSubFormPath = true;\n }\n component = this.hook('addComponent', component, data, before, noAdd);\n const comp = this.createComponent(component, this.options, data, before ? before : null);\n if (noAdd) {\n return comp;\n }\n return comp;\n }\n beforeFocus() {\n if (this.parent && 'beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n }\n render(children) {\n // If already rendering, don't re-render.\n return super.render(children || this.renderTemplate(this.templateName, {\n children: !this.visible ? '' : this.renderComponents(),\n nestedKey: this.nestedKey,\n collapsed: this.options.pdf ? false : this.collapsed,\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n return this.renderTemplate('components', {\n children,\n components,\n });\n }\n attach(element) {\n const superPromise = super.attach(element);\n this.loadRefs(element, {\n header: 'single',\n collapsed: this.collapsed,\n [this.nestedKey]: 'single',\n });\n let childPromise = Promise.resolve();\n if (this.refs[this.nestedKey]) {\n childPromise = this.attachComponents(this.refs[this.nestedKey]);\n }\n if (!this.visible) {\n this.attachComponentsLogic();\n }\n if (this.component.collapsible && this.refs.header) {\n this.addEventListener(this.refs.header, 'click', () => {\n this.collapsed = !this.collapsed;\n });\n this.addEventListener(this.refs.header, 'keydown', (e) => {\n if (e.keyCode === 13 || e.keyCode === 32) {\n e.preventDefault();\n this.collapsed = !this.collapsed;\n }\n });\n }\n return Promise.all([\n superPromise,\n childPromise,\n ]);\n }\n attachComponentsLogic(components) {\n components = components || this.components;\n lodash_1.default.each(components, (comp) => {\n comp.attachLogic();\n if (lodash_1.default.isFunction(comp.attachComponentsLogic)) {\n comp.attachComponentsLogic();\n }\n });\n }\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n if (!element) {\n // Return a non-resolving promise.\n return (new Promise(() => { }));\n }\n let index = 0;\n const promises = [];\n Array.prototype.slice.call(element.children).forEach(child => {\n if (!child.getAttribute('data-noattach') && components[index]) {\n promises.push(components[index].attach(child));\n index++;\n }\n });\n return Promise.all(promises);\n }\n /**\n * Remove a component from the components array.\n *\n * @param {Component} component - The component to remove from the components.\n * @param {Array<Component>} components - An array of components to remove this component from.\n */\n removeComponent(component, components, all = false) {\n components = components || this.components;\n component.destroy(all);\n lodash_1.default.remove(components, { id: component.id });\n }\n /**\n * Removes a component provided the API key of that component.\n *\n * @param {string} key - The API key of the component to remove.\n * @param {function} fn - Called once the component is removed.\n * @return {null}\n */\n removeComponentByKey(key, fn) {\n const comp = this.getComponent(key, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n /**\n * Removes a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component to remove.\n * @param {function} fn - Called when the component is removed.\n * @return {null}\n */\n removeComponentById(id, fn) {\n const comp = this.getComponentById(id, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n updateValue(value, flags = {}) {\n return this.components.reduce((changed, comp) => {\n return comp.updateValue(null, flags) || changed;\n }, super.updateValue(value, flags));\n }\n shouldSkipValidation(data, dirty, row) {\n // Nested components with no input should not be validated.\n if (!this.component.input) {\n return true;\n }\n else {\n return super.shouldSkipValidation(data, dirty, row);\n }\n }\n checkData(data, flags, row, components) {\n if (this.builderMode) {\n return true;\n }\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n components = components && lodash_1.default.isArray(components) ? components : this.getComponents();\n const isValid = components.reduce((valid, comp) => {\n return comp.checkData(data, flags, row) && valid;\n }, super.checkData(data, flags, row));\n this.checkModal(isValid, this.isDirty);\n return isValid;\n }\n checkConditions(data, flags, row) {\n // check conditions of parent component first, because it may influence on visibility of it's children\n const check = super.checkConditions(data, flags, row);\n //row data of parent component not always corresponds to row of nested components, use comp.data as row data for children instead\n this.getComponents().forEach(comp => comp.checkConditions(data, flags, comp.data));\n return check;\n }\n clearOnHide(show) {\n super.clearOnHide(show);\n if (this.component.clearOnHide) {\n if (this.allowData && !this.hasValue() && !(this.options.server && !this.visible)) {\n this.dataValue = this.defaultValue;\n }\n if (this.hasValue()) {\n this.restoreComponentsContext();\n }\n }\n this.getComponents().forEach(component => component.clearOnHide(show));\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => component.data = this.dataValue);\n }\n /**\n * Allow components to hook into the next page trigger to perform their own logic.\n *\n * @return {*}\n */\n beforePage(next) {\n return Promise.all(this.getComponents().map((comp) => comp.beforePage(next)));\n }\n /**\n * Allow components to hook into the submission to provide their own async data.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.all(this.getComponents().map((comp) => comp.beforeSubmit()));\n }\n calculateValue(data, flags, row) {\n // Do not iterate into children and calculateValues if this nested component is conditionally hidden.\n if (!this.conditionallyVisible()) {\n return false;\n }\n return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));\n }\n isLastPage() {\n return this.pages.length - 1 === this.page;\n }\n isValid(data, dirty) {\n return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));\n }\n checkChildComponentsValidity(data, dirty, row, silentCheck, isParentValid) {\n return this.getComponents().reduce((check, comp) => comp.checkValidity(data, dirty, row, silentCheck) && check, isParentValid);\n }\n checkValidity(data, dirty, row, silentCheck) {\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n const isValid = this.checkChildComponentsValidity(data, dirty, row, silentCheck, super.checkValidity(data, dirty, row, silentCheck));\n this.checkModal(isValid, dirty);\n return isValid;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n return this.ready.then(() => {\n const promises = [super.checkAsyncValidity(data, dirty, row, silentCheck)];\n this.eachComponent((component) => promises.push(component.checkAsyncValidity(data, dirty, row, silentCheck)));\n return Promise.all(promises).then((results) => results.reduce((valid, result) => (valid && result), true));\n });\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n this.getComponents().forEach((comp) => comp.setPristine(pristine));\n }\n get isPristine() {\n return this.pristine && this.getComponents().every((c) => c.isPristine);\n }\n get isDirty() {\n return this.dirty && this.getComponents().every((c) => c.isDirty);\n }\n detach() {\n this.components.forEach(component => {\n component.detach();\n });\n super.detach();\n }\n clear() {\n this.components.forEach(component => {\n component.clear();\n });\n super.clear();\n }\n destroy(all = false) {\n this.destroyComponents(all);\n super.destroy(all);\n }\n destroyComponents(all = false) {\n const components = this.getComponents().slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n this.components = [];\n }\n get errors() {\n const thisErrors = this.error ? [this.error] : [];\n return this.getComponents()\n .reduce((errors, comp) => errors.concat(comp.errors || []), thisErrors)\n .filter(err => err.level !== 'hidden');\n }\n getValue() {\n return this.data;\n }\n resetValue() {\n super.resetValue();\n this.getComponents().forEach((comp) => comp.resetValue());\n this.setPristine(true);\n }\n get dataReady() {\n return Promise.all(this.getComponents().map((component) => component.dataReady));\n }\n setNestedValue(component, value, flags = {}) {\n component._data = this.componentContext(component);\n if (component.type === 'button') {\n return false;\n }\n if (component.type === 'components') {\n if (component.tree && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n return component.setValue(value, flags);\n }\n else if (value && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {\n flags.noValidate = !flags.dirty;\n flags.resetValue = true;\n return component.setValue(component.defaultValue, flags);\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n return false;\n }\n if (value.submitAsDraft && !value.submit) {\n flags.noValidate = true;\n }\n return this.getComponents().reduce((changed, component) => {\n return this.setNestedValue(component, value, flags, changed) || changed;\n }, false);\n }\n get lazyLoad() {\n var _a;\n return (_a = this.component.lazyLoad) !== null && _a !== void 0 ? _a : false;\n }\n}\nexports[\"default\"] = NestedComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/nested/NestedComponent.js?");
|
|
5089
|
+
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 Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ../../Components */ \"./lib/cjs/components/Components.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass NestedComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n tree: false,\n lazyLoad: false,\n }, ...extend);\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.type = 'components';\n this._collapsed = !!this.component.collapsed;\n }\n get defaultSchema() {\n return NestedComponent.schema();\n }\n get schema() {\n const schema = super.schema;\n const components = lodash_1.default.uniqBy(this.getComponents(), 'component.key');\n schema.components = lodash_1.default.map(components, 'schema');\n return schema;\n }\n get collapsed() {\n return this._collapsed;\n }\n collapse(value) {\n const promise = this.redraw();\n if (!value) {\n this.checkValidity(this.data, !this.pristine, null, this.pristine);\n }\n return promise;\n }\n set collapsed(value) {\n this._collapsed = value;\n this.collapse(value);\n }\n set visible(value) {\n // DO NOT CALL super here. There is an issue where clearOnHide was getting triggered with\n // subcomponents because the \"parentVisible\" flag was set to false when it should really be\n // set to true.\n const visibilityChanged = this._visible !== value;\n this._visible = value;\n const isVisible = this.visible;\n const forceShow = this.shouldForceShow();\n const forceHide = this.shouldForceHide();\n this.components.forEach(component => {\n // Set the parent visibility first since we may have nested components within nested components\n // and they need to be able to determine their visibility based on the parent visibility.\n component.parentVisible = isVisible;\n const conditionallyVisible = component.conditionallyVisible();\n if (forceShow || conditionallyVisible) {\n component.visible = true;\n }\n else if (forceHide || !isVisible || !conditionallyVisible) {\n component.visible = false;\n }\n // If hiding a nested component, clear all errors below.\n if (!component.visible) {\n component.error = '';\n }\n });\n if (visibilityChanged) {\n this.clearOnHide();\n this.redraw();\n }\n }\n get visible() {\n return super.visible;\n }\n set parentVisible(value) {\n super.parentVisible = value;\n this.components.forEach(component => component.parentVisible = this.visible);\n }\n get parentVisible() {\n return super.parentVisible;\n }\n get disabled() {\n return super.disabled;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n this.components.forEach((component) => component.parentDisabled = disabled);\n }\n set parentDisabled(value) {\n super.parentDisabled = value;\n this.components.forEach(component => {\n component.parentDisabled = this.disabled;\n });\n }\n get parentDisabled() {\n return super.parentDisabled;\n }\n get ready() {\n return Promise.all(this.getComponents().map(component => component.ready));\n }\n get currentForm() {\n return super.currentForm;\n }\n set currentForm(instance) {\n super.currentForm = instance;\n this.getComponents().forEach(component => {\n component.currentForm = instance;\n });\n }\n get rowIndex() {\n return this._rowIndex;\n }\n set rowIndex(value) {\n this._rowIndex = value;\n this.eachComponent((component) => {\n component.rowIndex = value;\n });\n }\n componentContext() {\n return this._data;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n this.eachComponent((component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.components || [];\n }\n /**\n * Perform a deep iteration over every component, including those\n * within other container based components.\n *\n * @param {function} fn - Called for every component.\n */\n everyComponent(fn, options) {\n const components = this.getComponents();\n lodash_1.default.each(components, (component, index) => {\n if (fn(component, components, index) === false) {\n return false;\n }\n if (typeof component.everyComponent === 'function') {\n if (component.everyComponent(fn, options) === false) {\n return false;\n }\n }\n });\n }\n hasComponent(component) {\n let result = false;\n this.everyComponent((comp) => {\n if (comp === component) {\n result = true;\n return false;\n }\n });\n return result;\n }\n flattenComponents() {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n });\n return result;\n }\n /**\n * Perform an iteration over each component within this container component.\n *\n * @param {function} fn - Called for each component\n */\n eachComponent(fn) {\n lodash_1.default.each(this.getComponents(), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n /**\n * Returns a component provided a key. This performs a deep search within the\n * component tree.\n *\n * @param {string} key - The key of the component to retrieve.\n * @param {function} fn - Called with the component once found.\n * @return {Object} - The component that is located.\n */\n getComponent(path, fn, originalPath) {\n originalPath = originalPath || (0, utils_1.getStringFromComponentPath)(path);\n path = (0, utils_1.getArrayFromComponentPath)(path);\n const pathStr = originalPath;\n const newPath = lodash_1.default.clone(path);\n let key = newPath.shift();\n const remainingPath = newPath;\n let comp = null;\n let possibleComp = null;\n if (lodash_1.default.isNumber(key)) {\n key = remainingPath.shift();\n }\n if (!lodash_1.default.isString(key)) {\n return comp;\n }\n this.everyComponent((component, components) => {\n const matchPath = component.hasInput && component.path ? pathStr.includes(component.path) : true;\n if (component.component.key === key) {\n possibleComp = component;\n if (matchPath) {\n comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn, originalPath);\n }\n else if (fn) {\n fn(component, components);\n }\n return false;\n }\n }\n });\n if (!comp) {\n comp = possibleComp;\n }\n return comp;\n }\n /**\n * Return a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component.\n * @param {function} fn - Called with the component once it is retrieved.\n * @return {Object} - The component retrieved.\n */\n getComponentById(id, fn) {\n let comp = null;\n this.everyComponent((component, components) => {\n if (component.id === id) {\n comp = component;\n if (fn) {\n fn(component, components);\n }\n return false;\n }\n });\n return comp;\n }\n /**\n * Return a path of component's value.\n *\n * @param {Object} component - The component instance.\n * @return {string} - The component's value path.\n */\n calculateComponentPath(component) {\n let path = '';\n if (component.component.key) {\n let thisPath = this;\n while (thisPath && !thisPath.allowData && thisPath.parent) {\n thisPath = thisPath.parent;\n }\n const rowIndex = component.row ? `[${Number.parseInt(component.row)}]` : '';\n path = thisPath.path ? `${thisPath.path}${rowIndex}.` : '';\n path += component._parentPath && component.component.shouldIncludeSubFormPath ? component._parentPath : '';\n path += component.component.key;\n return path;\n }\n }\n /**\n * Create a new component and add it to the components array.\n *\n * @param component\n * @param data\n */\n createComponent(component, options, data, before, replacedComp) {\n if (!component) {\n return;\n }\n options = options || this.options;\n data = data || this.data;\n options.parent = this;\n options.parentVisible = this.visible;\n options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;\n options.localRoot = this.localRoot;\n options.skipInit = true;\n if (!(options.display === 'pdf' && this.builderMode)) {\n component.id = (0, utils_1.getRandomComponentId)();\n }\n if (!this.isInputComponent && this.component.shouldIncludeSubFormPath) {\n component.shouldIncludeSubFormPath = true;\n }\n const comp = Components_1.default.create(component, options, data, true);\n const path = this.calculateComponentPath(comp);\n if (path) {\n comp.path = path;\n }\n comp.init();\n if (component.internal) {\n return comp;\n }\n if (before) {\n const index = lodash_1.default.findIndex(this.components, { id: before.id });\n if (index !== -1) {\n this.components.splice(index, 0, comp);\n }\n else {\n this.components.push(comp);\n }\n }\n else if (replacedComp) {\n const index = lodash_1.default.findIndex(this.components, { id: replacedComp.id });\n if (index !== -1) {\n this.components[index] = comp;\n }\n else {\n this.components.push(comp);\n }\n }\n else {\n this.components.push(comp);\n }\n return comp;\n }\n getContainer() {\n return this.element;\n }\n get componentComponents() {\n return this.component.components || [];\n }\n get nestedKey() {\n return `nested-${this.key}`;\n }\n get templateName() {\n return 'container';\n }\n init() {\n this.components = this.components || [];\n this.addComponents();\n return super.init();\n }\n /**\n *\n * @param element\n * @param data\n */\n addComponents(data, options) {\n data = data || this.data;\n this.components = this.components || [];\n options = options || this.options;\n if (options.components) {\n this.components = options.components;\n }\n else {\n const components = this.hook('addComponents', this.componentComponents, this) || [];\n components.forEach((component) => this.addComponent(component, data));\n }\n }\n /**\n * Add a new component to the components array.\n *\n * @param {Object} component - The component JSON schema to add.\n * @param {Object} data - The submission data object to house the data for this component.\n * @param {HTMLElement} before - A DOM element to insert this element before.\n * @return {Component} - The created component instance.\n */\n addComponent(component, data, before, noAdd) {\n data = data || this.data;\n this.components = this.components || [];\n if (this.options.parentPath) {\n component.shouldIncludeSubFormPath = true;\n }\n component = this.hook('addComponent', component, data, before, noAdd);\n const comp = this.createComponent(component, this.options, data, before ? before : null);\n if (noAdd) {\n return comp;\n }\n return comp;\n }\n beforeFocus() {\n if (this.parent && 'beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n }\n render(children) {\n // If already rendering, don't re-render.\n return super.render(children || this.renderTemplate(this.templateName, {\n children: !this.visible ? '' : this.renderComponents(),\n nestedKey: this.nestedKey,\n collapsed: this.options.pdf ? false : this.collapsed,\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n return this.renderTemplate('components', {\n children,\n components,\n });\n }\n attach(element) {\n const superPromise = super.attach(element);\n this.loadRefs(element, {\n header: 'single',\n collapsed: this.collapsed,\n [this.nestedKey]: 'single',\n });\n let childPromise = Promise.resolve();\n if (this.refs[this.nestedKey]) {\n childPromise = this.attachComponents(this.refs[this.nestedKey]);\n }\n if (!this.visible) {\n this.attachComponentsLogic();\n }\n if (this.component.collapsible && this.refs.header) {\n this.addEventListener(this.refs.header, 'click', () => {\n this.collapsed = !this.collapsed;\n });\n this.addEventListener(this.refs.header, 'keydown', (e) => {\n if (e.keyCode === 13 || e.keyCode === 32) {\n e.preventDefault();\n this.collapsed = !this.collapsed;\n }\n });\n }\n return Promise.all([\n superPromise,\n childPromise,\n ]);\n }\n attachComponentsLogic(components) {\n components = components || this.components;\n lodash_1.default.each(components, (comp) => {\n comp.attachLogic();\n if (lodash_1.default.isFunction(comp.attachComponentsLogic)) {\n comp.attachComponentsLogic();\n }\n });\n }\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n if (!element) {\n // Return a non-resolving promise.\n return (new Promise(() => { }));\n }\n let index = 0;\n const promises = [];\n Array.prototype.slice.call(element.children).forEach(child => {\n if (!child.getAttribute('data-noattach') && components[index]) {\n promises.push(components[index].attach(child));\n index++;\n }\n });\n return Promise.all(promises);\n }\n /**\n * Remove a component from the components array.\n *\n * @param {Component} component - The component to remove from the components.\n * @param {Array<Component>} components - An array of components to remove this component from.\n */\n removeComponent(component, components, all = false) {\n components = components || this.components;\n component.destroy(all);\n lodash_1.default.remove(components, { id: component.id });\n }\n /**\n * Removes a component provided the API key of that component.\n *\n * @param {string} key - The API key of the component to remove.\n * @param {function} fn - Called once the component is removed.\n * @return {null}\n */\n removeComponentByKey(key, fn) {\n const comp = this.getComponent(key, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n /**\n * Removes a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component to remove.\n * @param {function} fn - Called when the component is removed.\n * @return {null}\n */\n removeComponentById(id, fn) {\n const comp = this.getComponentById(id, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n updateValue(value, flags = {}) {\n return this.components.reduce((changed, comp) => {\n return comp.updateValue(null, flags) || changed;\n }, super.updateValue(value, flags));\n }\n shouldSkipValidation(data, dirty, row) {\n // Nested components with no input should not be validated.\n if (!this.component.input) {\n return true;\n }\n else {\n return super.shouldSkipValidation(data, dirty, row);\n }\n }\n checkData(data, flags, row, components) {\n if (this.builderMode) {\n return true;\n }\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n components = components && lodash_1.default.isArray(components) ? components : this.getComponents();\n const isValid = components.reduce((valid, comp) => {\n return comp.checkData(data, Object.assign({}, flags), row) && valid;\n }, super.checkData(data, Object.assign({}, flags), row));\n this.checkModal(isValid, this.isDirty);\n return isValid;\n }\n checkConditions(data, flags, row) {\n // check conditions of parent component first, because it may influence on visibility of it's children\n const check = super.checkConditions(data, flags, row);\n //row data of parent component not always corresponds to row of nested components, use comp.data as row data for children instead\n this.getComponents().forEach(comp => comp.checkConditions(data, flags, comp.data));\n return check;\n }\n clearOnHide(show) {\n super.clearOnHide(show);\n if (this.component.clearOnHide) {\n if (this.allowData && !this.hasValue() && !(this.options.server && !this.visible)) {\n this.dataValue = this.defaultValue;\n }\n if (this.hasValue()) {\n this.restoreComponentsContext();\n }\n }\n this.getComponents().forEach(component => component.clearOnHide(show));\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => component.data = this.dataValue);\n }\n /**\n * Allow components to hook into the next page trigger to perform their own logic.\n *\n * @return {*}\n */\n beforePage(next) {\n return Promise.all(this.getComponents().map((comp) => comp.beforePage(next)));\n }\n /**\n * Allow components to hook into the submission to provide their own async data.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.all(this.getComponents().map((comp) => comp.beforeSubmit()));\n }\n calculateValue(data, flags, row) {\n // Do not iterate into children and calculateValues if this nested component is conditionally hidden.\n if (!this.conditionallyVisible()) {\n return false;\n }\n return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));\n }\n isLastPage() {\n return this.pages.length - 1 === this.page;\n }\n isValid(data, dirty) {\n return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));\n }\n checkChildComponentsValidity(data, dirty, row, silentCheck, isParentValid) {\n return this.getComponents().reduce((check, comp) => comp.checkValidity(data, dirty, row, silentCheck) && check, isParentValid);\n }\n checkValidity(data, dirty, row, silentCheck) {\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n const isValid = this.checkChildComponentsValidity(data, dirty, row, silentCheck, super.checkValidity(data, dirty, row, silentCheck));\n this.checkModal(isValid, dirty);\n return isValid;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n return this.ready.then(() => {\n const promises = [super.checkAsyncValidity(data, dirty, row, silentCheck)];\n this.eachComponent((component) => promises.push(component.checkAsyncValidity(data, dirty, row, silentCheck)));\n return Promise.all(promises).then((results) => results.reduce((valid, result) => (valid && result), true));\n });\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n this.getComponents().forEach((comp) => comp.setPristine(pristine));\n }\n get isPristine() {\n return this.pristine && this.getComponents().every((c) => c.isPristine);\n }\n get isDirty() {\n return this.dirty && this.getComponents().every((c) => c.isDirty);\n }\n detach() {\n this.components.forEach(component => {\n component.detach();\n });\n super.detach();\n }\n clear() {\n this.components.forEach(component => {\n component.clear();\n });\n super.clear();\n }\n destroy(all = false) {\n this.destroyComponents(all);\n super.destroy(all);\n }\n destroyComponents(all = false) {\n const components = this.getComponents().slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n this.components = [];\n }\n get errors() {\n const thisErrors = this.error ? [this.error] : [];\n return this.getComponents()\n .reduce((errors, comp) => errors.concat(comp.errors || []), thisErrors)\n .filter(err => err.level !== 'hidden');\n }\n getValue() {\n return this.data;\n }\n resetValue() {\n super.resetValue();\n this.getComponents().forEach((comp) => comp.resetValue());\n this.setPristine(true);\n }\n get dataReady() {\n return Promise.all(this.getComponents().map((component) => component.dataReady));\n }\n setNestedValue(component, value, flags = {}) {\n component._data = this.componentContext(component);\n if (component.type === 'button') {\n return false;\n }\n if (component.type === 'components') {\n if (component.tree && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n return component.setValue(value, flags);\n }\n else if (value && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {\n flags.noValidate = !flags.dirty;\n flags.resetValue = true;\n return component.setValue(component.defaultValue, flags);\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n return false;\n }\n if (value.submitAsDraft && !value.submit) {\n flags.noValidate = true;\n }\n return this.getComponents().reduce((changed, component) => {\n return this.setNestedValue(component, value, flags, changed) || changed;\n }, false);\n }\n get lazyLoad() {\n var _a;\n return (_a = this.component.lazyLoad) !== null && _a !== void 0 ? _a : false;\n }\n}\nexports[\"default\"] = NestedComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/nested/NestedComponent.js?");
|
|
5090
5090
|
|
|
5091
5091
|
/***/ }),
|
|
5092
5092
|
|
|
@@ -5207,7 +5207,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5207
5207
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5208
5208
|
|
|
5209
5209
|
"use strict";
|
|
5210
|
-
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 NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DataGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n label: 'Data Grid',\n key: 'dataGrid',\n type: 'datagrid',\n clearOnHide: true,\n input: true,\n tree: true,\n components: []\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Data Grid',\n icon: 'th',\n group: 'data',\n documentation: '/userguide/form-building/data-components#data-grid',\n showPreview: false,\n weight: 30,\n schema: DataGridComponent.schema()\n };\n }\n constructor(...args) {\n super(...args);\n this.type = 'datagrid';\n this.tabIndex = 0;\n }\n init() {\n this.components = this.components || [];\n // Add new values based on minLength.\n this.rows = [];\n this.columns = [...this.component.components];\n if (this.initRows || !lodash_1.default.isEqual(this.dataValue, this.emptyValue)) {\n this.createRows(true);\n }\n this.visibleColumns = {};\n this.prevHasAddButton = this.hasAddButton();\n this.checkColumns();\n }\n get dataValue() {\n const dataValue = super.dataValue;\n if (!dataValue || !Array.isArray(dataValue)) {\n return this.emptyValue;\n }\n return dataValue;\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get defaultSchema() {\n return DataGridComponent.schema();\n }\n get initEmpty() {\n return this.component.initEmpty || this.component.noFirstRow;\n }\n get initRows() {\n return this.builderMode || this.path === 'defaultValue' || !this.initEmpty;\n }\n get emptyValue() {\n return this.initEmpty ? [] : [{}];\n }\n get addAnotherPosition() {\n return lodash_1.default.get(this.component, 'addAnotherPosition', 'bottom');\n }\n get minLength() {\n if (this.hasRowGroups()) {\n return lodash_1.default.sum(this.getGroupSizes());\n }\n else {\n return lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n }\n get defaultValue() {\n const isBuilderMode = this.builderMode;\n const isEmptyInit = this.initEmpty;\n // Ensure we have one and only one row in builder mode.\n if (isBuilderMode || (isEmptyInit && !this.dataValue.length)) {\n return isEmptyInit && !isBuilderMode ? [] : [{}];\n }\n const value = super.defaultValue;\n let defaultValue;\n if (Array.isArray(value)) {\n defaultValue = value;\n }\n else if (value && (typeof value === 'object')) {\n defaultValue = [value];\n }\n else {\n defaultValue = this.emptyValue;\n }\n for (let dIndex = defaultValue.length; dIndex < this.minLength; dIndex++) {\n defaultValue.push({});\n }\n return defaultValue;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n lodash_1.default.each(this.refs[`${this.datagridKey}-addRow`], (button) => {\n button.disabled = disabled;\n });\n lodash_1.default.each(this.refs[`${this.datagridKey}-removeRow`], (button) => {\n button.disabled = disabled;\n });\n }\n get disabled() {\n return super.disabled;\n }\n get datagridKey() {\n return `datagrid-${this.key}`;\n }\n get allowReorder() {\n return !this.options.readOnly && lodash_1.default.get(this.component, 'reorder', false);\n }\n get iteratableRows() {\n return this.rows.map((row, index) => ({\n components: row,\n data: this.dataValue[index],\n }));\n }\n isEmpty(value = this.dataValue) {\n var _a;\n const isEmpty = super.isEmpty(value);\n if ((_a = this.components) === null || _a === void 0 ? void 0 : _a.length) {\n return this.components.reduce((isEmpty, component) => {\n return isEmpty && component.isEmpty();\n }, true);\n }\n return isEmpty;\n }\n /**\n * Split rows into chunks.\n * @param {Number[]} groups - array of numbers where each item is size of group\n * @param {Array<T>} rows - rows collection\n * @return {Array<T[]>}\n */\n getRowChunks(groups, rows) {\n const [, chunks] = groups.reduce(([startIndex, acc], size) => {\n const endIndex = startIndex + size;\n return [endIndex, [...acc, [startIndex, endIndex]]];\n }, [0, []]);\n return chunks.map(range => lodash_1.default.slice(rows, ...range));\n }\n /**\n * Create groups object.\n * Each key in object represents index of first row in group.\n * @return {Object}\n */\n getGroups() {\n const groups = lodash_1.default.get(this.component, 'rowGroups', []);\n const sizes = lodash_1.default.map(groups, 'numberOfRows').slice(0, -1);\n const indexes = sizes.reduce((groupIndexes, size) => {\n const last = groupIndexes[groupIndexes.length - 1];\n return groupIndexes.concat(last + size);\n }, [0]);\n return groups.reduce((gidxs, group, idx) => {\n return Object.assign(Object.assign({}, gidxs), { [indexes[idx]]: group });\n }, {});\n }\n /**\n * Retrun group sizes.\n * @return {Number[]}\n */\n getGroupSizes() {\n return lodash_1.default.map(lodash_1.default.get(this.component, 'rowGroups', []), 'numberOfRows');\n }\n hasRowGroups() {\n return lodash_1.default.get(this, 'component.enableRowGroups', false) && !this.builderMode;\n }\n totalRowsNumber(groups) {\n return lodash_1.default.sum(lodash_1.default.map(groups, 'numberOfRows'));\n }\n setStaticValue(n) {\n this.dataValue = lodash_1.default.range(n).map(() => ({}));\n }\n hasExtraColumn() {\n return (this.hasRemoveButtons() || this.canAddColumn);\n }\n hasRemoveButtons() {\n return !this.builderMode && !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n hasTopSubmit() {\n return this.hasAddButton() && ['top', 'both'].includes(this.addAnotherPosition);\n }\n hasBottomSubmit() {\n return this.hasAddButton() && ['bottom', 'both'].includes(this.addAnotherPosition);\n }\n get canAddColumn() {\n return this.builderMode;\n }\n render() {\n const columns = this.getColumns();\n let columnExtra = 0;\n const hasRemoveButtons = this.hasRemoveButtons();\n if (this.component.reorder) {\n columnExtra++;\n }\n if (hasRemoveButtons) {\n columnExtra++;\n }\n if (this.canAddColumn) {\n columnExtra++;\n }\n const colWidth = Math.floor(12 / (columns.length + columnExtra));\n return super.render(this.renderTemplate('datagrid', {\n rows: this.getRows(),\n columns: columns,\n groups: this.hasRowGroups() ? this.getGroups() : [],\n visibleColumns: this.visibleColumns,\n hasToggle: lodash_1.default.get(this, 'component.groupToggle', false),\n hasHeader: this.hasHeader(),\n hasExtraColumn: this.hasExtraColumn(),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons,\n hasTopSubmit: this.hasTopSubmit(),\n hasBottomSubmit: this.hasBottomSubmit(),\n hasGroups: this.hasRowGroups(),\n numColumns: columns.length + (this.hasExtraColumn() ? 1 : 0),\n datagridKey: this.datagridKey,\n allowReorder: this.allowReorder,\n builder: this.builderMode,\n canAddColumn: this.canAddColumn,\n tabIndex: this.tabIndex,\n placeholder: this.renderTemplate('builderPlaceholder', {\n position: this.componentComponents.length,\n }),\n colWidth: colWidth.toString()\n }));\n }\n getRows() {\n return this.rows.map(row => {\n const components = {};\n lodash_1.default.each(row, (col, key) => {\n components[key] = col.render();\n });\n return components;\n });\n }\n getColumns() {\n return this.columns.filter((comp) => {\n return (!this.visibleColumns.hasOwnProperty(comp.key) || this.visibleColumns[comp.key]);\n });\n }\n hasHeader() {\n return this.component.components.reduce((hasHeader, col) => {\n // If any of the components has a title and it isn't hidden, display the header.\n return hasHeader || ((col.label || col.title) && !col.hideLabel);\n }, false);\n }\n loadRefs(element, refs) {\n super.loadRefs(element, refs);\n if (refs['messageContainer'] === 'single') {\n const container = lodash_1.default.last(element.querySelectorAll('[ref=messageContainer]'));\n this.refs['messageContainer'] = container || this.refs['messageContainer'];\n }\n }\n attach(element) {\n this.loadRefs(element, {\n [`${this.datagridKey}-row`]: 'multiple',\n [`${this.datagridKey}-tbody`]: 'single',\n [`${this.datagridKey}-addRow`]: 'multiple',\n [`${this.datagridKey}-removeRow`]: 'multiple',\n [`${this.datagridKey}-group-header`]: 'multiple',\n [this.datagridKey]: 'multiple',\n 'messageContainer': 'single'\n });\n if (this.allowReorder) {\n this.refs[`${this.datagridKey}-row`].forEach((row, index) => {\n row.dragInfo = { index };\n });\n if (this.root.dragulaLib) {\n this.dragula = this.root.dragulaLib([this.refs[`${this.datagridKey}-tbody`]], {\n moves: (_draggedElement, _oldParent, clickedElement) => {\n const clickedElementKey = clickedElement.getAttribute('data-key');\n const oldParentKey = _oldParent.getAttribute('data-key');\n //Check if the clicked button belongs to that container, if false, it belongs to the nested container\n if (oldParentKey === clickedElementKey) {\n return clickedElement.classList.contains('formio-drag-button');\n }\n }\n }).on('drop', this.onReorder.bind(this));\n this.dragula.on('cloned', (el, original) => {\n if (el && el.children && original && original.children) {\n lodash_1.default.each(original.children, (child, index) => {\n const styles = getComputedStyle(child, null);\n if (styles.cssText !== '') {\n el.children[index].style.cssText = styles.cssText;\n }\n else {\n const cssText = Object.values(styles).reduce((css, propertyName) => {\n return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;\n }, '');\n el.children[index].style.cssText = cssText;\n }\n });\n }\n });\n }\n }\n this.refs[`${this.datagridKey}-addRow`].forEach((addButton) => {\n this.addEventListener(addButton, 'click', this.addRow.bind(this));\n });\n this.refs[`${this.datagridKey}-removeRow`].forEach((removeButton, index) => {\n this.addEventListener(removeButton, 'click', this.removeRow.bind(this, index));\n });\n if (this.hasRowGroups()) {\n this.refs.chunks = this.getRowChunks(this.getGroupSizes(), this.refs[`${this.datagridKey}-row`]);\n this.refs[`${this.datagridKey}-group-header`].forEach((header, index) => {\n this.addEventListener(header, 'click', () => this.toggleGroup(header, index));\n });\n }\n const columns = this.getColumns();\n const rowLength = columns.length;\n this.rows.forEach((row, rowIndex) => {\n let columnIndex = 0;\n columns.forEach((col) => {\n this.attachComponents(this.refs[this.datagridKey][(rowIndex * rowLength) + columnIndex], [this.rows[rowIndex][col.key]], this.getComponentsContainer());\n columnIndex++;\n });\n });\n return super.attach(element);\n }\n getComponentsContainer() {\n return this.component.components;\n }\n onReorder(element, _target, _source, sibling) {\n if (!element.dragInfo || (sibling && !sibling.dragInfo)) {\n console.warn('There is no Drag Info available for either dragged or sibling element');\n return;\n }\n const oldPosition = element.dragInfo.index;\n //should drop at next sibling position; no next sibling means drop to last position\n const newPosition = sibling ? sibling.dragInfo.index : this.dataValue.length;\n const movedBelow = newPosition > oldPosition;\n const dataValue = (0, utils_1.fastCloneDeep)(this.dataValue);\n const draggedRowData = dataValue[oldPosition];\n //insert element at new position\n dataValue.splice(newPosition, 0, draggedRowData);\n //remove element from old position (if was moved above, after insertion it's at +1 index)\n dataValue.splice(movedBelow ? oldPosition : oldPosition + 1, 1);\n //need to re-build rows to re-calculate indexes and other indexed fields for component instance (like rows for ex.)\n this.setValue(dataValue, { isReordered: true });\n this.rebuild();\n }\n focusOnNewRowElement(row) {\n Object.keys(row).find((key) => {\n const element = row[key].element;\n if (element) {\n const focusableElements = (0, utils_1.getFocusableElements)(element);\n if (focusableElements && focusableElements[0]) {\n focusableElements[0].focus();\n return true;\n }\n }\n return false;\n });\n }\n addRow() {\n const index = this.rows.length;\n // Handle length mismatch between rows and dataValue\n if (this.dataValue.length === index) {\n this.dataValue.push({});\n }\n let row;\n const dataValue = this.dataValue;\n const defaultValue = this.defaultValue;\n if (this.initEmpty && defaultValue[index]) {\n row = defaultValue[index];\n dataValue[index] = row;\n }\n else {\n row = dataValue[index];\n }\n this.rows[index] = this.createRowComponents(row, index);\n this.emit('dataGridAddRow', {\n component: this.component,\n row\n });\n this.checkConditions();\n this.triggerChange();\n this.redraw().then(() => {\n this.focusOnNewRowElement(this.rows[index]);\n });\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n var _a;\n if ((_a = component.options) === null || _a === void 0 ? void 0 : _a.name) {\n const newName = `[${this.key}][${rowIndex}]`;\n component.options.name = component.options.name.replace(`[${this.key}][${component.rowIndex}]`, newName);\n }\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n component.path = this.calculateComponentPath(component);\n });\n }\n updateRowsComponents(rowIndex) {\n this.rows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(Object.values(row), rowIndex + index);\n });\n }\n removeRow(index) {\n const makeEmpty = index === 0 && this.rows.length === 1;\n const flags = { isReordered: !makeEmpty, resetValue: makeEmpty };\n this.splice(index, flags);\n this.emit('dataGridDeleteRow', { index });\n const [row] = this.rows.splice(index, 1);\n this.removeRowComponents(row);\n this.updateRowsComponents(index);\n this.setValue(this.dataValue, flags);\n this.redraw();\n }\n removeRowComponents(row) {\n lodash_1.default.each(row, (component) => this.removeComponent(component));\n }\n getRowValues() {\n return this.dataValue;\n }\n setRowComponentsData(rowIndex, rowData) {\n lodash_1.default.each(this.rows[rowIndex], (component) => {\n component.data = rowData;\n });\n }\n createRows(init, rebuild) {\n let added = false;\n const rowValues = this.getRowValues();\n // Create any missing rows.\n rowValues.forEach((row, index) => {\n if (!rebuild && this.rows[index]) {\n this.setRowComponentsData(index, row);\n }\n else {\n if (this.rows[index]) {\n this.removeRowComponents(this.rows[index]);\n }\n this.rows[index] = this.createRowComponents(row, index);\n added = true;\n }\n });\n // Delete any extra rows.\n const removedRows = this.rows.splice(rowValues.length);\n const removed = !!removedRows.length;\n // Delete components of extra rows (to make sure that this.components contain only components of exisiting rows)\n if (removed) {\n removedRows.forEach(row => this.removeRowComponents(row));\n }\n if (!init && (added || removed)) {\n this.redraw();\n }\n return added;\n }\n createRowComponents(row, rowIndex) {\n const components = {};\n this.tabIndex = 0;\n this.component.components.map((col, colIndex) => {\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n let columnComponent;\n if (this.builderMode) {\n col.id = col.id + rowIndex;\n columnComponent = col;\n }\n else {\n columnComponent = Object.assign(Object.assign({}, col), { id: (col.id + rowIndex) });\n }\n const component = this.createComponent(columnComponent, options, row);\n component.parentDisabled = !!this.disabled;\n component.rowIndex = rowIndex;\n component.inDataGrid = true;\n if (columnComponent.tabindex &&\n parseInt(columnComponent.tabindex) > this.tabIndex) {\n this.tabIndex = parseInt(columnComponent.tabindex);\n }\n components[col.key] = component;\n });\n return components;\n }\n /**\n * Checks the validity of this datagrid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n if (!this.checkComponentValidity(data, dirty, row, { silentCheck })) {\n return false;\n }\n const isValid = this.checkRows('checkValidity', data, dirty, true, silentCheck);\n this.checkModal(isValid, dirty);\n return isValid;\n }\n checkColumns(data, flags = {}) {\n data = data || this.rootValue;\n let show = false;\n if (!this.rows || !this.rows.length) {\n return { rebuild: false, show: false };\n }\n if (this.builderMode) {\n return { rebuild: false, show: true };\n }\n const visibility = {};\n let logicRebuild = false;\n const dataValue = this.dataValue;\n this.rows.forEach((row, rowIndex) => {\n lodash_1.default.each(row, (col, key) => {\n if (col && (typeof col.checkConditions === 'function')) {\n const firstRowCheck = visibility[key] === undefined;\n visibility[key] = !!visibility[key] ||\n (col.checkConditions(data, flags, dataValue[rowIndex]) && col.type !== 'hidden');\n if (col.component.logic && firstRowCheck) {\n const compIndex = lodash_1.default.findIndex(this.columns, ['key', key]);\n const equalColumns = lodash_1.default.isEqualWith(this.columns[compIndex], col.component, (col1, col2, key) => {\n // Don't compare columns by their auto-generated ids.\n if (key === 'id') {\n return true;\n }\n });\n if (!equalColumns) {\n logicRebuild = true;\n this.columns[compIndex] = col.component;\n }\n }\n }\n });\n });\n const rebuild = !lodash_1.default.isEqual(visibility, this.visibleColumns) || logicRebuild;\n lodash_1.default.each(visibility, (col) => {\n show |= col;\n });\n this.visibleColumns = visibility;\n return { rebuild, show };\n }\n checkComponentConditions(data, flags, row) {\n const isVisible = this.visible;\n // If table isn't visible, don't bother calculating columns.\n if (!super.checkComponentConditions(data, flags, row)) {\n return false;\n }\n const { rebuild, show } = this.checkColumns(data, flags);\n // Check if a rebuild is needed or the visibility changes.\n if (rebuild || !isVisible) {\n this.createRows(false, rebuild);\n }\n // Return if this table should show.\n return show;\n }\n setValue(value, flags = {}) {\n if (!value) {\n this.dataValue = this.defaultValue;\n this.createRows();\n return false;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n this.createRows();\n value = [{}];\n }\n }\n // Make sure we always have at least one row.\n // NOTE: Removing this will break \"Public Configurations\" in portal. ;)\n if (value && !value.length && !this.initEmpty) {\n value.push({});\n }\n const isSettingSubmission = flags.fromSubmission && !lodash_1.default.isEqual(value, this.emptyValue);\n const changed = this.hasChanged(value, this.dataValue);\n this.dataValue = value;\n if (this.initRows || isSettingSubmission) {\n if (!this.createRows() && changed) {\n this.redraw();\n }\n }\n if (this.componentModal && isSettingSubmission) {\n this.componentModal.setValue(value);\n }\n this.rows.forEach((row, rowIndex) => {\n if (value.length <= rowIndex) {\n return;\n }\n lodash_1.default.each(row, (col) => {\n col.rowIndex = rowIndex;\n this.setNestedValue(col, value[rowIndex], flags);\n });\n });\n this.updateOnChange(flags, changed);\n return changed;\n }\n restoreComponentsContext() {\n this.rows.forEach((row, index) => lodash_1.default.forIn(row, (component) => component.data = this.dataValue[index]));\n }\n getComponent(path, fn) {\n path = Array.isArray(path) ? path : [path];\n const [key, ...remainingPath] = path;\n let result = [];\n if (lodash_1.default.isNumber(key) && remainingPath.length) {\n const compKey = remainingPath.pop();\n result = this.rows[key][compKey];\n // If the component is inside a Layout Component, try to find it among all the row's components\n if (!result) {\n Object.entries(this.rows[key]).forEach(([, comp]) => {\n if ('getComponent' in comp) {\n const possibleResult = comp.getComponent([compKey], fn);\n if (possibleResult) {\n result = possibleResult;\n }\n }\n });\n }\n if (result && lodash_1.default.isFunction(fn)) {\n fn(result, this.getComponents());\n }\n if (remainingPath.length && 'getComponent' in result) {\n return result.getComponent(remainingPath, fn);\n }\n return result;\n }\n if (!lodash_1.default.isString(key)) {\n return result;\n }\n this.everyComponent((component, components) => {\n if (component.component.key === key) {\n let comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn);\n }\n else if (fn) {\n fn(component, components);\n }\n result = result.concat(comp);\n }\n });\n return result.length > 0 ? result : null;\n }\n toggleGroup(element, index) {\n element.classList.toggle('collapsed');\n lodash_1.default.each(this.refs.chunks[index], row => {\n row.classList.toggle('hidden');\n });\n }\n}\nexports[\"default\"] = DataGridComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/datagrid/DataGrid.js?");
|
|
5210
|
+
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 NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DataGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n label: 'Data Grid',\n key: 'dataGrid',\n type: 'datagrid',\n clearOnHide: true,\n input: true,\n tree: true,\n components: []\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Data Grid',\n icon: 'th',\n group: 'data',\n documentation: '/userguide/form-building/data-components#data-grid',\n showPreview: false,\n weight: 30,\n schema: DataGridComponent.schema()\n };\n }\n constructor(...args) {\n super(...args);\n this.type = 'datagrid';\n this.tabIndex = 0;\n }\n init() {\n this.components = this.components || [];\n // Add new values based on minLength.\n this.rows = [];\n this.columns = [...this.component.components];\n if (this.initRows || !lodash_1.default.isEqual(this.dataValue, this.emptyValue)) {\n this.createRows(true);\n }\n this.visibleColumns = {};\n this.prevHasAddButton = this.hasAddButton();\n this.checkColumns();\n }\n get dataValue() {\n const dataValue = super.dataValue;\n if (!dataValue || !Array.isArray(dataValue)) {\n return this.emptyValue;\n }\n return dataValue;\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get defaultSchema() {\n return DataGridComponent.schema();\n }\n get initEmpty() {\n return this.component.initEmpty || this.component.noFirstRow;\n }\n get initRows() {\n return this.builderMode || this.path === 'defaultValue' || !this.initEmpty;\n }\n get emptyValue() {\n return this.initEmpty ? [] : [{}];\n }\n get addAnotherPosition() {\n return lodash_1.default.get(this.component, 'addAnotherPosition', 'bottom');\n }\n get minLength() {\n if (this.hasRowGroups()) {\n return lodash_1.default.sum(this.getGroupSizes());\n }\n else {\n return lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n }\n get defaultValue() {\n const isBuilderMode = this.builderMode;\n const isEmptyInit = this.initEmpty;\n // Ensure we have one and only one row in builder mode.\n if (isBuilderMode || (isEmptyInit && !this.dataValue.length)) {\n return isEmptyInit && !isBuilderMode ? [] : [{}];\n }\n const value = super.defaultValue;\n let defaultValue;\n if (Array.isArray(value)) {\n defaultValue = value;\n }\n else if (value && (typeof value === 'object')) {\n defaultValue = [value];\n }\n else {\n defaultValue = this.emptyValue;\n }\n for (let dIndex = defaultValue.length; dIndex < this.minLength; dIndex++) {\n defaultValue.push({});\n }\n return defaultValue;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n lodash_1.default.each(this.refs[`${this.datagridKey}-addRow`], (button) => {\n button.disabled = disabled;\n });\n lodash_1.default.each(this.refs[`${this.datagridKey}-removeRow`], (button) => {\n button.disabled = disabled;\n });\n }\n get disabled() {\n return super.disabled;\n }\n get datagridKey() {\n return `datagrid-${this.key}`;\n }\n get allowReorder() {\n return !this.options.readOnly && lodash_1.default.get(this.component, 'reorder', false);\n }\n get iteratableRows() {\n return this.rows.map((row, index) => ({\n components: row,\n data: this.dataValue[index],\n }));\n }\n isEmpty(value = this.dataValue) {\n var _a;\n const isEmpty = super.isEmpty(value);\n if ((_a = this.components) === null || _a === void 0 ? void 0 : _a.length) {\n return this.components.reduce((isEmpty, component) => {\n return isEmpty && component.isEmpty();\n }, true);\n }\n return isEmpty;\n }\n /**\n * Split rows into chunks.\n * @param {Number[]} groups - array of numbers where each item is size of group\n * @param {Array<T>} rows - rows collection\n * @return {Array<T[]>}\n */\n getRowChunks(groups, rows) {\n const [, chunks] = groups.reduce(([startIndex, acc], size) => {\n const endIndex = startIndex + size;\n return [endIndex, [...acc, [startIndex, endIndex]]];\n }, [0, []]);\n return chunks.map(range => lodash_1.default.slice(rows, ...range));\n }\n /**\n * Create groups object.\n * Each key in object represents index of first row in group.\n * @return {Object}\n */\n getGroups() {\n const groups = lodash_1.default.get(this.component, 'rowGroups', []);\n const sizes = lodash_1.default.map(groups, 'numberOfRows').slice(0, -1);\n const indexes = sizes.reduce((groupIndexes, size) => {\n const last = groupIndexes[groupIndexes.length - 1];\n return groupIndexes.concat(last + size);\n }, [0]);\n return groups.reduce((gidxs, group, idx) => {\n return Object.assign(Object.assign({}, gidxs), { [indexes[idx]]: group });\n }, {});\n }\n /**\n * Retrun group sizes.\n * @return {Number[]}\n */\n getGroupSizes() {\n return lodash_1.default.map(lodash_1.default.get(this.component, 'rowGroups', []), 'numberOfRows');\n }\n hasRowGroups() {\n return lodash_1.default.get(this, 'component.enableRowGroups', false) && !this.builderMode;\n }\n totalRowsNumber(groups) {\n return lodash_1.default.sum(lodash_1.default.map(groups, 'numberOfRows'));\n }\n setStaticValue(n) {\n this.dataValue = lodash_1.default.range(n).map(() => ({}));\n }\n hasExtraColumn() {\n return (this.hasRemoveButtons() || this.canAddColumn);\n }\n hasRemoveButtons() {\n return !this.builderMode && !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n hasTopSubmit() {\n return this.hasAddButton() && ['top', 'both'].includes(this.addAnotherPosition);\n }\n hasBottomSubmit() {\n return this.hasAddButton() && ['bottom', 'both'].includes(this.addAnotherPosition);\n }\n get canAddColumn() {\n return this.builderMode;\n }\n render() {\n const columns = this.getColumns();\n let columnExtra = 0;\n const hasRemoveButtons = this.hasRemoveButtons();\n if (this.component.reorder) {\n columnExtra++;\n }\n if (hasRemoveButtons) {\n columnExtra++;\n }\n if (this.canAddColumn) {\n columnExtra++;\n }\n const colWidth = Math.floor(12 / (columns.length + columnExtra));\n return super.render(this.renderTemplate('datagrid', {\n rows: this.getRows(),\n columns: columns,\n groups: this.hasRowGroups() ? this.getGroups() : [],\n visibleColumns: this.visibleColumns,\n hasToggle: lodash_1.default.get(this, 'component.groupToggle', false),\n hasHeader: this.hasHeader(),\n hasExtraColumn: this.hasExtraColumn(),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons,\n hasTopSubmit: this.hasTopSubmit(),\n hasBottomSubmit: this.hasBottomSubmit(),\n hasGroups: this.hasRowGroups(),\n numColumns: columns.length + (this.hasExtraColumn() ? 1 : 0),\n datagridKey: this.datagridKey,\n allowReorder: this.allowReorder,\n builder: this.builderMode,\n canAddColumn: this.canAddColumn,\n tabIndex: this.tabIndex,\n placeholder: this.renderTemplate('builderPlaceholder', {\n position: this.componentComponents.length,\n }),\n colWidth: colWidth.toString()\n }));\n }\n getRows() {\n return this.rows.map(row => {\n const components = {};\n lodash_1.default.each(row, (col, key) => {\n components[key] = col.render();\n });\n return components;\n });\n }\n getColumns() {\n return this.columns.filter((comp) => {\n return (!this.visibleColumns.hasOwnProperty(comp.key) || this.visibleColumns[comp.key]);\n });\n }\n hasHeader() {\n return this.component.components.reduce((hasHeader, col) => {\n // If any of the components has a title and it isn't hidden, display the header.\n return hasHeader || ((col.label || col.title) && !col.hideLabel);\n }, false);\n }\n loadRefs(element, refs) {\n super.loadRefs(element, refs);\n if (refs['messageContainer'] === 'single') {\n const container = lodash_1.default.last(element.querySelectorAll('[ref=messageContainer]'));\n this.refs['messageContainer'] = container || this.refs['messageContainer'];\n }\n }\n attach(element) {\n this.loadRefs(element, {\n [`${this.datagridKey}-row`]: 'multiple',\n [`${this.datagridKey}-tbody`]: 'single',\n [`${this.datagridKey}-addRow`]: 'multiple',\n [`${this.datagridKey}-removeRow`]: 'multiple',\n [`${this.datagridKey}-group-header`]: 'multiple',\n [this.datagridKey]: 'multiple',\n 'messageContainer': 'single'\n });\n if (this.allowReorder) {\n this.refs[`${this.datagridKey}-row`].forEach((row, index) => {\n row.dragInfo = { index };\n });\n if (this.root.dragulaLib) {\n this.dragula = this.root.dragulaLib([this.refs[`${this.datagridKey}-tbody`]], {\n moves: (_draggedElement, _oldParent, clickedElement) => {\n const clickedElementKey = clickedElement.getAttribute('data-key');\n const oldParentKey = _oldParent.getAttribute('data-key');\n //Check if the clicked button belongs to that container, if false, it belongs to the nested container\n if (oldParentKey === clickedElementKey) {\n return clickedElement.classList.contains('formio-drag-button');\n }\n }\n }).on('drop', this.onReorder.bind(this));\n this.dragula.on('cloned', (el, original) => {\n if (el && el.children && original && original.children) {\n lodash_1.default.each(original.children, (child, index) => {\n const styles = getComputedStyle(child, null);\n if (styles.cssText !== '') {\n el.children[index].style.cssText = styles.cssText;\n }\n else {\n const cssText = Object.values(styles).reduce((css, propertyName) => {\n return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;\n }, '');\n el.children[index].style.cssText = cssText;\n }\n });\n }\n });\n }\n }\n this.refs[`${this.datagridKey}-addRow`].forEach((addButton) => {\n this.addEventListener(addButton, 'click', this.addRow.bind(this));\n });\n this.refs[`${this.datagridKey}-removeRow`].forEach((removeButton, index) => {\n this.addEventListener(removeButton, 'click', this.removeRow.bind(this, index));\n });\n if (this.hasRowGroups()) {\n this.refs.chunks = this.getRowChunks(this.getGroupSizes(), this.refs[`${this.datagridKey}-row`]);\n this.refs[`${this.datagridKey}-group-header`].forEach((header, index) => {\n this.addEventListener(header, 'click', () => this.toggleGroup(header, index));\n });\n }\n const columns = this.getColumns();\n const rowLength = columns.length;\n this.rows.forEach((row, rowIndex) => {\n let columnIndex = 0;\n columns.forEach((col) => {\n this.attachComponents(this.refs[this.datagridKey][(rowIndex * rowLength) + columnIndex], [this.rows[rowIndex][col.key]], this.getComponentsContainer());\n columnIndex++;\n });\n });\n return super.attach(element);\n }\n getComponentsContainer() {\n return this.component.components;\n }\n onReorder(element, _target, _source, sibling) {\n if (!element.dragInfo || (sibling && !sibling.dragInfo)) {\n console.warn('There is no Drag Info available for either dragged or sibling element');\n return;\n }\n const oldPosition = element.dragInfo.index;\n //should drop at next sibling position; no next sibling means drop to last position\n const newPosition = sibling ? sibling.dragInfo.index : this.dataValue.length;\n const movedBelow = newPosition > oldPosition;\n const dataValue = (0, utils_1.fastCloneDeep)(this.dataValue);\n const draggedRowData = dataValue[oldPosition];\n //insert element at new position\n dataValue.splice(newPosition, 0, draggedRowData);\n //remove element from old position (if was moved above, after insertion it's at +1 index)\n dataValue.splice(movedBelow ? oldPosition : oldPosition + 1, 1);\n //need to re-build rows to re-calculate indexes and other indexed fields for component instance (like rows for ex.)\n this.setValue(dataValue, { isReordered: true });\n this.rebuild();\n }\n focusOnNewRowElement(row) {\n Object.keys(row).find((key) => {\n const element = row[key].element;\n if (element) {\n const focusableElements = (0, utils_1.getFocusableElements)(element);\n if (focusableElements && focusableElements[0]) {\n focusableElements[0].focus();\n return true;\n }\n }\n return false;\n });\n }\n addRow() {\n const index = this.rows.length;\n // Handle length mismatch between rows and dataValue\n if (this.dataValue.length === index) {\n this.dataValue.push({});\n }\n let row;\n const dataValue = this.dataValue;\n const defaultValue = this.defaultValue;\n if (this.initEmpty && defaultValue[index]) {\n row = defaultValue[index];\n dataValue[index] = row;\n }\n else {\n row = dataValue[index];\n }\n this.rows[index] = this.createRowComponents(row, index);\n this.emit('dataGridAddRow', {\n component: this.component,\n row\n });\n this.checkConditions();\n this.triggerChange();\n this.redraw().then(() => {\n this.focusOnNewRowElement(this.rows[index]);\n });\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n var _a;\n if ((_a = component.options) === null || _a === void 0 ? void 0 : _a.name) {\n const newName = `[${this.key}][${rowIndex}]`;\n component.options.name = component.options.name.replace(`[${this.key}][${component.rowIndex}]`, newName);\n }\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n component.path = this.calculateComponentPath(component);\n });\n }\n updateRowsComponents(rowIndex) {\n this.rows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(Object.values(row), rowIndex + index);\n });\n }\n removeRow(index) {\n const makeEmpty = index === 0 && this.rows.length === 1;\n const flags = { isReordered: !makeEmpty, resetValue: makeEmpty };\n this.splice(index, flags);\n this.emit('dataGridDeleteRow', { index });\n const [row] = this.rows.splice(index, 1);\n this.removeRowComponents(row);\n this.updateRowsComponents(index);\n this.setValue(this.dataValue, flags);\n this.redraw();\n }\n removeRowComponents(row) {\n lodash_1.default.each(row, (component) => this.removeComponent(component));\n }\n getRowValues() {\n return this.dataValue;\n }\n setRowComponentsData(rowIndex, rowData) {\n lodash_1.default.each(this.rows[rowIndex], (component) => {\n component.data = rowData;\n });\n }\n createRows(init, rebuild) {\n let added = false;\n const rowValues = this.getRowValues();\n // Create any missing rows.\n rowValues.forEach((row, index) => {\n if (!rebuild && this.rows[index]) {\n this.setRowComponentsData(index, row);\n }\n else {\n if (this.rows[index]) {\n this.removeRowComponents(this.rows[index]);\n }\n this.rows[index] = this.createRowComponents(row, index);\n added = true;\n }\n });\n // Delete any extra rows.\n const removedRows = this.rows.splice(rowValues.length);\n const removed = !!removedRows.length;\n // Delete components of extra rows (to make sure that this.components contain only components of exisiting rows)\n if (removed) {\n removedRows.forEach(row => this.removeRowComponents(row));\n }\n if (!init && (added || removed)) {\n this.redraw();\n }\n return added;\n }\n createRowComponents(row, rowIndex) {\n const components = {};\n this.tabIndex = 0;\n this.component.components.map((col, colIndex) => {\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n let columnComponent;\n if (this.builderMode) {\n col.id = col.id + rowIndex;\n columnComponent = col;\n }\n else {\n columnComponent = Object.assign(Object.assign({}, col), { id: (col.id + rowIndex) });\n }\n const component = this.createComponent(columnComponent, options, row);\n component.parentDisabled = !!this.disabled;\n component.rowIndex = rowIndex;\n component.inDataGrid = true;\n if (columnComponent.tabindex &&\n parseInt(columnComponent.tabindex) > this.tabIndex) {\n this.tabIndex = parseInt(columnComponent.tabindex);\n }\n components[col.key] = component;\n });\n return components;\n }\n /**\n * Checks the validity of this datagrid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n if (!this.checkComponentValidity(data, dirty, row, { silentCheck })) {\n return false;\n }\n const isValid = this.checkRows('checkValidity', data, dirty, true, silentCheck);\n this.checkModal(isValid, dirty);\n return isValid;\n }\n checkColumns(data, flags = {}) {\n data = data || this.rootValue;\n let show = false;\n if (!this.rows || !this.rows.length) {\n return { rebuild: false, show: false };\n }\n if (this.builderMode) {\n return { rebuild: false, show: true };\n }\n const visibility = {};\n let logicRebuild = false;\n const dataValue = this.dataValue;\n this.rows.forEach((row, rowIndex) => {\n lodash_1.default.each(row, (col, key) => {\n if (col && (typeof col.checkConditions === 'function')) {\n const firstRowCheck = visibility[key] === undefined;\n visibility[key] = !!visibility[key] ||\n (col.checkConditions(data, flags, dataValue[rowIndex]) && col.type !== 'hidden');\n if (col.component.logic && firstRowCheck) {\n const compIndex = lodash_1.default.findIndex(this.columns, ['key', key]);\n const equalColumns = lodash_1.default.isEqualWith(this.columns[compIndex], col.component, (col1, col2, key) => {\n // Don't compare columns by their auto-generated ids.\n if (key === 'id') {\n return true;\n }\n });\n if (!equalColumns) {\n logicRebuild = true;\n this.columns[compIndex] = col.component;\n }\n }\n }\n });\n });\n const rebuild = !lodash_1.default.isEqual(visibility, this.visibleColumns) || logicRebuild;\n lodash_1.default.each(visibility, (col) => {\n show |= col;\n });\n this.visibleColumns = visibility;\n return { rebuild, show };\n }\n checkComponentConditions(data, flags, row) {\n const isVisible = this.visible;\n // If table isn't visible, don't bother calculating columns.\n if (!super.checkComponentConditions(data, flags, row)) {\n return false;\n }\n const { rebuild, show } = this.checkColumns(data, flags);\n // Check if a rebuild is needed or the visibility changes.\n if (rebuild || !isVisible) {\n this.createRows(false, rebuild);\n }\n // Return if this table should show.\n return show;\n }\n setValue(value, flags = {}) {\n if (!value) {\n this.dataValue = this.defaultValue;\n this.createRows();\n return false;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n this.createRows();\n value = [{}];\n }\n }\n // Make sure we always have at least one row.\n // NOTE: Removing this will break \"Public Configurations\" in portal. ;)\n if (value && !value.length && !this.initEmpty) {\n value.push({});\n }\n const isSettingSubmission = flags.fromSubmission && !lodash_1.default.isEqual(value, this.emptyValue);\n const changed = this.hasChanged(value, this.dataValue);\n this.dataValue = value;\n if (this.initRows || isSettingSubmission ||\n (Array.isArray(this.dataValue) && this.dataValue.length !== this.rows.length)) {\n if (!this.createRows() && changed) {\n this.redraw();\n }\n }\n if (this.componentModal && isSettingSubmission) {\n this.componentModal.setValue(value);\n }\n this.rows.forEach((row, rowIndex) => {\n if (value.length <= rowIndex) {\n return;\n }\n lodash_1.default.each(row, (col) => {\n col.rowIndex = rowIndex;\n this.setNestedValue(col, value[rowIndex], flags);\n });\n });\n this.updateOnChange(flags, changed);\n return changed;\n }\n restoreComponentsContext() {\n this.rows.forEach((row, index) => lodash_1.default.forIn(row, (component) => component.data = this.dataValue[index]));\n }\n getComponent(path, fn) {\n path = Array.isArray(path) ? path : [path];\n const [key, ...remainingPath] = path;\n let result = [];\n if (lodash_1.default.isNumber(key) && remainingPath.length) {\n const compKey = remainingPath.pop();\n result = this.rows[key][compKey];\n // If the component is inside a Layout Component, try to find it among all the row's components\n if (!result) {\n Object.entries(this.rows[key]).forEach(([, comp]) => {\n if ('getComponent' in comp) {\n const possibleResult = comp.getComponent([compKey], fn);\n if (possibleResult) {\n result = possibleResult;\n }\n }\n });\n }\n if (result && lodash_1.default.isFunction(fn)) {\n fn(result, this.getComponents());\n }\n if (remainingPath.length && 'getComponent' in result) {\n return result.getComponent(remainingPath, fn);\n }\n return result;\n }\n if (!lodash_1.default.isString(key)) {\n return result;\n }\n this.everyComponent((component, components) => {\n if (component.component.key === key) {\n let comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn);\n }\n else if (fn) {\n fn(component, components);\n }\n result = result.concat(comp);\n }\n });\n return result.length > 0 ? result : null;\n }\n toggleGroup(element, index) {\n element.classList.toggle('collapsed');\n lodash_1.default.each(this.refs.chunks[index], row => {\n row.classList.toggle('hidden');\n });\n }\n}\nexports[\"default\"] = DataGridComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/datagrid/DataGrid.js?");
|
|
5211
5211
|
|
|
5212
5212
|
/***/ }),
|
|
5213
5213
|
|
|
@@ -5251,7 +5251,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5251
5251
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5252
5252
|
|
|
5253
5253
|
"use strict";
|
|
5254
|
-
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 NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Alert_1 = __importDefault(__webpack_require__(/*! ../alert/Alert */ \"./lib/cjs/components/alert/Alert.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst components_1 = __webpack_require__(/*! @formio/bootstrap/components */ \"./node_modules/@formio/bootstrap/lib/cjs/templates/components/index.js\");\nconst EditRowState = {\n New: 'new',\n Editing: 'editing',\n Saved: 'saved',\n Viewing: 'viewing',\n Removed: 'removed',\n Draft: 'draft',\n};\nclass EditGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n type: 'editgrid',\n label: 'Edit Grid',\n key: 'editGrid',\n clearOnHide: true,\n input: true,\n tree: true,\n removeRow: 'Cancel',\n defaultOpen: false,\n openWhenEmpty: false,\n modal: false,\n components: [],\n inlineEdit: false,\n templates: {\n header: EditGridComponent.defaultHeaderTemplate,\n row: EditGridComponent.defaultRowTemplate,\n tableHeader: EditGridComponent.defaultTableHeaderTemplate,\n tableRow: EditGridComponent.defaultTableRowTemplate,\n footer: '',\n },\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Edit Grid',\n icon: 'tasks',\n group: 'data',\n documentation: '/userguide/form-building/data-components#edit-grid',\n showPreview: false,\n weight: 30,\n schema: EditGridComponent.schema(),\n };\n }\n static get defaultHeaderTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">{{ t(component.label) }}</div>\n {% } %}\n {% }) %}\n </div>`;\n }\n static get defaultTableHeaderTemplate() {\n return `\n <tr>\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">{{ component.label }}</td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">Actions</td>\n {% } %}\n </tr>\n `;\n }\n static get defaultRowTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">\n {{ isVisibleInRow(component) ? getView(component, row[component.key]) : ''}}\n </div>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <div class=\"col-sm-2\">\n <div class=\"btn-group pull-right\">\n <button class=\"btn btn-default btn-light btn-sm editRow\"><i class=\"{{ iconClass('edit') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </div>\n {% } %}\n </div>`;\n }\n static get defaultTableRowTemplate() {\n return `\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">\n {{ getView(component, row[component.key]) }}\n </td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">\n <div class=\"btn-group\">\n <button class=\"btn btn-default btn-light btn-sm editRow\" aria-label=\"{{ t('Edit row') }}\"><i class=\"{{ iconClass('edit') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\" aria-label=\"{{ t('Remove row') }}\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </td>\n {% } %}\n `;\n }\n get defaultDialogTemplate() {\n return `\n <h3 ref=\"dialogHeader\">${this.t('Do you want to clear data?')}</h3>\n <div style=\"display:flex; justify-content: flex-end;\">\n <button ref=\"dialogCancelButton\" class=\"btn btn-secondary\" aria-label=\"${this.t('Cancel')}\">${this.t('Cancel')}</button>\n <button ref=\"dialogYesButton\" class=\"btn btn-danger\" aria-label=\"${this.t('Yes, delete it')}\">${this.t('Yes, delete it')}</button>\n </div>\n `;\n }\n get defaultRowTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableRowTemplate\n : EditGridComponent.defaultRowTemplate;\n }\n get defaultHeaderTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableHeaderTemplate\n : EditGridComponent.defaultHeaderTemplate;\n }\n get rowTemplate() {\n let rowTemplate;\n if (utils_1.Evaluator.noeval) {\n rowTemplate = this.displayAsTable ?\n components_1.editgrid.tableRow\n : components_1.editgrid.row;\n }\n else {\n rowTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableRow', this.defaultRowTemplate)\n : lodash_1.default.get(this.component, 'templates.row', this.defaultRowTemplate);\n }\n return rowTemplate;\n }\n get headerTemplate() {\n let headerTemplate;\n if (utils_1.Evaluator.noeval) {\n headerTemplate = this.displayAsTable ?\n components_1.editgrid.tableHeader\n : components_1.editgrid.header;\n }\n else {\n headerTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableHeader', this.defaultHeaderTemplate)\n : lodash_1.default.get(this.component, 'templates.header', this.defaultHeaderTemplate);\n }\n return headerTemplate;\n }\n /**\n * Returns true if the component has nested components which don't trigger changes on the root level\n */ //\n get hasScopedChildren() {\n return !this.inlineEditMode;\n }\n get defaultSchema() {\n return EditGridComponent.schema();\n }\n get emptyValue() {\n return [];\n }\n get editgridKey() {\n return `editgrid-${this.key}`;\n }\n get rowRef() {\n return `${this.editgridKey}-row`;\n }\n get rowElements() {\n return this.refs[this.rowRef];\n }\n get rowRefs() {\n return this.refs[`editgrid-${this.component.key}-row`];\n }\n get addRowRef() {\n return `${this.editgridKey}-addRow`;\n }\n get addRowElements() {\n return this.refs[this.addRowRef];\n }\n get saveRowRef() {\n return `${this.editgridKey}-saveRow`;\n }\n get saveRowElements() {\n return this.refs[this.saveRowRef];\n }\n get cancelRowRef() {\n return `${this.editgridKey}-cancelRow`;\n }\n get cancelRowElements() {\n return this.refs[this.cancelRowRef];\n }\n get inlineEditMode() {\n return this.component.inlineEdit;\n }\n get saveEditMode() {\n return !this.inlineEditMode;\n }\n get minLength() {\n return this.builderMode ? 0 : lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n get data() {\n return this._data;\n }\n get dataValue() {\n return super.dataValue || [];\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get displayAsTable() {\n return this.component.displayAsTable;\n }\n set data(value) {\n this._data = value;\n const data = this.dataValue;\n (this.editRows || []).forEach((row, index) => {\n if (!data[index] && row.state !== EditRowState.New) {\n data[index] = {};\n }\n const rowData = data[index] || {};\n row.data = rowData;\n row.components.forEach((component) => {\n component.data = rowData;\n });\n });\n }\n get iteratableRows() {\n return this.editRows;\n }\n get defaultValue() {\n const value = super.defaultValue;\n const defaultValue = Array.isArray(value) ? value : [];\n lodash_1.default.times(this.minLength - defaultValue.length, () => defaultValue.push({}));\n return defaultValue;\n }\n constructor(...args) {\n super(...args);\n this.type = 'editgrid';\n }\n hasRemoveButtons() {\n return !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n init() {\n if (this.builderMode) {\n this.editRows = [];\n return super.init();\n }\n this.components = this.components || [];\n const dataValue = this.dataValue;\n const openWhenEmpty = !dataValue.length && this.component.openWhenEmpty;\n if (openWhenEmpty) {\n const dataObj = {};\n this.editRows = [];\n this.createRow(dataObj, 0);\n }\n else {\n this.editRows = dataValue.map((row, rowIndex) => ({\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n rowIndex,\n }));\n }\n this.prevHasAddButton = this.hasAddButton();\n this.checkData();\n this.setVariableTypeComponents();\n if (this.variableTypeComponentsIndexes.length) {\n lodash_1.default.each(this.editRows || [], (editRow, rowIndex) => this.checkRowVariableTypeComponents(editRow, rowIndex));\n }\n }\n checkRowVariableTypeComponents(editRow, rowIndex) {\n const rowComponents = editRow.components;\n if (lodash_1.default.some(this.variableTypeComponentsIndexes, (compIndex) => {\n const variableTypeComp = rowComponents[compIndex];\n return variableTypeComp.type !== variableTypeComp.component.type;\n })) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex, true);\n }\n }\n setVariableTypeComponents() {\n //set components which type is changing within a row (e.g.,by mergeComponentSchema action)\n this.variableTypeComponentsIndexes = [];\n lodash_1.default.each(this.component.components, (comp, index) => {\n if (comp.typeChangeEnabled) {\n this.variableTypeComponentsIndexes.push(index);\n }\n });\n }\n isOpen(editRow) {\n return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);\n }\n isComponentVisibleInSomeRow(component) {\n const rows = this.editRows;\n const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];\n const savedRows = rows.filter(row => lodash_1.default.includes(savedStates, row.state));\n this.visibleInHeader = this.visibleInHeader || [];\n const changeVisibleInHeader = (component, isVisible) => {\n if (!isVisible) {\n lodash_1.default.remove(this.visibleInHeader, (key) => key === component.key);\n }\n if (isVisible && !lodash_1.default.includes(this.visibleInHeader, component.key)) {\n this.visibleInHeader.push(component.key);\n }\n };\n if (lodash_1.default.isEmpty(rows)) {\n const rowComponents = this.createRowComponents({}, 0);\n let checkComponent;\n (0, utils_1.eachComponent)(rowComponents, (comp) => {\n if (comp.component.key === component.key) {\n checkComponent = comp;\n }\n comp.checkConditions();\n });\n const isVisible = checkComponent ? checkComponent.visible : true;\n [...this.components].forEach((comp) => this.removeComponent(comp, this.components));\n changeVisibleInHeader(component, isVisible);\n return isVisible;\n }\n const isOpenRowWhenEmpty = lodash_1.default.get(this.component, 'openWhenEmpty') && rows.length === 1 && rows[0].state === EditRowState.New;\n if (!lodash_1.default.isEmpty(rows) && lodash_1.default.isEmpty(savedRows) && !isOpenRowWhenEmpty) {\n return lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return lodash_1.default.some(isOpenRowWhenEmpty ? rows : savedRows, (row, index) => {\n const editingRow = row.state === EditRowState.Editing;\n let isVisible;\n if (!editingRow) {\n const flattenedComponents = this.flattenComponents(index);\n const instance = flattenedComponents[component.key];\n isVisible = instance ? instance.visible : true;\n changeVisibleInHeader(component, isVisible);\n }\n else {\n isVisible = lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return isVisible;\n });\n }\n render(children) {\n if (this.builderMode) {\n return super.render();\n }\n const dataValue = this.dataValue;\n const headerTemplate = this.headerTemplate;\n const t = this.t.bind(this);\n const templateName = this.displayAsTable ? 'editgridTable' : 'editgrid';\n return super.render(children || this.renderTemplate(templateName, {\n ref: {\n row: this.rowRef,\n addRow: this.addRowRef,\n saveRow: this.saveRowRef,\n cancelRow: this.cancelRowRef,\n },\n header: this.renderString(headerTemplate, {\n displayValue: (component) => this.displayComponentValue(component, true),\n components: this.component.components,\n value: dataValue,\n t\n }),\n footer: this.renderString(lodash_1.default.get(this.component, 'templates.footer'), {\n components: this.component.components,\n value: dataValue,\n t\n }),\n rows: this.editRows.map(this.renderRow.bind(this)),\n openRows: this.editRows.map((row) => this.isOpen(row)),\n errors: this.editRows.map((row) => row.error),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons: this.hasRemoveButtons(),\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n const templateName = this.displayAsTable && this.prevHasAddButton ? 'tableComponents' : 'components';\n return this.renderTemplate(templateName, {\n children,\n components,\n });\n }\n attach(element) {\n if (this.builderMode) {\n return super.attach(element);\n }\n this.loadRefs(element, {\n [this.addRowRef]: 'multiple',\n [this.saveRowRef]: 'multiple',\n [this.cancelRowRef]: 'multiple',\n [this.rowRef]: 'multiple',\n });\n this.addRowElements.forEach((addButton) => {\n this.addEventListener(addButton, 'click', () => this.addRow());\n });\n let openRowCount = 0;\n this.rowElements.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.isRowSelected) {\n row.classList.add('selected');\n }\n if (this.isOpen(editRow)) {\n this.attachComponents(row, editRow.components);\n this.addEventListener(this.saveRowElements[openRowCount], 'click', () => this.saveRow(rowIndex, true));\n this.addEventListener(this.cancelRowElements[openRowCount], 'click', () => this.cancelRow(rowIndex));\n openRowCount++;\n }\n else {\n // Attach edit and remove button events.\n [\n {\n className: 'removeRow',\n event: 'click',\n action: () => this.removeRow(rowIndex, true),\n },\n {\n className: 'editRow',\n event: 'click',\n action: () => {\n this.editRow(rowIndex).then(() => {\n var _a;\n if (this.component.rowDrafts) {\n this.validateRow(editRow, false);\n const hasErrors = editRow.errors && !!editRow.errors.length;\n const shouldShowRowErrorsAlert = this.component.modal && hasErrors && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted);\n if (shouldShowRowErrorsAlert) {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n }\n });\n },\n },\n {\n className: 'row',\n event: 'click',\n action: () => {\n row.classList.toggle('selected');\n let eventName = 'editGridSelectRow';\n if (Array.from(row.classList).includes('selected')) {\n editRow.isRowSelected = true;\n }\n else {\n delete editRow.isRowSelected;\n eventName = 'editGridUnSelectRow';\n }\n this.emit(eventName, {\n component: this.component,\n data: this.dataValue[rowIndex]\n });\n },\n }\n ].forEach(({ className, event, action, }) => {\n const elements = row.getElementsByClassName(className);\n Array.prototype.forEach.call(elements, (element) => {\n if (this.options.pdf && lodash_1.default.intersection(element.classList, ['editRow', 'removeRow']).length) {\n element.style.display = 'none';\n }\n else {\n this.addEventListener(element, event, action);\n }\n });\n });\n }\n });\n // Add open class to the element if any edit grid row is open\n if (openRowCount) {\n this.addClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n else {\n this.removeClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n messageContainer: 'single-scope',\n });\n return superAttach;\n }\n flattenRowDataValue(dataValue) {\n const flattened = {};\n Object.keys(dataValue).forEach((key) => {\n if (lodash_1.default.isObject(dataValue[key]) && !lodash_1.default.isNil(dataValue[key])) {\n Object.assign(flattened, this.flattenRowDataValue(dataValue[key]));\n }\n else {\n flattened[key] = dataValue[key];\n }\n });\n return flattened;\n }\n isComponentVisibleInRow(component, flattenedComponents) {\n const instance = flattenedComponents[component.key];\n return instance ? instance.visible : true;\n }\n displayComponentValue(component, header) {\n return !!((!component.hasOwnProperty('tableView') || component.tableView)\n && header ? this.isComponentVisibleInSomeRow(component) : lodash_1.default.includes(this.visibleInHeader, component.key));\n }\n renderRow(row, rowIndex) {\n const dataValue = this.dataValue;\n if (this.isOpen(row)) {\n return this.renderComponents(row.components);\n }\n else {\n const flattenedComponents = this.flattenComponents(rowIndex);\n const rowTemplate = this.rowTemplate;\n return this.renderString(rowTemplate, {\n row: dataValue[rowIndex] || {},\n data: this.data,\n rowIndex,\n components: this.component.components,\n flattenedComponents,\n displayValue: (component) => this.displayComponentValue(component),\n isVisibleInRow: (component) => this.isComponentVisibleInRow(component, flattenedComponents),\n getView: (component, data) => {\n var _a, _b;\n const instance = flattenedComponents[component.key];\n const view = instance ? instance.getView(data || instance.dataValue) : '';\n // If there is an html tag in view, don't allow it to be injected in template\n const htmlTagRegExp = new RegExp('<(.*?)>');\n return typeof view === 'string' && view.length && !((_a = instance.component) === null || _a === void 0 ? void 0 : _a.template) && htmlTagRegExp.test(view) && ((_b = instance.component) === null || _b === void 0 ? void 0 : _b.inputFormat) !== 'html'\n ? `<input type=\"text\" value=\"${view.replace(/\"/g, '"')}\" readonly/>`\n : view;\n },\n state: this.editRows[rowIndex].state,\n t: this.t.bind(this)\n });\n }\n }\n eachComponent(fn, rowIndex) {\n lodash_1.default.each(this.getComponents(rowIndex), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => {\n var _a;\n const rowData = this.dataValue[component.rowIndex];\n const editRowData = (_a = this.editRows[component.rowIndex]) === null || _a === void 0 ? void 0 : _a.data;\n component.data = rowData || editRowData;\n });\n }\n flattenComponents(rowIndex) {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n }, rowIndex);\n return result;\n }\n getComponents(rowIndex) {\n var _a;\n // Ensure editrows is set.\n this.editRows = this.editRows || [];\n return this.builderMode\n ? super.getComponents()\n : lodash_1.default.isNumber(rowIndex)\n ? (((_a = this.editRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.components) || [])\n : this.editRows.reduce((result, row) => result.concat(row.components || []), []);\n }\n destroy(all = false) {\n this.calculatedValue = undefined;\n super.destroy(all);\n }\n destroyComponents(all = false, rowIndex = 0) {\n if (this.builderMode) {\n return super.destroyComponents(all);\n }\n const components = this.getComponents(rowIndex).slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n }\n createRow(dataObj, rowIndex) {\n const editRow = {\n components: this.createRowComponents(dataObj, rowIndex),\n data: dataObj,\n state: EditRowState.New,\n backup: null,\n error: null,\n rowIndex,\n };\n this.editRows.push(editRow);\n if (this.inlineEditMode) {\n this.dataValue.push(dataObj);\n }\n return editRow;\n }\n addRow() {\n if (this.options.readOnly) {\n return;\n }\n const dataObj = {};\n const rowIndex = this.editRows.length;\n const editRow = this.createRow(dataObj, rowIndex);\n if (editRow.state === EditRowState.New) {\n this.emptyRow = (0, utils_1.fastCloneDeep)(editRow.data);\n }\n if (this.inlineEditMode) {\n this.triggerChange();\n }\n this.emit('editGridAddRow', {\n component: this.component,\n row: editRow,\n });\n this.checkRow('checkData', null, {}, editRow.data, editRow.components);\n if (this.component.modal) {\n this.addRowModal(rowIndex);\n }\n else {\n this.redraw();\n }\n return editRow;\n }\n addRowModal(rowIndex) {\n const modalContent = this.ce('div');\n const editRow = this.editRows[rowIndex];\n editRow.willBeSaved = false;\n const { components } = editRow;\n modalContent.innerHTML = this.renderComponents(components);\n const dialog = this.component.modal ? this.createModal(modalContent, {}, () => this.showDialog(rowIndex)) : undefined;\n dialog.classList.add(`editgrid-row-modal-${this.id}`);\n editRow.dialog = dialog;\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n this.alert = new Alert_1.default(dialog.refs.dialogContents, this);\n this.addEventListener(dialog, 'close', () => {\n if (!editRow.willBeSaved) {\n if (this.editRows[rowIndex] && this.editRows[rowIndex].state !== EditRowState.New) {\n this.editRows[rowIndex].components.forEach((comp) => {\n comp.setPristine(true);\n });\n }\n this.cancelRow(rowIndex);\n }\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n // Remove references to dialog elements to prevent possible in some cases memory leaks\n delete editRow.confirmationDialog;\n delete editRow.dialog;\n });\n dialog.refs.dialogContents.appendChild(this.ce('button', {\n class: 'btn btn-primary',\n onClick: () => {\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n if (this.validateRow(editRow, true) || this.component.rowDrafts) {\n editRow.willBeSaved = true;\n dialog.close();\n this.saveRow(rowIndex, true);\n }\n else {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n },\n }, this.component.saveRow || 'Save'));\n return this.attachComponents(modalContent, components);\n }\n showDialog(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow.state === EditRowState.New ? lodash_1.default.isEqual(this.emptyRow, editRow.data) : lodash_1.default.isEqual(editRow.backup, editRow.data)) {\n return Promise.resolve();\n }\n const wrapper = this.ce('div', { ref: 'confirmationDialog' });\n const dialogContent = this.component.dialogTemplate || this.defaultDialogTemplate;\n wrapper.innerHTML = dialogContent;\n wrapper.refs = {};\n this.loadRefs.call(wrapper, wrapper, {\n dialogHeader: 'single',\n dialogCancelButton: 'single',\n dialogYesButton: 'single',\n });\n const dialog = this.createModal(wrapper);\n dialog.classList.add(`editgrid-row-modal-confirmation-${this.id}`);\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n let dialogResult;\n const promise = new Promise((resolve, reject) => {\n dialogResult = { resolve, reject };\n });\n this.addEventListener(wrapper.refs.dialogYesButton, 'click', (event) => {\n close(event);\n dialogResult.resolve();\n });\n this.addEventListener(wrapper.refs.dialogCancelButton, 'click', (event) => {\n close(event);\n dialogResult.reject();\n });\n editRow.confirmationDialog = dialog;\n return promise;\n }\n editRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n const isAlreadyEditing = editRow.state === EditRowState.Editing || editRow.state === EditRowState.New;\n if (!editRow || isAlreadyEditing) {\n return Promise.resolve();\n }\n editRow.prevState = editRow.state;\n editRow.state = this.options.readOnly ? EditRowState.Viewing : EditRowState.Editing;\n if (this.lazyLoad && (editRow.components.length === 0)) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex);\n }\n const dataSnapshot = (0, utils_1.fastCloneDeep)(editRow.data);\n if (this.inlineEditMode) {\n editRow.backup = dataSnapshot;\n }\n else {\n editRow.backup = (0, utils_1.fastCloneDeep)(editRow.data);\n editRow.data = dataSnapshot;\n this.restoreRowContext(editRow);\n }\n if (this.component.modal) {\n return this.addRowModal(rowIndex);\n }\n return this.redraw();\n }\n clearErrors(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow && Array.isArray(editRow.components)) {\n editRow.components.forEach((comp) => {\n comp.setPristine(true);\n comp.setCustomValidity('');\n });\n }\n }\n cancelRow(rowIndex) {\n if (this.options.readOnly) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n switch (editRow.state) {\n case EditRowState.New: {\n editRow.state = EditRowState.Removed;\n this.clearErrors(rowIndex);\n this.destroyComponents(false, rowIndex);\n if (this.inlineEditMode) {\n this.splice(rowIndex);\n }\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n break;\n }\n case EditRowState.Editing: {\n editRow.state = editRow.prevState;\n if (this.inlineEditMode) {\n this.dataValue[rowIndex] = editRow.backup;\n }\n editRow.data = editRow.backup;\n editRow.backup = null;\n this.restoreRowContext(editRow);\n this.clearErrors(rowIndex);\n break;\n }\n }\n this.emit('editGridCancelRow', {\n instance: this,\n component: this.component,\n editRow,\n });\n this.checkValidity(null, true);\n this.redraw();\n if (this.component.rowDrafts) {\n this.checkValidity(this.data, false);\n }\n }\n saveRow(rowIndex, modified) {\n var _a, _b;\n const editRow = this.editRows[rowIndex];\n if (this.options.readOnly) {\n return;\n }\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const isRowValid = this.validateRow(editRow, true);\n if (!this.component.rowDrafts) {\n if (!isRowValid) {\n return false;\n }\n }\n if (this.saveEditMode) {\n const dataValue = this.dataValue;\n if ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.component.typeChangeEnabled) {\n this.root.focusedComponent = null;\n }\n switch (editRow.state) {\n case EditRowState.New: {\n const newIndex = dataValue.length;\n dataValue.push(editRow.data);\n editRow.components.forEach(component => component.rowIndex = newIndex);\n if (rowIndex !== newIndex) {\n this.editRows.splice(rowIndex, 1);\n this.editRows.splice(newIndex, 0, editRow);\n }\n break;\n }\n case EditRowState.Editing: {\n dataValue[rowIndex] = editRow.data;\n break;\n }\n }\n }\n editRow.state = this.component.rowDrafts && !isRowValid ? EditRowState.Draft : EditRowState.Saved;\n editRow.backup = null;\n this.updateValue();\n this.emit('editGridSaveRow', {\n component: this.component,\n row: editRow.data,\n instance: this\n });\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n if (this.component.rowDrafts) {\n editRow.components.forEach(comp => comp.setPristine(this.pristine));\n }\n this.checkValidity(null, true);\n this.redraw();\n if (editRow.alerts) {\n editRow.alerts = false;\n }\n return true;\n }\n beforeFocus(component) {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n const relativePath = this.getRelativePath(component.path);\n const arrayPath = (0, utils_1.getArrayFromComponentPath)(relativePath);\n const rowIndex = arrayPath[0];\n let rowToEditIndex = arrayPath[0];\n this.editRows.forEach((row, indexInArray) => {\n if (row.rowIndex === rowIndex) {\n rowToEditIndex = indexInArray;\n }\n });\n if (lodash_1.default.isNumber(rowToEditIndex)) {\n this.editRow(rowToEditIndex);\n }\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n });\n }\n updateRowsComponents(rowIndex) {\n this.editRows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(row.components, rowIndex + index);\n });\n }\n baseRemoveRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n editRow.state = EditRowState.Removed;\n this.destroyComponents(false, rowIndex);\n return editRow;\n }\n removeRow(rowIndex, modified) {\n if (this.options.readOnly) {\n return;\n }\n this.clearErrors(rowIndex);\n this.baseRemoveRow(rowIndex);\n this.splice(rowIndex);\n this.emit('editGridDeleteRow', {\n index: rowIndex\n });\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n this.updateRowsComponents(rowIndex);\n this.updateValue();\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n this.checkValidity(null, true);\n this.checkData();\n this.redraw();\n }\n createRowComponents(row, rowIndex, recreatePartially) {\n // Iterate through existing components and destroy the ones with the same rowIndex.\n if (this.components) {\n for (let i = 0; i < this.components.length; i++) {\n if (this.components[i].rowIndex === rowIndex) {\n this.components[i].destroy();\n this.components.splice(i, 1);\n }\n }\n }\n const currentRowComponents = lodash_1.default.get(this.editRows, `[${rowIndex}].components`, null);\n return this.component.components.map((col, colIndex) => {\n var _a;\n if (recreatePartially && currentRowComponents && this.variableTypeComponentsIndexes.length) {\n const currentComp = currentRowComponents[colIndex];\n const shouldRecreate = lodash_1.default.includes(this.variableTypeComponentsIndexes, colIndex) && (currentComp === null || currentComp === void 0 ? void 0 : currentComp.type) !== ((_a = currentComp === null || currentComp === void 0 ? void 0 : currentComp.component) === null || _a === void 0 ? void 0 : _a.type);\n if (!shouldRecreate) {\n return currentComp;\n }\n col = currentComp.component;\n }\n const column = lodash_1.default.clone(col);\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n options.onChange = (flags = {}, changed, modified) => {\n var _a, _b;\n if (((_a = changed.instance.root) === null || _a === void 0 ? void 0 : _a.id) && (((_b = this.root) === null || _b === void 0 ? void 0 : _b.id) !== changed.instance.root.id)) {\n changed.instance.root.triggerChange(flags, changed, modified);\n }\n else if (!this.component.modal) {\n this.triggerRootChange(flags, changed, modified);\n }\n if (this.inlineEditMode) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.alerts) {\n this.checkData(null, Object.assign(Object.assign({}, flags), { changed,\n rowIndex }), this.data);\n }\n else if (editRow) {\n // If drafts allowed, perform validation silently if there was no attempt to submit a form\n const silentCheck = this.component.rowDrafts && !this.shouldValidateDraft(editRow);\n this.checkRow('checkData', null, Object.assign(Object.assign({}, flags), { changed,\n silentCheck }), editRow.data, editRow.components, silentCheck);\n }\n if (this.variableTypeComponentsIndexes.length) {\n this.checkRowVariableTypeComponents(editRow, rowIndex);\n this.redraw();\n }\n };\n const comp = this.createComponent(lodash_1.default.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);\n comp.rowIndex = rowIndex;\n comp.inEditGrid = true;\n return comp;\n });\n }\n hasOpenRows() {\n return this.editRows.some(row => this.isOpen(row));\n }\n shouldValidateDraft(editRow) {\n var _a, _b;\n // Draft rows should be validated only when there was an attempt to submit a form\n return (editRow.state === EditRowState.Draft &&\n !this.pristine &&\n !((_a = this.root) === null || _a === void 0 ? void 0 : _a.pristine) &&\n !this.hasOpenRows()) ||\n ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted);\n }\n shouldValidateRow(editRow, dirty) {\n return this.shouldValidateDraft(editRow) ||\n editRow.state === EditRowState.Editing ||\n editRow.alerts ||\n dirty;\n }\n validateRow(editRow, dirty, forceSilentCheck) {\n var _a;\n let valid = true;\n const errorsSnapshot = [...this.errors];\n if (this.shouldValidateRow(editRow, dirty)) {\n editRow.components.forEach(comp => {\n const silentCheck = (this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck;\n valid &= comp.checkValidity(null, dirty, null, silentCheck);\n });\n }\n if (this.component.validate && this.component.validate.row) {\n valid = this.evaluate(this.component.validate.row, {\n valid,\n row: editRow.data\n }, 'valid', true);\n if (valid.toString() !== 'true') {\n editRow.error = valid;\n valid = false;\n }\n else {\n editRow.error = null;\n }\n if (valid === null) {\n valid = `Invalid row validation for ${this.key}`;\n }\n }\n editRow.errors = !valid ? this.errors.filter((err) => !errorsSnapshot.includes(err)) : null;\n if (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted)) {\n this.showRowErrorAlerts(editRow, !!valid);\n }\n return !!valid;\n }\n showRowErrorAlerts(editRow, valid) {\n var _a;\n if (editRow.alerts) {\n if (this.alert) {\n if (((_a = editRow.errors) === null || _a === void 0 ? void 0 : _a.length) && !valid) {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n else {\n this.alert.clear();\n }\n }\n }\n }\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n return this.checkComponentValidity(data, dirty, row, { silentCheck });\n }\n checkComponentValidity(data, dirty, row, options = {}) {\n var _a, _b, _c;\n const { silentCheck } = options;\n const errorsLength = this.errors.length;\n const superValid = super.checkComponentValidity(data, dirty, row, options);\n // If super tells us that component invalid and there is no need to update alerts, just return false\n if (!superValid && (!this.alert && !this.hasOpenRows())) {\n return false;\n }\n if (this.shouldSkipValidation(data, dirty, row)) {\n return true;\n }\n let rowsValid = true;\n let rowsEditing = false;\n this.editRows.forEach((editRow, index) => {\n // Trigger all errors on the row.\n const rowValid = this.validateRow(editRow, dirty, silentCheck);\n rowsValid &= rowValid;\n if (this.rowRefs) {\n const rowContainer = this.rowRefs[index];\n if (rowContainer) {\n const errorContainer = rowContainer.querySelector('.editgrid-row-error');\n if (!rowValid && errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n }\n // If this is a dirty check, and any rows are still editing, we need to throw validation error.\n rowsEditing |= (dirty && this.isOpen(editRow));\n });\n if (!rowsValid) {\n if (!silentCheck && (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted))) {\n this.setCustomValidity(this.t(this.errorMessage('invalidRowsError')), dirty);\n // Delete this class, because otherwise all the components inside EditGrid will has red border even if they are valid\n this.removeClass(this.element, 'has-error');\n }\n return false;\n }\n else if (rowsEditing && this.saveEditMode) {\n this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);\n return false;\n }\n const message = this.invalid || this.invalidMessage(data, dirty);\n if (((_b = this.errors) === null || _b === void 0 ? void 0 : _b.length) !== errorsLength && ((_c = this.root) === null || _c === void 0 ? void 0 : _c.submitted) && !message) {\n this.setCustomValidity(message, dirty);\n this.root.showErrors();\n }\n else {\n this.setCustomValidity(message, dirty);\n }\n return superValid;\n }\n changeState(changed, flags) {\n if (changed || (flags.resetValue && this.component.modalEdit)) {\n this.rebuild();\n }\n else {\n this.redraw();\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n value = this.defaultValue;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n return false;\n }\n }\n const changed = this.hasChanged(value, this.dataValue);\n flags.noValidate = !changed;\n if (this.parent && !(this.options.server && !this.parent.parentVisible)) {\n this.parent.checkComponentConditions();\n }\n this.dataValue = value;\n // Refresh editRow data when data changes.\n this.dataValue.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n editRow.data = row;\n this.restoreRowContext(editRow, flags);\n editRow.state = EditRowState.Saved;\n editRow.backup = null;\n editRow.error = null;\n }\n else {\n this.editRows[rowIndex] = {\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n };\n }\n });\n let { length: dataLength } = this.dataValue;\n // If the last row is a new row, then do not remove it.\n if (this.editRows[dataLength] && (this.editRows[dataLength].state === EditRowState.New)) {\n dataLength = (dataLength + 1);\n }\n this.editRows.slice(dataLength).forEach((editRow, index) => this.baseRemoveRow(dataLength + index));\n this.editRows = this.editRows.slice(0, dataLength);\n this.openWhenEmpty();\n this.updateOnChange(flags, changed);\n this.checkData();\n this.changeState(changed, flags);\n return changed;\n }\n openWhenEmpty() {\n const shouldBeOpened = !this.dataValue.length && this.component.openWhenEmpty;\n const hasNoRows = !this.editRows.length;\n if (hasNoRows && shouldBeOpened && !this.builderMode) {\n const dataObj = {};\n this.createRow(dataObj, 0);\n }\n }\n restoreRowContext(editRow, flags = {}) {\n editRow.components.forEach((component) => {\n component.data = editRow.data;\n this.setNestedValue(component, editRow.data, flags);\n });\n }\n emptyRows() {\n this.editRows.forEach((editRow, index) => this.destroyComponents(false, index));\n this.editRows = [];\n }\n resetValue() {\n super.resetValue();\n this.emptyRows();\n }\n}\nexports[\"default\"] = EditGridComponent;\nEditGridComponent.prototype.hasChanged = Component_1.default.prototype.hasChanged;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/editgrid/EditGrid.js?");
|
|
5254
|
+
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 NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Alert_1 = __importDefault(__webpack_require__(/*! ../alert/Alert */ \"./lib/cjs/components/alert/Alert.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst components_1 = __webpack_require__(/*! @formio/bootstrap/components */ \"./node_modules/@formio/bootstrap/lib/cjs/templates/components/index.js\");\nconst EditRowState = {\n New: 'new',\n Editing: 'editing',\n Saved: 'saved',\n Viewing: 'viewing',\n Removed: 'removed',\n Draft: 'draft',\n};\nclass EditGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n type: 'editgrid',\n label: 'Edit Grid',\n key: 'editGrid',\n clearOnHide: true,\n input: true,\n tree: true,\n removeRow: 'Cancel',\n defaultOpen: false,\n openWhenEmpty: false,\n modal: false,\n components: [],\n inlineEdit: false,\n templates: {\n header: EditGridComponent.defaultHeaderTemplate,\n row: EditGridComponent.defaultRowTemplate,\n tableHeader: EditGridComponent.defaultTableHeaderTemplate,\n tableRow: EditGridComponent.defaultTableRowTemplate,\n footer: '',\n },\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Edit Grid',\n icon: 'tasks',\n group: 'data',\n documentation: '/userguide/form-building/data-components#edit-grid',\n showPreview: false,\n weight: 30,\n schema: EditGridComponent.schema(),\n };\n }\n static get defaultHeaderTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">{{ t(component.label) }}</div>\n {% } %}\n {% }) %}\n </div>`;\n }\n static get defaultTableHeaderTemplate() {\n return `\n <tr>\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">{{ component.label }}</td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">Actions</td>\n {% } %}\n </tr>\n `;\n }\n static get defaultRowTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">\n {{ isVisibleInRow(component) ? getView(component, row[component.key]) : ''}}\n </div>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <div class=\"col-sm-2\">\n <div class=\"btn-group pull-right\">\n <button class=\"btn btn-default btn-light btn-sm editRow\"><i class=\"{{ iconClass('edit') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </div>\n {% } %}\n </div>`;\n }\n static get defaultTableRowTemplate() {\n return `\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">\n {{ getView(component, row[component.key]) }}\n </td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">\n <div class=\"btn-group\">\n <button class=\"btn btn-default btn-light btn-sm editRow\" aria-label=\"{{ t('Edit row') }}\"><i class=\"{{ iconClass('edit') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\" aria-label=\"{{ t('Remove row') }}\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </td>\n {% } %}\n `;\n }\n get defaultDialogTemplate() {\n return `\n <h3 ref=\"dialogHeader\">${this.t('Do you want to clear data?')}</h3>\n <div style=\"display:flex; justify-content: flex-end;\">\n <button ref=\"dialogCancelButton\" class=\"btn btn-secondary\" aria-label=\"${this.t('Cancel')}\">${this.t('Cancel')}</button>\n <button ref=\"dialogYesButton\" class=\"btn btn-danger\" aria-label=\"${this.t('Yes, delete it')}\">${this.t('Yes, delete it')}</button>\n </div>\n `;\n }\n get defaultRowTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableRowTemplate\n : EditGridComponent.defaultRowTemplate;\n }\n get defaultHeaderTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableHeaderTemplate\n : EditGridComponent.defaultHeaderTemplate;\n }\n get rowTemplate() {\n let rowTemplate;\n if (utils_1.Evaluator.noeval) {\n rowTemplate = this.displayAsTable ?\n components_1.editgrid.tableRow\n : components_1.editgrid.row;\n }\n else {\n rowTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableRow', this.defaultRowTemplate)\n : lodash_1.default.get(this.component, 'templates.row', this.defaultRowTemplate);\n }\n return rowTemplate;\n }\n get headerTemplate() {\n let headerTemplate;\n if (utils_1.Evaluator.noeval) {\n headerTemplate = this.displayAsTable ?\n components_1.editgrid.tableHeader\n : components_1.editgrid.header;\n }\n else {\n headerTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableHeader', this.defaultHeaderTemplate)\n : lodash_1.default.get(this.component, 'templates.header', this.defaultHeaderTemplate);\n }\n return headerTemplate;\n }\n /**\n * Returns true if the component has nested components which don't trigger changes on the root level\n */ //\n get hasScopedChildren() {\n return !this.inlineEditMode;\n }\n get defaultSchema() {\n return EditGridComponent.schema();\n }\n get emptyValue() {\n return [];\n }\n get editgridKey() {\n return `editgrid-${this.key}`;\n }\n get rowRef() {\n return `${this.editgridKey}-row`;\n }\n get rowElements() {\n return this.refs[this.rowRef];\n }\n get rowRefs() {\n return this.refs[`editgrid-${this.component.key}-row`];\n }\n get addRowRef() {\n return `${this.editgridKey}-addRow`;\n }\n get addRowElements() {\n return this.refs[this.addRowRef];\n }\n get saveRowRef() {\n return `${this.editgridKey}-saveRow`;\n }\n get saveRowElements() {\n return this.refs[this.saveRowRef];\n }\n get cancelRowRef() {\n return `${this.editgridKey}-cancelRow`;\n }\n get cancelRowElements() {\n return this.refs[this.cancelRowRef];\n }\n get inlineEditMode() {\n return this.component.inlineEdit;\n }\n get saveEditMode() {\n return !this.inlineEditMode;\n }\n get minLength() {\n return this.builderMode ? 0 : lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n get data() {\n return this._data;\n }\n get dataValue() {\n return super.dataValue || [];\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get displayAsTable() {\n return this.component.displayAsTable;\n }\n set data(value) {\n this._data = value;\n const data = this.dataValue;\n (this.editRows || []).forEach((row, index) => {\n if (!data[index] && row.state !== EditRowState.New) {\n data[index] = {};\n }\n const rowData = data[index] || {};\n row.data = rowData;\n row.components.forEach((component) => {\n component.data = rowData;\n });\n });\n }\n get iteratableRows() {\n return this.editRows;\n }\n get defaultValue() {\n const value = super.defaultValue;\n const defaultValue = Array.isArray(value) ? value : [];\n lodash_1.default.times(this.minLength - defaultValue.length, () => defaultValue.push({}));\n return defaultValue;\n }\n constructor(...args) {\n super(...args);\n this.type = 'editgrid';\n }\n hasRemoveButtons() {\n return !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n init() {\n if (this.builderMode) {\n this.editRows = [];\n return super.init();\n }\n this.components = this.components || [];\n const dataValue = this.dataValue;\n const openWhenEmpty = !dataValue.length && this.component.openWhenEmpty;\n if (openWhenEmpty) {\n const dataObj = {};\n this.editRows = [];\n this.createRow(dataObj, 0);\n }\n else {\n this.editRows = dataValue.map((row, rowIndex) => ({\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n rowIndex,\n }));\n }\n this.prevHasAddButton = this.hasAddButton();\n this.checkData();\n this.setVariableTypeComponents();\n if (this.variableTypeComponentsIndexes.length) {\n lodash_1.default.each(this.editRows || [], (editRow, rowIndex) => this.checkRowVariableTypeComponents(editRow, rowIndex));\n }\n }\n checkRowVariableTypeComponents(editRow, rowIndex) {\n const rowComponents = editRow.components;\n if (lodash_1.default.some(this.variableTypeComponentsIndexes, (compIndex) => {\n const variableTypeComp = rowComponents[compIndex];\n return variableTypeComp.type !== variableTypeComp.component.type;\n })) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex, true);\n }\n }\n setVariableTypeComponents() {\n //set components which type is changing within a row (e.g.,by mergeComponentSchema action)\n this.variableTypeComponentsIndexes = [];\n lodash_1.default.each(this.component.components, (comp, index) => {\n if (comp.typeChangeEnabled) {\n this.variableTypeComponentsIndexes.push(index);\n }\n });\n }\n isOpen(editRow) {\n return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);\n }\n isComponentVisibleInSomeRow(component) {\n const rows = this.editRows;\n const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];\n const savedRows = rows.filter(row => lodash_1.default.includes(savedStates, row.state));\n this.visibleInHeader = this.visibleInHeader || [];\n const changeVisibleInHeader = (component, isVisible) => {\n if (!isVisible) {\n lodash_1.default.remove(this.visibleInHeader, (key) => key === component.key);\n }\n if (isVisible && !lodash_1.default.includes(this.visibleInHeader, component.key)) {\n this.visibleInHeader.push(component.key);\n }\n };\n if (lodash_1.default.isEmpty(rows)) {\n const rowComponents = this.createRowComponents({}, 0);\n let checkComponent;\n (0, utils_1.eachComponent)(rowComponents, (comp) => {\n if (comp.component.key === component.key) {\n checkComponent = comp;\n }\n comp.checkConditions();\n });\n const isVisible = checkComponent ? checkComponent.visible : true;\n [...this.components].forEach((comp) => this.removeComponent(comp, this.components));\n changeVisibleInHeader(component, isVisible);\n return isVisible;\n }\n const isOpenRowWhenEmpty = lodash_1.default.get(this.component, 'openWhenEmpty') && rows.length === 1 && rows[0].state === EditRowState.New;\n if (!lodash_1.default.isEmpty(rows) && lodash_1.default.isEmpty(savedRows) && !isOpenRowWhenEmpty) {\n return lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return lodash_1.default.some(isOpenRowWhenEmpty ? rows : savedRows, (row, index) => {\n const editingRow = row.state === EditRowState.Editing;\n let isVisible;\n if (!editingRow) {\n const flattenedComponents = this.flattenComponents(index);\n const instance = flattenedComponents[component.key];\n isVisible = instance ? instance.visible : true;\n changeVisibleInHeader(component, isVisible);\n }\n else {\n isVisible = lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return isVisible;\n });\n }\n render(children) {\n if (this.builderMode) {\n return super.render();\n }\n const dataValue = this.dataValue;\n const headerTemplate = this.headerTemplate;\n const t = this.t.bind(this);\n const templateName = this.displayAsTable ? 'editgridTable' : 'editgrid';\n return super.render(children || this.renderTemplate(templateName, {\n ref: {\n row: this.rowRef,\n addRow: this.addRowRef,\n saveRow: this.saveRowRef,\n cancelRow: this.cancelRowRef,\n },\n header: this.renderString(headerTemplate, {\n displayValue: (component) => this.displayComponentValue(component, true),\n components: this.component.components,\n value: dataValue,\n t\n }),\n footer: this.renderString(lodash_1.default.get(this.component, 'templates.footer'), {\n components: this.component.components,\n value: dataValue,\n t\n }),\n rows: this.editRows.map(this.renderRow.bind(this)),\n openRows: this.editRows.map((row) => this.isOpen(row)),\n errors: this.editRows.map((row) => row.error),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons: this.hasRemoveButtons(),\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n const templateName = this.displayAsTable && this.prevHasAddButton ? 'tableComponents' : 'components';\n return this.renderTemplate(templateName, {\n children,\n components,\n });\n }\n attach(element) {\n if (this.builderMode) {\n return super.attach(element);\n }\n this.loadRefs(element, {\n [this.addRowRef]: 'multiple',\n [this.saveRowRef]: 'multiple',\n [this.cancelRowRef]: 'multiple',\n [this.rowRef]: 'multiple',\n });\n this.addRowElements.forEach((addButton) => {\n this.addEventListener(addButton, 'click', () => this.addRow());\n });\n let openRowCount = 0;\n this.rowElements.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.isRowSelected) {\n row.classList.add('selected');\n }\n if (this.isOpen(editRow)) {\n this.attachComponents(row, editRow.components);\n this.addEventListener(this.saveRowElements[openRowCount], 'click', () => this.saveRow(rowIndex, true));\n this.addEventListener(this.cancelRowElements[openRowCount], 'click', () => this.cancelRow(rowIndex));\n openRowCount++;\n }\n else {\n // Attach edit and remove button events.\n [\n {\n className: 'removeRow',\n event: 'click',\n action: () => this.removeRow(rowIndex, true),\n },\n {\n className: 'editRow',\n event: 'click',\n action: () => {\n this.editRow(rowIndex).then(() => {\n var _a;\n if (this.component.rowDrafts) {\n this.validateRow(editRow, false);\n const hasErrors = editRow.errors && !!editRow.errors.length;\n const shouldShowRowErrorsAlert = this.component.modal && hasErrors && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted);\n if (shouldShowRowErrorsAlert) {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n }\n });\n },\n },\n {\n className: 'row',\n event: 'click',\n action: () => {\n row.classList.toggle('selected');\n let eventName = 'editGridSelectRow';\n if (Array.from(row.classList).includes('selected')) {\n editRow.isRowSelected = true;\n }\n else {\n delete editRow.isRowSelected;\n eventName = 'editGridUnSelectRow';\n }\n this.emit(eventName, {\n component: this.component,\n data: this.dataValue[rowIndex]\n });\n },\n }\n ].forEach(({ className, event, action, }) => {\n const elements = row.getElementsByClassName(className);\n Array.prototype.forEach.call(elements, (element) => {\n if (this.options.pdf && lodash_1.default.intersection(element.classList, ['editRow', 'removeRow']).length) {\n element.style.display = 'none';\n }\n else {\n this.addEventListener(element, event, action);\n }\n });\n });\n }\n });\n // Add open class to the element if any edit grid row is open\n if (openRowCount) {\n this.addClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n else {\n this.removeClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n messageContainer: 'single-scope',\n });\n return superAttach;\n }\n flattenRowDataValue(dataValue) {\n const flattened = {};\n Object.keys(dataValue).forEach((key) => {\n if (lodash_1.default.isObject(dataValue[key]) && !lodash_1.default.isNil(dataValue[key])) {\n Object.assign(flattened, this.flattenRowDataValue(dataValue[key]));\n }\n else {\n flattened[key] = dataValue[key];\n }\n });\n return flattened;\n }\n isComponentVisibleInRow(component, flattenedComponents) {\n const instance = flattenedComponents[component.key];\n return instance ? instance.visible : true;\n }\n displayComponentValue(component, header) {\n return !!((!component.hasOwnProperty('tableView') || component.tableView)\n && header ? this.isComponentVisibleInSomeRow(component) : lodash_1.default.includes(this.visibleInHeader, component.key));\n }\n renderRow(row, rowIndex) {\n const dataValue = this.dataValue;\n if (this.isOpen(row)) {\n return this.renderComponents(row.components);\n }\n else {\n const flattenedComponents = this.flattenComponents(rowIndex);\n const rowTemplate = this.rowTemplate;\n return this.renderString(rowTemplate, {\n row: dataValue[rowIndex] || {},\n data: this.data,\n rowIndex,\n components: this.component.components,\n flattenedComponents,\n displayValue: (component) => this.displayComponentValue(component),\n isVisibleInRow: (component) => this.isComponentVisibleInRow(component, flattenedComponents),\n getView: (component, data) => {\n var _a, _b;\n const instance = flattenedComponents[component.key];\n const view = instance ? instance.getView(data || instance.dataValue) : '';\n // If there is an html tag in view, don't allow it to be injected in template\n const htmlTagRegExp = new RegExp('<(.*?)>');\n return typeof view === 'string' && view.length && !((_a = instance.component) === null || _a === void 0 ? void 0 : _a.template) && htmlTagRegExp.test(view) && ((_b = instance.component) === null || _b === void 0 ? void 0 : _b.inputFormat) !== 'html'\n ? `<input type=\"text\" value=\"${view.replace(/\"/g, '"')}\" readonly/>`\n : view;\n },\n state: this.editRows[rowIndex].state,\n t: this.t.bind(this)\n });\n }\n }\n eachComponent(fn, rowIndex) {\n lodash_1.default.each(this.getComponents(rowIndex), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => {\n var _a;\n const rowData = this.dataValue[component.rowIndex];\n const editRowData = (_a = this.editRows[component.rowIndex]) === null || _a === void 0 ? void 0 : _a.data;\n component.data = rowData || editRowData;\n });\n }\n flattenComponents(rowIndex) {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n }, rowIndex);\n return result;\n }\n getComponents(rowIndex) {\n var _a;\n // Ensure editrows is set.\n this.editRows = this.editRows || [];\n return this.builderMode\n ? super.getComponents()\n : lodash_1.default.isNumber(rowIndex)\n ? (((_a = this.editRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.components) || [])\n : this.editRows.reduce((result, row) => result.concat(row.components || []), []);\n }\n destroy(all = false) {\n this.calculatedValue = undefined;\n super.destroy(all);\n }\n destroyComponents(all = false, rowIndex = 0) {\n if (this.builderMode) {\n return super.destroyComponents(all);\n }\n const components = this.getComponents(rowIndex).slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n }\n createRow(dataObj, rowIndex) {\n const editRow = {\n components: this.createRowComponents(dataObj, rowIndex),\n data: dataObj,\n state: EditRowState.New,\n backup: null,\n error: null,\n rowIndex,\n };\n this.editRows.push(editRow);\n if (this.inlineEditMode) {\n this.dataValue.push(dataObj);\n }\n return editRow;\n }\n addRow() {\n if (this.options.readOnly) {\n return;\n }\n const dataObj = {};\n const rowIndex = this.editRows.length;\n const editRow = this.createRow(dataObj, rowIndex);\n if (editRow.state === EditRowState.New) {\n this.emptyRow = (0, utils_1.fastCloneDeep)(editRow.data);\n }\n if (this.inlineEditMode) {\n this.triggerChange();\n }\n this.emit('editGridAddRow', {\n component: this.component,\n row: editRow,\n });\n this.checkRow('checkData', null, {}, editRow.data, editRow.components);\n if (this.component.modal) {\n this.addRowModal(rowIndex);\n }\n else {\n this.redraw();\n }\n return editRow;\n }\n addRowModal(rowIndex) {\n const modalContent = this.ce('div');\n const editRow = this.editRows[rowIndex];\n editRow.willBeSaved = false;\n const { components } = editRow;\n modalContent.innerHTML = this.renderComponents(components);\n const dialog = this.component.modal ? this.createModal(modalContent, {}, () => this.showDialog(rowIndex)) : undefined;\n dialog.classList.add(`editgrid-row-modal-${this.id}`);\n editRow.dialog = dialog;\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n this.alert = new Alert_1.default(dialog.refs.dialogContents, this);\n this.addEventListener(dialog, 'close', () => {\n if (!editRow.willBeSaved) {\n if (this.editRows[rowIndex] && this.editRows[rowIndex].state !== EditRowState.New) {\n this.editRows[rowIndex].components.forEach((comp) => {\n comp.setPristine(true);\n });\n }\n this.cancelRow(rowIndex);\n }\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n // Remove references to dialog elements to prevent possible in some cases memory leaks\n delete editRow.confirmationDialog;\n delete editRow.dialog;\n });\n dialog.refs.dialogContents.appendChild(this.ce('button', {\n class: 'btn btn-primary',\n onClick: () => {\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n if (this.validateRow(editRow, true) || this.component.rowDrafts) {\n editRow.willBeSaved = true;\n dialog.close();\n this.saveRow(rowIndex, true);\n }\n else {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n },\n }, this.component.saveRow || 'Save'));\n return this.attachComponents(modalContent, components);\n }\n showDialog(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow.state === EditRowState.New ? lodash_1.default.isEqual(this.emptyRow, editRow.data) : lodash_1.default.isEqual(editRow.backup, editRow.data)) {\n return Promise.resolve();\n }\n const wrapper = this.ce('div', { ref: 'confirmationDialog' });\n const dialogContent = this.component.dialogTemplate || this.defaultDialogTemplate;\n wrapper.innerHTML = dialogContent;\n wrapper.refs = {};\n this.loadRefs.call(wrapper, wrapper, {\n dialogHeader: 'single',\n dialogCancelButton: 'single',\n dialogYesButton: 'single',\n });\n const dialog = this.createModal(wrapper);\n dialog.classList.add(`editgrid-row-modal-confirmation-${this.id}`);\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n let dialogResult;\n const promise = new Promise((resolve, reject) => {\n dialogResult = { resolve, reject };\n });\n this.addEventListener(wrapper.refs.dialogYesButton, 'click', (event) => {\n close(event);\n dialogResult.resolve();\n });\n this.addEventListener(wrapper.refs.dialogCancelButton, 'click', (event) => {\n close(event);\n dialogResult.reject();\n });\n editRow.confirmationDialog = dialog;\n return promise;\n }\n editRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n const isAlreadyEditing = editRow.state === EditRowState.Editing || editRow.state === EditRowState.New;\n if (!editRow || isAlreadyEditing) {\n return Promise.resolve();\n }\n editRow.prevState = editRow.state;\n editRow.state = this.options.readOnly ? EditRowState.Viewing : EditRowState.Editing;\n if (this.lazyLoad && (editRow.components.length === 0)) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex);\n }\n const dataSnapshot = (0, utils_1.fastCloneDeep)(editRow.data);\n if (this.inlineEditMode) {\n editRow.backup = dataSnapshot;\n }\n else {\n editRow.backup = (0, utils_1.fastCloneDeep)(editRow.data);\n editRow.data = dataSnapshot;\n this.restoreRowContext(editRow);\n }\n if (this.component.modal) {\n return this.addRowModal(rowIndex);\n }\n return this.redraw();\n }\n clearErrors(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow && Array.isArray(editRow.components)) {\n editRow.components.forEach((comp) => {\n comp.setPristine(true);\n comp.setCustomValidity('');\n });\n }\n }\n cancelRow(rowIndex) {\n if (this.options.readOnly) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n switch (editRow.state) {\n case EditRowState.New: {\n editRow.state = EditRowState.Removed;\n this.clearErrors(rowIndex);\n this.destroyComponents(false, rowIndex);\n if (this.inlineEditMode) {\n this.splice(rowIndex);\n }\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n break;\n }\n case EditRowState.Editing: {\n editRow.state = editRow.prevState;\n if (this.inlineEditMode) {\n this.dataValue[rowIndex] = editRow.backup;\n }\n editRow.data = editRow.backup;\n editRow.backup = null;\n this.restoreRowContext(editRow);\n this.clearErrors(rowIndex);\n break;\n }\n }\n this.emit('editGridCancelRow', {\n instance: this,\n component: this.component,\n editRow,\n });\n this.checkValidity(null, true);\n this.redraw();\n if (this.component.rowDrafts) {\n this.checkValidity(this.data, false);\n }\n }\n saveRow(rowIndex, modified) {\n var _a, _b;\n const editRow = this.editRows[rowIndex];\n if (this.options.readOnly) {\n return;\n }\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const isRowValid = this.validateRow(editRow, true);\n if (!this.component.rowDrafts) {\n if (!isRowValid) {\n return false;\n }\n }\n if (this.saveEditMode) {\n const dataValue = this.dataValue;\n if ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.component.typeChangeEnabled) {\n this.root.focusedComponent = null;\n }\n switch (editRow.state) {\n case EditRowState.New: {\n const newIndex = dataValue.length;\n dataValue.push(editRow.data);\n editRow.components.forEach(component => component.rowIndex = newIndex);\n if (rowIndex !== newIndex) {\n this.editRows.splice(rowIndex, 1);\n this.editRows.splice(newIndex, 0, editRow);\n }\n break;\n }\n case EditRowState.Editing: {\n dataValue[rowIndex] = editRow.data;\n break;\n }\n }\n }\n editRow.state = this.component.rowDrafts && !isRowValid ? EditRowState.Draft : EditRowState.Saved;\n editRow.backup = null;\n this.updateValue();\n this.emit('editGridSaveRow', {\n component: this.component,\n row: editRow.data,\n instance: this\n });\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n if (this.component.rowDrafts) {\n editRow.components.forEach(comp => comp.setPristine(this.pristine));\n }\n this.checkValidity(null, true);\n this.redraw();\n if (editRow.alerts) {\n editRow.alerts = false;\n }\n return true;\n }\n beforeFocus(component) {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n const relativePath = this.getRelativePath(component.path);\n const arrayPath = (0, utils_1.getArrayFromComponentPath)(relativePath);\n const rowIndex = arrayPath[0];\n let rowToEditIndex = arrayPath[0];\n this.editRows.forEach((row, indexInArray) => {\n if (row.rowIndex === rowIndex) {\n rowToEditIndex = indexInArray;\n }\n });\n if (lodash_1.default.isNumber(rowToEditIndex)) {\n this.editRow(rowToEditIndex);\n }\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n });\n }\n updateRowsComponents(rowIndex) {\n this.editRows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(row.components, rowIndex + index);\n });\n }\n baseRemoveRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n editRow.state = EditRowState.Removed;\n this.destroyComponents(false, rowIndex);\n return editRow;\n }\n removeRow(rowIndex, modified) {\n if (this.options.readOnly) {\n return;\n }\n this.clearErrors(rowIndex);\n this.baseRemoveRow(rowIndex);\n this.splice(rowIndex);\n this.emit('editGridDeleteRow', {\n index: rowIndex\n });\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n this.updateRowsComponents(rowIndex);\n this.updateValue();\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n this.checkValidity(null, true);\n this.checkData();\n this.redraw();\n }\n createRowComponents(row, rowIndex, recreatePartially) {\n // Iterate through existing components and destroy the ones with the same rowIndex.\n if (this.components) {\n for (let i = 0; i < this.components.length; i++) {\n if (this.components[i].rowIndex === rowIndex) {\n this.components[i].destroy();\n this.components.splice(i, 1);\n }\n }\n }\n const currentRowComponents = lodash_1.default.get(this.editRows, `[${rowIndex}].components`, null);\n return this.component.components.map((col, colIndex) => {\n var _a;\n if (recreatePartially && currentRowComponents && this.variableTypeComponentsIndexes.length) {\n const currentComp = currentRowComponents[colIndex];\n const shouldRecreate = lodash_1.default.includes(this.variableTypeComponentsIndexes, colIndex) && (currentComp === null || currentComp === void 0 ? void 0 : currentComp.type) !== ((_a = currentComp === null || currentComp === void 0 ? void 0 : currentComp.component) === null || _a === void 0 ? void 0 : _a.type);\n if (!shouldRecreate) {\n return currentComp;\n }\n col = currentComp.component;\n }\n const column = lodash_1.default.clone(col);\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n options.onChange = (flags = {}, changed, modified) => {\n var _a, _b;\n if (((_a = changed.instance.root) === null || _a === void 0 ? void 0 : _a.id) && (((_b = this.root) === null || _b === void 0 ? void 0 : _b.id) !== changed.instance.root.id)) {\n changed.instance.root.triggerChange(flags, changed, modified);\n }\n else if (!this.component.modal) {\n this.triggerRootChange(flags, changed, modified);\n }\n if (this.inlineEditMode) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.alerts) {\n this.checkData(null, Object.assign(Object.assign({}, flags), { changed,\n rowIndex }), this.data);\n }\n else if (editRow) {\n // If drafts allowed, perform validation silently if there was no attempt to submit a form\n const silentCheck = this.component.rowDrafts && !this.shouldValidateDraft(editRow);\n this.checkRow('checkData', null, Object.assign(Object.assign({}, flags), { changed,\n silentCheck }), editRow.data, editRow.components, silentCheck);\n }\n if (this.variableTypeComponentsIndexes.length) {\n this.checkRowVariableTypeComponents(editRow, rowIndex);\n this.redraw();\n }\n };\n const comp = this.createComponent(lodash_1.default.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);\n comp.rowIndex = rowIndex;\n comp.inEditGrid = true;\n return comp;\n });\n }\n hasOpenRows() {\n return this.editRows.some(row => this.isOpen(row));\n }\n shouldValidateDraft(editRow) {\n var _a, _b;\n // Draft rows should be validated only when there was an attempt to submit a form\n return (editRow.state === EditRowState.Draft &&\n !this.pristine &&\n !((_a = this.root) === null || _a === void 0 ? void 0 : _a.pristine) &&\n !this.hasOpenRows()) ||\n ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted);\n }\n shouldValidateRow(editRow, dirty) {\n return this.shouldValidateDraft(editRow) ||\n editRow.state === EditRowState.Editing ||\n editRow.alerts ||\n dirty;\n }\n validateRow(editRow, dirty, forceSilentCheck) {\n var _a;\n let valid = true;\n const errorsSnapshot = [...this.errors];\n if (this.shouldValidateRow(editRow, dirty)) {\n editRow.components.forEach(comp => {\n const silentCheck = (this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck;\n valid &= comp.checkValidity(null, dirty, null, silentCheck);\n });\n }\n if (this.component.validate && this.component.validate.row) {\n valid = this.evaluate(this.component.validate.row, {\n valid,\n row: editRow.data\n }, 'valid', true);\n if (valid.toString() !== 'true') {\n editRow.error = valid;\n valid = false;\n }\n else {\n editRow.error = null;\n }\n if (valid === null) {\n valid = `Invalid row validation for ${this.key}`;\n }\n }\n editRow.errors = !valid ? this.errors.filter((err) => !errorsSnapshot.includes(err)) : null;\n if (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted)) {\n this.showRowErrorAlerts(editRow, !!valid);\n }\n return !!valid;\n }\n showRowErrorAlerts(editRow, valid) {\n var _a;\n if (editRow.alerts) {\n if (this.alert) {\n if (((_a = editRow.errors) === null || _a === void 0 ? void 0 : _a.length) && !valid) {\n this.alert.showErrors(editRow.errors, false);\n editRow.alerts = true;\n }\n else {\n this.alert.clear();\n }\n }\n }\n }\n checkValidity(data, dirty, row, silentCheck) {\n data = data || this.rootValue;\n row = row || this.data;\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n return this.checkComponentValidity(data, dirty, row, { silentCheck });\n }\n checkComponentValidity(data, dirty, row, options = {}) {\n var _a, _b, _c;\n const { silentCheck } = options;\n const errorsLength = this.errors.length;\n const superValid = super.checkComponentValidity(data, dirty, row, options);\n // If super tells us that component invalid and there is no need to update alerts, just return false\n if (!superValid && (!this.alert && !this.hasOpenRows())) {\n return false;\n }\n if (this.shouldSkipValidation(data, dirty, row)) {\n return true;\n }\n let rowsValid = true;\n let rowsEditing = false;\n this.editRows.forEach((editRow, index) => {\n // Trigger all errors on the row.\n const rowValid = this.validateRow(editRow, dirty, silentCheck);\n rowsValid &= rowValid;\n if (this.rowRefs) {\n const rowContainer = this.rowRefs[index];\n if (rowContainer) {\n const errorContainer = rowContainer.querySelector('.editgrid-row-error');\n if (!rowValid && errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n }\n // If this is a dirty check, and any rows are still editing, we need to throw validation error.\n rowsEditing |= (dirty && this.isOpen(editRow));\n });\n if (!rowsValid) {\n if (!silentCheck && (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted))) {\n this.setCustomValidity(this.t(this.errorMessage('invalidRowsError')), dirty);\n // Delete this class, because otherwise all the components inside EditGrid will has red border even if they are valid\n this.removeClass(this.element, 'has-error');\n }\n return false;\n }\n else if (rowsEditing && this.saveEditMode && !this.component.openWhenEmpty) {\n this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);\n return false;\n }\n const message = this.invalid || this.invalidMessage(data, dirty);\n if (((_b = this.errors) === null || _b === void 0 ? void 0 : _b.length) !== errorsLength && ((_c = this.root) === null || _c === void 0 ? void 0 : _c.submitted) && !message) {\n this.setCustomValidity(message, dirty);\n this.root.showErrors();\n }\n else {\n this.setCustomValidity(message, dirty);\n }\n return superValid;\n }\n changeState(changed, flags) {\n if (this.visible && (changed || (flags.resetValue && this.component.modalEdit))) {\n this.rebuild();\n }\n else {\n this.redraw();\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n value = this.defaultValue;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n return false;\n }\n }\n const changed = this.hasChanged(value, this.dataValue);\n flags.noValidate = !changed;\n if (this.parent && !this.options.server) {\n this.parent.checkComponentConditions();\n }\n this.dataValue = value;\n // Refresh editRow data when data changes.\n this.dataValue.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n editRow.data = row;\n this.restoreRowContext(editRow, flags);\n editRow.state = EditRowState.Saved;\n editRow.backup = null;\n editRow.error = null;\n }\n else {\n this.editRows[rowIndex] = {\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n };\n }\n });\n let { length: dataLength } = this.dataValue;\n // If the last row is a new row, then do not remove it.\n if (this.editRows[dataLength] && (this.editRows[dataLength].state === EditRowState.New)) {\n dataLength = (dataLength + 1);\n }\n this.editRows.slice(dataLength).forEach((editRow, index) => this.baseRemoveRow(dataLength + index));\n this.editRows = this.editRows.slice(0, dataLength);\n this.openWhenEmpty();\n this.updateOnChange(flags, changed);\n // do not call checkData with server option, it is called when change is triggered in updateOnChange\n if (!this.options.server) {\n this.checkData();\n }\n this.changeState(changed, flags);\n return changed;\n }\n openWhenEmpty() {\n const shouldBeOpened = !this.dataValue.length && this.component.openWhenEmpty;\n const hasNoRows = !this.editRows.length;\n if (hasNoRows && shouldBeOpened && !this.builderMode) {\n const dataObj = {};\n this.createRow(dataObj, 0);\n }\n }\n restoreRowContext(editRow, flags = {}) {\n editRow.components.forEach((component) => {\n component.data = editRow.data;\n this.setNestedValue(component, editRow.data, flags);\n });\n }\n emptyRows() {\n this.editRows.forEach((editRow, index) => this.destroyComponents(false, index));\n this.editRows = [];\n }\n resetValue() {\n super.resetValue();\n this.emptyRows();\n }\n}\nexports[\"default\"] = EditGridComponent;\nEditGridComponent.prototype.hasChanged = Component_1.default.prototype.hasChanged;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/editgrid/EditGrid.js?");
|
|
5255
5255
|
|
|
5256
5256
|
/***/ }),
|
|
5257
5257
|
|
|
@@ -5317,7 +5317,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5317
5317
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5318
5318
|
|
|
5319
5319
|
"use strict";
|
|
5320
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass HTMLComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n label: 'HTML',\n type: 'htmlelement',\n tag: 'p',\n attrs: [],\n content: '',\n input: false,\n persistent: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'HTML Element',\n group: 'layout',\n icon: 'code',\n weight: 0,\n documentation: '/userguide/form-building/layout-components#html-element',\n showPreview: false,\n schema: HTMLComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n get defaultSchema() {\n return HTMLComponent.schema();\n }\n get content() {\n if (this.builderMode) {\n return this.component.content;\n }\n // i18n returns error exactly with word 'select', spaces will be trimmed\n if (this.component.content.replace(/(<(\\/?[^>]+)>)/g, '').trim() === 'select') {\n return ` ${this.component.content} `;\n }\n const submission = lodash_1.default.get(this.root, 'submission', {});\n const content = this.component.content ? this.interpolate(this.component.content, {\n metadata: submission.metadata || {},\n submission: submission,\n data: this.rootValue,\n row: this.data\n }) : '';\n return this.sanitize(content, this.shouldSanitizeValue);\n }\n get singleTags() {\n return ['br', 'img', 'hr'];\n }\n checkRefreshOn(changed) {\n super.checkRefreshOn(changed);\n if (!this.builderMode && this.component.refreshOnChange && this.element &&\n !lodash_1.default.isUndefined(changed) && ((lodash_1.default.isBoolean(changed) && changed) || !lodash_1.default.isEmpty(changed)) &&\n this.conditionallyVisible(this.data, this.row)) {\n this.setContent(this.element, this.renderContent());\n }\n }\n renderContent() {\n const submission = lodash_1.default.get(this.root, 'submission', {});\n return this.renderTemplate('html', {\n component: this.component,\n tag: this.component.tag,\n attrs: (this.component.attrs || []).map((attr) => {\n return {\n attr: attr.attr,\n value: this.interpolate(attr.value, {\n metadata: submission.metadata || {},\n submission: submission,\n data: this.rootValue,\n row: this.data\n })\n };\n }),\n content: this.content,\n singleTags: this.singleTags,\n });\n }\n render() {\n return super.render(this.renderContent());\n }\n attach(element) {\n this.loadRefs(element, { html: 'single' });\n return super.attach(element);\n }\n}\nexports[\"default\"] = HTMLComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/html/HTML.js?");
|
|
5320
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass HTMLComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n label: 'HTML',\n type: 'htmlelement',\n tag: 'p',\n attrs: [],\n content: '',\n input: false,\n persistent: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'HTML Element',\n group: 'layout',\n icon: 'code',\n weight: 0,\n documentation: '/userguide/form-building/layout-components#html-element',\n showPreview: false,\n schema: HTMLComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n get defaultSchema() {\n return HTMLComponent.schema();\n }\n get content() {\n if (this.builderMode) {\n return this.component.content;\n }\n // i18n returns error exactly with word 'select', spaces will be trimmed\n if (this.component.content.replace(/(<(\\/?[^>]+)>)/g, '').trim() === 'select') {\n return ` ${this.component.content} `;\n }\n const submission = lodash_1.default.get(this.root, 'submission', {});\n const content = this.component.content ? this.interpolate(this.component.content, {\n metadata: submission.metadata || {},\n submission: submission,\n data: this.rootValue,\n row: this.data\n }) : '';\n return this.sanitize(content, this.shouldSanitizeValue);\n }\n get singleTags() {\n return ['br', 'img', 'hr'];\n }\n checkRefreshOn(changed) {\n super.checkRefreshOn(changed);\n if (!this.builderMode && this.component.refreshOnChange && this.element &&\n !lodash_1.default.isUndefined(changed) && ((lodash_1.default.isBoolean(changed) && changed) || !lodash_1.default.isEmpty(changed)) &&\n this.conditionallyVisible(this.data, this.row)) {\n this.setContent(this.element, this.renderContent());\n }\n }\n renderContent() {\n const submission = lodash_1.default.get(this.root, 'submission', {});\n return this.renderTemplate('html', {\n component: this.component,\n tag: this.component.tag,\n attrs: (this.component.attrs || []).map((attr) => {\n return {\n attr: attr.attr,\n value: this.interpolate(attr.value, {\n metadata: submission.metadata || {},\n submission: submission,\n data: this.rootValue,\n row: this.data\n })\n };\n }),\n content: this.content,\n singleTags: this.singleTags,\n });\n }\n render() {\n return super.render(this.renderContent());\n }\n get dataReady() {\n var _a;\n return ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submissionReady) || Promise.resolve();\n }\n attach(element) {\n this.loadRefs(element, { html: 'single' });\n this.dataReady.then(() => {\n if (this.element) {\n this.setContent(this.elemet, this.content);\n }\n });\n return super.attach(element);\n }\n}\nexports[\"default\"] = HTMLComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/html/HTML.js?");
|
|
5321
5321
|
|
|
5322
5322
|
/***/ }),
|
|
5323
5323
|
|
|
@@ -5394,7 +5394,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5394
5394
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5395
5395
|
|
|
5396
5396
|
"use strict";
|
|
5397
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/*globals grecaptcha*/\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst get_1 = __importDefault(__webpack_require__(/*! lodash/get */ \"./node_modules/lodash/get.js\"));\nconst debounce_1 = __importDefault(__webpack_require__(/*! lodash/debounce */ \"./node_modules/lodash/debounce.js\"));\nclass ReCaptchaComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n type: 'recaptcha',\n key: 'recaptcha',\n label: 'reCAPTCHA'\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'reCAPTCHA',\n group: 'premium',\n icon: 'refresh',\n documentation: '/userguide/form-building/premium-components#recaptcha',\n weight: 40,\n schema: ReCaptchaComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n render() {\n this.recaptchaResult = null;\n if (this.builderMode) {\n return super.render('reCAPTCHA');\n }\n else {\n return super.render('', true);\n }\n }\n createInput() {\n if (this.builderMode) {\n // We need to see it in builder mode.\n this.append(this.text(this.name));\n }\n else {\n const siteKey = (0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey');\n if (siteKey) {\n const recaptchaApiScriptUrl = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;\n this.recaptchaApiReady = Formio_1.Formio.requireLibrary('googleRecaptcha', 'grecaptcha', recaptchaApiScriptUrl, true);\n }\n else {\n console.warn('There is no Site Key specified in settings in form JSON');\n }\n }\n }\n createLabel() {\n return;\n }\n get skipInEmail() {\n return true;\n }\n verify(actionName) {\n const siteKey = (0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey');\n if (!siteKey) {\n console.warn('There is no Site Key specified in settings in form JSON');\n return;\n }\n if (!this.recaptchaApiReady) {\n const recaptchaApiScriptUrl = `https://www.google.com/recaptcha/api.js?render=${(0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey')}`;\n this.recaptchaApiReady = Formio_1.Formio.requireLibrary('googleRecaptcha', 'grecaptcha', recaptchaApiScriptUrl, true);\n }\n if (this.recaptchaApiReady) {\n this.recaptchaVerifiedPromise = new Promise((resolve, reject) => {\n this.recaptchaApiReady\n .then(() => {\n if (!this.isLoading) {\n this.isLoading = true;\n grecaptcha.ready((0, debounce_1.default)(() => {\n grecaptcha\n .execute(siteKey, {\n action: actionName\n })\n .then((token) => {\n return this.sendVerificationRequest(token).then(({ verificationResult, token }) => {\n this.recaptchaResult = Object.assign(Object.assign({}, verificationResult), { token });\n this.updateValue(this.recaptchaResult);\n return resolve(verificationResult);\n });\n })\n .catch(() => {\n this.isLoading = false;\n });\n }, 1000));\n }\n })\n .catch(() => {\n return reject();\n });\n }).then(() => {\n this.isLoading = false;\n });\n }\n }\n beforeSubmit() {\n if (this.recaptchaVerifiedPromise) {\n return this.recaptchaVerifiedPromise\n .then(() => super.beforeSubmit());\n }\n return super.beforeSubmit();\n }\n sendVerificationRequest(token) {\n return Formio_1.Formio.makeStaticRequest(`${Formio_1.Formio.projectUrl}/recaptcha?recaptchaToken=${token}`)\n .then((verificationResult) => ({ verificationResult, token }));\n }\n checkComponentValidity(data, dirty, row, options = {}) {\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false } = options;\n // Verification could be async only\n if (!async) {\n return super.checkComponentValidity(data, dirty, row, options);\n }\n const componentData = row[this.component.key];\n if (!componentData || !componentData.token) {\n this.setCustomValidity('
|
|
5397
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/*globals grecaptcha*/\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst get_1 = __importDefault(__webpack_require__(/*! lodash/get */ \"./node_modules/lodash/get.js\"));\nconst debounce_1 = __importDefault(__webpack_require__(/*! lodash/debounce */ \"./node_modules/lodash/debounce.js\"));\nclass ReCaptchaComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n type: 'recaptcha',\n key: 'recaptcha',\n label: 'reCAPTCHA'\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'reCAPTCHA',\n group: 'premium',\n icon: 'refresh',\n documentation: '/userguide/form-building/premium-components#recaptcha',\n weight: 40,\n schema: ReCaptchaComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n render() {\n this.recaptchaResult = null;\n if (this.builderMode) {\n return super.render('reCAPTCHA');\n }\n else {\n return super.render('', true);\n }\n }\n createInput() {\n if (this.builderMode) {\n // We need to see it in builder mode.\n this.append(this.text(this.name));\n }\n else {\n const siteKey = (0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey');\n if (siteKey) {\n const recaptchaApiScriptUrl = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;\n this.recaptchaApiReady = Formio_1.Formio.requireLibrary('googleRecaptcha', 'grecaptcha', recaptchaApiScriptUrl, true);\n }\n else {\n console.warn('There is no Site Key specified in settings in form JSON');\n }\n }\n }\n createLabel() {\n return;\n }\n get skipInEmail() {\n return true;\n }\n verify(actionName) {\n const siteKey = (0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey');\n if (!siteKey) {\n console.warn('There is no Site Key specified in settings in form JSON');\n return;\n }\n if (!this.recaptchaApiReady) {\n const recaptchaApiScriptUrl = `https://www.google.com/recaptcha/api.js?render=${(0, get_1.default)(this.root.form, 'settings.recaptcha.siteKey')}`;\n this.recaptchaApiReady = Formio_1.Formio.requireLibrary('googleRecaptcha', 'grecaptcha', recaptchaApiScriptUrl, true);\n }\n if (this.recaptchaApiReady) {\n this.recaptchaVerifiedPromise = new Promise((resolve, reject) => {\n this.recaptchaApiReady\n .then(() => {\n if (!this.isLoading) {\n this.isLoading = true;\n grecaptcha.ready((0, debounce_1.default)(() => {\n grecaptcha\n .execute(siteKey, {\n action: actionName\n })\n .then((token) => {\n return this.sendVerificationRequest(token).then(({ verificationResult, token }) => {\n this.recaptchaResult = Object.assign(Object.assign({}, verificationResult), { token });\n this.updateValue(this.recaptchaResult);\n return resolve(verificationResult);\n });\n })\n .catch(() => {\n this.isLoading = false;\n });\n }, 1000));\n }\n })\n .catch(() => {\n return reject();\n });\n }).then(() => {\n this.isLoading = false;\n });\n }\n }\n beforeSubmit() {\n if (this.recaptchaVerifiedPromise) {\n return this.recaptchaVerifiedPromise\n .then(() => super.beforeSubmit());\n }\n return super.beforeSubmit();\n }\n sendVerificationRequest(token) {\n return Formio_1.Formio.makeStaticRequest(`${Formio_1.Formio.projectUrl}/recaptcha?recaptchaToken=${token}`)\n .then((verificationResult) => ({ verificationResult, token }));\n }\n checkComponentValidity(data, dirty, row, options = {}) {\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false } = options;\n // Verification could be async only\n if (!async) {\n return super.checkComponentValidity(data, dirty, row, options);\n }\n const componentData = row[this.component.key];\n if (!componentData || !componentData.token) {\n this.setCustomValidity(this.t('reCaptchaTokenNotSpecifiedError'));\n return Promise.resolve(false);\n }\n if (!componentData.success) {\n this.setCustomValidity(this.t('reCaptchaTokenValidationError'));\n return Promise.resolve(false);\n }\n return this.hook('validateReCaptcha', componentData.token, () => Promise.resolve(true))\n .then((success) => success)\n .catch((err) => {\n this.setCustomValidity(this.t(err.message || err));\n return false;\n });\n }\n normalizeValue(newValue) {\n // If a recaptcha result has already been established, then do not allow it to be reset.\n return this.recaptchaResult ? this.recaptchaResult : newValue;\n }\n}\nexports[\"default\"] = ReCaptchaComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/recaptcha/ReCaptcha.js?");
|
|
5398
5398
|
|
|
5399
5399
|
/***/ }),
|
|
5400
5400
|
|
|
@@ -5570,7 +5570,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5570
5570
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
5571
5571
|
|
|
5572
5572
|
"use strict";
|
|
5573
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.EventEmitter = exports.Licenses = exports.Formio = exports.Form = exports.Utils = exports.ValueSources = exports.Transformers = exports.QuickRules = exports.Operators = exports.Conjunctions = exports.Templates = exports.Widgets = exports.Rules = exports.Providers = exports.Displays = exports.Components = exports.useModule = exports.registerModule = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return Formio_1.Formio; } }));\nconst components_1 = __importDefault(__webpack_require__(/*! ./components */ \"./lib/cjs/components/index.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nexports.Components = Components_1.default;\nconst Displays_1 = __importDefault(__webpack_require__(/*! ./displays/Displays */ \"./lib/cjs/displays/Displays.js\"));\nexports.Displays = Displays_1.default;\nconst Templates_1 = __importDefault(__webpack_require__(/*! ./templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nexports.Templates = Templates_1.default;\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\nexports.Providers = providers_1.default;\nconst Rules_1 = __importDefault(__webpack_require__(/*! ./validator/Rules */ \"./lib/cjs/validator/Rules.js\"));\nexports.Rules = Rules_1.default;\nconst conjunctions_1 = __importDefault(__webpack_require__(/*! ./validator/conjunctions */ \"./lib/cjs/validator/conjunctions/index.js\"));\nexports.Conjunctions = conjunctions_1.default;\nconst operators_1 = __importDefault(__webpack_require__(/*! ./validator/operators */ \"./lib/cjs/validator/operators/index.js\"));\nexports.Operators = operators_1.default;\nconst quickRules_1 = __importDefault(__webpack_require__(/*! ./validator/quickRules */ \"./lib/cjs/validator/quickRules/index.js\"));\nexports.QuickRules = quickRules_1.default;\nconst transformers_1 = __importDefault(__webpack_require__(/*! ./validator/transformers */ \"./lib/cjs/validator/transformers/index.js\"));\nexports.Transformers = transformers_1.default;\nconst valueSources_1 = __importDefault(__webpack_require__(/*! ./validator/valueSources */ \"./lib/cjs/validator/valueSources/index.js\"));\nexports.ValueSources = valueSources_1.default;\nconst widgets_1 = __importDefault(__webpack_require__(/*! ./widgets */ \"./lib/cjs/widgets/index.js\"));\nexports.Widgets = widgets_1.default;\nconst Form_1 = __importDefault(__webpack_require__(/*! ./Form */ \"./lib/cjs/Form.js\"));\nexports.Form = Form_1.default;\nconst utils_1 = __importDefault(__webpack_require__(/*! ./utils */ \"./lib/cjs/utils/index.js\"));\nexports.Utils = utils_1.default;\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./utils/Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nconst licenses_1 = __importDefault(__webpack_require__(/*! ./licenses */ \"./lib/cjs/licenses/index.js\"));\nexports.Licenses = licenses_1.default;\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nexports.EventEmitter = EventEmitter_1.default;\nFormio_1.Formio.loadModules = (path = `${Formio_1.Formio.getApiUrl()}/externalModules.js`, name = 'externalModules') => {\n Formio_1.Formio.requireLibrary(name, name, path, true)\n .then((modules) => {\n Formio_1.Formio.use(modules);\n });\n};\n// This is needed to maintain correct imports using the \"dist\" file.\nFormio_1.Formio.Components = Components_1.default;\nFormio_1.Formio.Templates = Templates_1.default;\nFormio_1.Formio.Utils = utils_1.default;\nFormio_1.Formio.Form = Form_1.default;\nFormio_1.Formio.Displays = Displays_1.default;\nFormio_1.Formio.Providers = providers_1.default;\nFormio_1.Formio.Rules = Rules_1.default;\nFormio_1.Formio.Widgets = widgets_1.default;\nFormio_1.Formio.Evaluator = Evaluator_1.default;\nFormio_1.Formio.Conjunctions = conjunctions_1.default;\nFormio_1.Formio.Operators = operators_1.default;\nFormio_1.Formio.QuickRules = quickRules_1.default;\nFormio_1.Formio.Transformers = transformers_1.default;\nFormio_1.Formio.ValueSources = valueSources_1.default;\nFormio_1.Formio.AllComponents = components_1.default;\nFormio_1.Formio.Licenses = licenses_1.default;\n// This is strange, but is needed for \"premium\" components to import correctly.\nFormio_1.Formio.Formio = Formio_1.Formio;\nFormio_1.Formio.Components.setComponents(components_1.default);\n/**\n * Register a module\n * @param {*} plugin\n * @returns\n */\nfunction registerModule(mod, defaultFn = null, options = {}) {\n // Sanity check.\n if (typeof mod !== 'object') {\n return;\n }\n for (const key of Object.keys(mod)) {\n const current = mod.framework || Formio_1.Formio.Templates.framework || 'bootstrap';\n switch (key) {\n case 'options':\n Formio_1.Formio.options = lodash_1.default.merge(Formio_1.Formio.options, mod.options);\n break;\n case 'templates':\n for (const framework of Object.keys(mod.templates)) {\n Formio_1.Formio.Templates.extendTemplate(framework, mod.templates[framework]);\n }\n if (mod.templates[current]) {\n Formio_1.Formio.Templates.current = mod.templates[current];\n }\n break;\n case 'components':\n Formio_1.Formio.Components.setComponents(mod.components);\n break;\n case 'framework':\n Formio_1.Formio.Templates.framework = mod.framework;\n break;\n case 'fetch':\n for (const name of Object.keys(mod.fetch)) {\n Formio_1.Formio.registerPlugin(mod.fetch[name], name);\n }\n break;\n case 'providers':\n for (const type of Object.keys(mod.providers)) {\n Formio_1.Formio.Providers.addProviders(type, mod.providers[type]);\n }\n break;\n case 'displays':\n Formio_1.Formio.Displays.addDisplays(mod.displays);\n break;\n case 'rules':\n Formio_1.Formio.Rules.addRules(mod.rules);\n break;\n case 'evaluator':\n Formio_1.Formio.Evaluator.registerEvaluator(mod.evaluator);\n break;\n case 'conjunctions':\n Formio_1.Formio.Conjunctions.addConjunctions(mod.conjunctions);\n break;\n case 'operators':\n Formio_1.Formio.Operators.addOperators(mod.operators);\n break;\n case 'quickRules':\n Formio_1.Formio.QuickRules.addQuickRules(mod.quickRules);\n break;\n case 'transformers':\n Formio_1.Formio.Transformers.addTransformers(mod.transformers);\n break;\n case 'valueSources':\n Formio_1.Formio.ValueSources.addValueSources(mod.valueSources);\n break;\n case 'library':\n options.license\n ? Formio_1.Formio.Licenses.addLicense(mod.library, options.license)\n : Formio_1.Formio.Licenses.removeLicense(mod.library);\n break;\n default:\n if (defaultFn) {\n if (!defaultFn(key, mod)) {\n console.warn('Unknown module option', key);\n }\n break;\n }\n console.log('Unknown module option', key);\n }\n }\n}\nexports.registerModule = registerModule;\nfunction useModule(defaultFn = null) {\n return (plugins, options = {}) => {\n plugins = lodash_1.default.isArray(plugins) ? plugins : [plugins];\n plugins.forEach((plugin) => {\n if (Array.isArray(plugin)) {\n plugin.forEach(p => registerModule(p, defaultFn, options));\n }\n else {\n registerModule(plugin, defaultFn, options);\n }\n });\n };\n}\nexports.useModule = useModule;\n/**\n * Allows passing in plugins as an array of plugins or a single plugin.\n *\n * Formio.plugins(plugin1, options);\n * Formio.plugins([plugin1, plugin2, etc], options);\n */\nFormio_1.Formio.use = useModule();\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/formio.form.js?");
|
|
5573
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.EventEmitter = exports.Licenses = exports.Formio = exports.Form = exports.Utils = exports.ValueSources = exports.Transformers = exports.QuickRules = exports.Operators = exports.Conjunctions = exports.Templates = exports.Widgets = exports.Rules = exports.Providers = exports.Displays = exports.Components = exports.useModule = exports.registerModule = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return Formio_1.Formio; } }));\nconst components_1 = __importDefault(__webpack_require__(/*! ./components */ \"./lib/cjs/components/index.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nexports.Components = Components_1.default;\nconst Displays_1 = __importDefault(__webpack_require__(/*! ./displays/Displays */ \"./lib/cjs/displays/Displays.js\"));\nexports.Displays = Displays_1.default;\nconst Templates_1 = __importDefault(__webpack_require__(/*! ./templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nexports.Templates = Templates_1.default;\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\nexports.Providers = providers_1.default;\nconst Rules_1 = __importDefault(__webpack_require__(/*! ./validator/Rules */ \"./lib/cjs/validator/Rules.js\"));\nexports.Rules = Rules_1.default;\nconst conjunctions_1 = __importDefault(__webpack_require__(/*! ./validator/conjunctions */ \"./lib/cjs/validator/conjunctions/index.js\"));\nexports.Conjunctions = conjunctions_1.default;\nconst operators_1 = __importDefault(__webpack_require__(/*! ./validator/operators */ \"./lib/cjs/validator/operators/index.js\"));\nexports.Operators = operators_1.default;\nconst quickRules_1 = __importDefault(__webpack_require__(/*! ./validator/quickRules */ \"./lib/cjs/validator/quickRules/index.js\"));\nexports.QuickRules = quickRules_1.default;\nconst transformers_1 = __importDefault(__webpack_require__(/*! ./validator/transformers */ \"./lib/cjs/validator/transformers/index.js\"));\nexports.Transformers = transformers_1.default;\nconst valueSources_1 = __importDefault(__webpack_require__(/*! ./validator/valueSources */ \"./lib/cjs/validator/valueSources/index.js\"));\nexports.ValueSources = valueSources_1.default;\nconst widgets_1 = __importDefault(__webpack_require__(/*! ./widgets */ \"./lib/cjs/widgets/index.js\"));\nexports.Widgets = widgets_1.default;\nconst Form_1 = __importDefault(__webpack_require__(/*! ./Form */ \"./lib/cjs/Form.js\"));\nexports.Form = Form_1.default;\nconst utils_1 = __importDefault(__webpack_require__(/*! ./utils */ \"./lib/cjs/utils/index.js\"));\nexports.Utils = utils_1.default;\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./utils/Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nconst licenses_1 = __importDefault(__webpack_require__(/*! ./licenses */ \"./lib/cjs/licenses/index.js\"));\nexports.Licenses = licenses_1.default;\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nexports.EventEmitter = EventEmitter_1.default;\nFormio_1.Formio.loadModules = (path = `${Formio_1.Formio.getApiUrl()}/externalModules.js`, name = 'externalModules') => {\n Formio_1.Formio.requireLibrary(name, name, path, true)\n .then((modules) => {\n Formio_1.Formio.use(modules);\n });\n};\n// This is needed to maintain correct imports using the \"dist\" file.\nFormio_1.Formio.Components = Components_1.default;\nFormio_1.Formio.Templates = Templates_1.default;\nFormio_1.Formio.Utils = utils_1.default;\nFormio_1.Formio.Form = Form_1.default;\nFormio_1.Formio.Displays = Displays_1.default;\nFormio_1.Formio.Providers = providers_1.default;\nFormio_1.Formio.Rules = Rules_1.default;\nFormio_1.Formio.Widgets = widgets_1.default;\nFormio_1.Formio.Evaluator = Evaluator_1.default;\nFormio_1.Formio.Conjunctions = conjunctions_1.default;\nFormio_1.Formio.Operators = operators_1.default;\nFormio_1.Formio.QuickRules = quickRules_1.default;\nFormio_1.Formio.Transformers = transformers_1.default;\nFormio_1.Formio.ValueSources = valueSources_1.default;\nFormio_1.Formio.AllComponents = components_1.default;\nFormio_1.Formio.Licenses = licenses_1.default;\n// This is strange, but is needed for \"premium\" components to import correctly.\nFormio_1.Formio.Formio = Formio_1.Formio;\nFormio_1.Formio.Components.setComponents(components_1.default);\n/**\n * Register a module\n * @param {*} plugin\n * @returns\n */\nfunction registerModule(mod, defaultFn = null, options = {}) {\n // Sanity check.\n if (typeof mod !== 'object') {\n return;\n }\n for (const key of Object.keys(mod)) {\n const current = mod.framework || Formio_1.Formio.Templates.framework || 'bootstrap';\n switch (key) {\n case 'options':\n Formio_1.Formio.options = lodash_1.default.merge(Formio_1.Formio.options, mod.options);\n break;\n case 'templates':\n for (const framework of Object.keys(mod.templates)) {\n Formio_1.Formio.Templates.extendTemplate(framework, mod.templates[framework]);\n }\n if (mod.templates[current]) {\n Formio_1.Formio.Templates.current = mod.templates[current];\n }\n break;\n case 'components':\n Formio_1.Formio.Components.setComponents(mod.components);\n break;\n case 'framework':\n Formio_1.Formio.Templates.framework = mod.framework;\n break;\n case 'fetch':\n for (const name of Object.keys(mod.fetch)) {\n Formio_1.Formio.registerPlugin(mod.fetch[name], name);\n }\n break;\n case 'providers':\n for (const type of Object.keys(mod.providers)) {\n Formio_1.Formio.Providers.addProviders(type, mod.providers[type]);\n }\n break;\n case 'displays':\n Formio_1.Formio.Displays.addDisplays(mod.displays);\n break;\n case 'rules':\n Formio_1.Formio.Rules.addRules(mod.rules);\n break;\n case 'evaluator':\n Formio_1.Formio.Evaluator.registerEvaluator(mod.evaluator);\n break;\n case 'conjunctions':\n Formio_1.Formio.Conjunctions.addConjunctions(mod.conjunctions);\n break;\n case 'operators':\n Formio_1.Formio.Operators.addOperators(mod.operators);\n break;\n case 'quickRules':\n Formio_1.Formio.QuickRules.addQuickRules(mod.quickRules);\n break;\n case 'transformers':\n Formio_1.Formio.Transformers.addTransformers(mod.transformers);\n break;\n case 'valueSources':\n Formio_1.Formio.ValueSources.addValueSources(mod.valueSources);\n break;\n case 'library':\n options.license\n ? Formio_1.Formio.Licenses.addLicense(mod.library, options.license)\n : Formio_1.Formio.Licenses.removeLicense(mod.library);\n break;\n default:\n if (defaultFn) {\n if (!defaultFn(key, mod)) {\n console.warn('Unknown module option', key);\n }\n break;\n }\n console.log('Unknown module option', key);\n }\n }\n}\nexports.registerModule = registerModule;\nfunction useModule(defaultFn = null) {\n return (plugins, options = {}) => {\n plugins = lodash_1.default.isArray(plugins) ? plugins : [plugins];\n plugins.forEach((plugin) => {\n if (Array.isArray(plugin)) {\n plugin.forEach(p => registerModule(p, defaultFn, options));\n }\n else {\n registerModule(plugin, defaultFn, options);\n }\n });\n };\n}\nexports.useModule = useModule;\n/**\n * Allows passing in plugins as an array of plugins or a single plugin.\n *\n * Formio.plugins(plugin1, options);\n * Formio.plugins([plugin1, plugin2, etc], options);\n */\nFormio_1.Formio.use = useModule();\n// Allow simple embedding.\nFormio_1.Formio.embedForm = (embed) => Form_1.default.embed(embed);\n/**\n * Factory that creates a new form based on the form parameters.\n *\n * @param element {HMTLElement} - The HTML Element to add this form to.\n * @param form {string|Object} - The src of the form, or a form object.\n * @param options {Object} - The options to create this form.\n *\n * @return {Promise} - When the form is instance is ready.\n */\nFormio_1.Formio.createForm = (...args) => {\n return (new Form_1.default(...args)).ready;\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/formio.form.js?");
|
|
5574
5574
|
|
|
5575
5575
|
/***/ }),
|
|
5576
5576
|
|
|
@@ -5856,7 +5856,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5856
5856
|
/***/ (function(__unused_webpack_module, exports) {
|
|
5857
5857
|
|
|
5858
5858
|
"use strict";
|
|
5859
|
-
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports[\"default\"] = {\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 alertMessageWithLabel: '{{label}}: {{message}}',\n alertMessage: '{{message}}',\n complete: 'Submission Complete',\n error: 'Please fix the following errors before submitting.',\n errorListHotkey: 'Press Ctrl + Alt + X to go back to the error list.',\n errorsListNavigationMessage: 'Click to navigate to the field with following error.',\n submitError: 'Please check the form and correct all errors before submitting.',\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',\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 minYear: '{{field}} should not contain year less than {{minYear}}',\n invalid_email: '{{field}} must be a valid email.',\n invalid_url: '{{field}} must be a valid url.',\n invalid_regex: '{{field}} does not match the pattern {{regex}}.',\n invalid_date: '{{field}} is not a valid date.',\n invalid_day: '{{field}} is not a valid day.',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n stripe: '{{stripe}}',\n month: 'Month',\n day: 'Day',\n year: 'Year',\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n next: 'Next',\n previous: 'Previous',\n cancel: 'Cancel',\n submit: 'Submit Form',\n confirmCancel: 'Are you sure you want to cancel?',\n saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',\n saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',\n restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',\n time: 'Invalid time',\n cancelButtonAriaLabel: 'Cancel button. Click to reset the form',\n previousButtonAriaLabel: 'Previous button. Click to go back to the previous tab',\n nextButtonAriaLabel: 'Next button. Click to go to the next tab',\n submitButtonAriaLabel: 'Submit Form button. Click to submit the form',\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/translations/en.js?");
|
|
5859
|
+
eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports[\"default\"] = {\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 alertMessageWithLabel: '{{label}}: {{message}}',\n alertMessage: '{{message}}',\n complete: 'Submission Complete',\n error: 'Please fix the following errors before submitting.',\n errorListHotkey: 'Press Ctrl + Alt + X to go back to the error list.',\n errorsListNavigationMessage: 'Click to navigate to the field with following error.',\n submitError: 'Please check the form and correct all errors before submitting.',\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',\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 minYear: '{{field}} should not contain year less than {{minYear}}',\n invalid_email: '{{field}} must be a valid email.',\n invalid_url: '{{field}} must be a valid url.',\n invalid_regex: '{{field}} does not match the pattern {{regex}}.',\n invalid_date: '{{field}} is not a valid date.',\n invalid_day: '{{field}} is not a valid day.',\n mask: '{{field}} does not match the mask.',\n valueIsNotAvailable: '{{ field }} is an invalid value.',\n stripe: '{{stripe}}',\n month: 'Month',\n day: 'Day',\n year: 'Year',\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n next: 'Next',\n previous: 'Previous',\n cancel: 'Cancel',\n submit: 'Submit Form',\n confirmCancel: 'Are you sure you want to cancel?',\n saveDraftInstanceError: 'Cannot save draft because there is no formio instance.',\n saveDraftAuthError: 'Cannot save draft unless a user is authenticated.',\n restoreDraftInstanceError: 'Cannot restore draft because there is no formio instance.',\n time: 'Invalid time',\n cancelButtonAriaLabel: 'Cancel button. Click to reset the form',\n previousButtonAriaLabel: 'Previous button. Click to go back to the previous tab',\n nextButtonAriaLabel: 'Next button. Click to go to the next tab',\n submitButtonAriaLabel: 'Submit Form button. Click to submit the form',\n reCaptchaTokenValidationError: 'ReCAPTCHA: Token validation error',\n reCaptchaTokenNotSpecifiedError: 'ReCAPTCHA: Token is not specified in submission',\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/translations/en.js?");
|
|
5860
5860
|
|
|
5861
5861
|
/***/ }),
|
|
5862
5862
|
|
|
@@ -6197,7 +6197,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6197
6197
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
6198
6198
|
|
|
6199
6199
|
"use strict";
|
|
6200
|
-
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.ValidationChecker = exports[\"default\"] = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst inputmask_1 = __importDefault(__webpack_require__(/*! inputmask */ \"./node_modules/inputmask/dist/inputmask.js\"));\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst { fetch, Headers, Request } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\nconst calendarUtils_1 = __webpack_require__(/*! ../utils/calendarUtils */ \"./lib/cjs/utils/calendarUtils.js\");\nconst Rules_1 = __importDefault(__webpack_require__(/*! ./Rules */ \"./lib/cjs/validator/Rules.js\"));\nclass ValidationChecker {\n constructor(config = {}) {\n this.config = lodash_1.default.defaults(config, ValidationChecker.config);\n this.validators = {\n required: {\n key: 'validate.required',\n method: 'validateRequired',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('required'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!(0, utils_1.boolValue)(setting) || component.isValueHidden()) {\n return true;\n }\n const isCalendar = component.validators.some(validator => validator === 'calendar');\n if (!value && isCalendar && component.widget.enteredDate) {\n return !this.validators.calendar.check.call(this, component, setting, value);\n }\n return !component.isEmpty(value);\n }\n },\n onlyAvailableItems: {\n key: 'validate.onlyAvailableItems',\n method: 'validateValueAvailability',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('valueIsNotAvailable'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting) {\n return !(0, utils_1.boolValue)(setting);\n }\n },\n unique: {\n key: 'validate.unique',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('unique'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n // Skip if setting is falsy\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n // Skip if value is empty object or falsy\n if (!value || lodash_1.default.isObjectLike(value) && lodash_1.default.isEmpty(value)) {\n return true;\n }\n // Skip if we don't have a database connection\n if (!this.config.db) {\n return true;\n }\n return new Promise(resolve => {\n var _a;\n const form = this.config.form;\n const submission = this.config.submission;\n const path = `data.${component.path}`;\n const addPathQueryParams = (pathQueryParams, query, path) => {\n const pathArray = path.split(/\\[\\d+\\]?./);\n const needValuesInArray = pathArray.length > 1;\n let pathToValue = path;\n if (needValuesInArray) {\n pathToValue = pathArray.shift();\n const pathQueryObj = {};\n lodash_1.default.reduce(pathArray, (pathQueryPath, pathPart, index) => {\n const isLastPathPart = index === (pathArray.length - 1);\n const obj = lodash_1.default.get(pathQueryObj, pathQueryPath, pathQueryObj);\n const addedPath = `$elemMatch['${pathPart}']`;\n lodash_1.default.set(obj, addedPath, isLastPathPart ? pathQueryParams : {});\n return pathQueryPath ? `${pathQueryPath}.${addedPath}` : addedPath;\n }, '');\n query[pathToValue] = pathQueryObj;\n }\n else {\n query[pathToValue] = pathQueryParams;\n }\n };\n // Build the query\n const query = { form: form._id };\n let collationOptions = {};\n if (lodash_1.default.isString(value)) {\n if (component.component.dbIndex) {\n addPathQueryParams(value, query, path);\n }\n // These are kind of hacky but provides for a more efficient \"unique\" validation when the string is an email,\n // because we (by and large) only have to worry about ASCII and partial unicode; this way, we can use collation-\n // aware indexes with case insensitive email searches to make things like login and registration a whole lot faster\n else if (component.component.type === 'email' ||\n (component.component.type === 'textfield' && ((_a = component.component.validate) === null || _a === void 0 ? void 0 : _a.pattern) === '[A-Za-z0-9]+')) {\n addPathQueryParams(value, query, path);\n collationOptions = { collation: { locale: 'en', strength: 2 } };\n }\n else {\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value)}$`),\n $options: 'i'\n }, query, path);\n }\n }\n // FOR-213 - Pluck the unique location id\n else if (lodash_1.default.isPlainObject(value) &&\n value.address &&\n value.address['address_components'] &&\n value.address['place_id']) {\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value.address['place_id'])}$`),\n $options: 'i'\n }, query, `${path}.address.place_id`);\n }\n // Compare the contents of arrays vs the order.\n else if (lodash_1.default.isArray(value)) {\n addPathQueryParams({ $all: value }, query, path);\n }\n else if (lodash_1.default.isObject(value) || lodash_1.default.isNumber(value)) {\n addPathQueryParams({ $eq: value }, query, path);\n }\n // Only search for non-deleted items\n query.deleted = { $eq: null };\n query.state = 'submitted';\n const uniqueValidationCallback = (err, result) => {\n if (err) {\n return resolve(false);\n }\n else if (result) {\n // Only OK if it matches the current submission\n if (submission._id && (result._id.toString() === submission._id)) {\n resolve(true);\n }\n else {\n component.conflictId = result._id.toString();\n return resolve(false);\n }\n }\n else {\n return resolve(true);\n }\n };\n // Try to find an existing value within the form\n this.config.db.findOne(query, null, collationOptions, (err, result) => {\n if (err && collationOptions.collation) {\n // presume this error comes from db compatibility, try again as regex\n delete query[path];\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value)}$`),\n $options: 'i'\n }, query, path);\n this.config.db.findOne(query, uniqueValidationCallback);\n }\n else {\n return uniqueValidationCallback(err, result);\n }\n });\n }).catch(() => false);\n }\n },\n multiple: {\n key: 'validate.multiple',\n hasLabel: true,\n message(component) {\n const shouldBeArray = (0, utils_1.boolValue)(component.component.multiple) || Array.isArray(component.emptyValue);\n const isRequired = component.component.validate.required;\n const messageKey = shouldBeArray ? (isRequired ? 'array_nonempty' : 'array') : 'nonarray';\n return component.t(component.errorMessage(messageKey), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n // Skip multiple validation if the component tells us to\n if (!component.validateMultiple()) {\n return true;\n }\n const shouldBeArray = (0, utils_1.boolValue)(setting);\n const canBeArray = Array.isArray(component.emptyValue);\n const isArray = Array.isArray(value);\n const isRequired = component.component.validate.required;\n if (shouldBeArray) {\n if (isArray) {\n return isRequired ? !!value.length : true;\n }\n else {\n // Null/undefined is ok if this value isn't required; anything else should fail\n return lodash_1.default.isNil(value) ? !isRequired : false;\n }\n }\n else {\n return canBeArray || !isArray;\n }\n }\n },\n select: {\n key: 'validate.select',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('select'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value, data, index, row, async) {\n // Skip if setting is falsy\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n // Skip if value is empty\n if (!value || lodash_1.default.isEmpty(value)) {\n return true;\n }\n // Skip if we're not async-capable\n if (!async) {\n return true;\n }\n const schema = component.component;\n // Initialize the request options\n const requestOptions = {\n url: setting,\n method: 'GET',\n qs: {},\n json: true,\n headers: {}\n };\n // If the url is a boolean value\n if (lodash_1.default.isBoolean(requestOptions.url)) {\n requestOptions.url = !!requestOptions.url;\n if (!requestOptions.url ||\n schema.dataSrc !== 'url' ||\n !schema.data.url ||\n !schema.searchField) {\n return true;\n }\n // Get the validation url\n requestOptions.url = schema.data.url;\n // Add the search field\n requestOptions.qs[schema.searchField] = value;\n // Add the filters\n if (schema.filter) {\n requestOptions.url += (!requestOptions.url.includes('?') ? '?' : '&') + schema.filter;\n }\n // If they only wish to return certain fields.\n if (schema.selectFields) {\n requestOptions.qs.select = schema.selectFields;\n }\n }\n if (!requestOptions.url) {\n return true;\n }\n // Make sure to interpolate.\n requestOptions.url = (0, utils_1.interpolate)(requestOptions.url, { data: component.data });\n // Add query string to URL\n requestOptions.url += (requestOptions.url.includes('?') ? '&' : '?') + lodash_1.default.chain(requestOptions.qs)\n .map((val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)\n .join('&')\n .value();\n // Set custom headers.\n if (schema.data && schema.data.headers) {\n lodash_1.default.each(schema.data.headers, header => {\n if (header.key) {\n requestOptions.headers[header.key] = header.value;\n }\n });\n }\n // Set form.io authentication.\n if (schema.authenticate && this.config.token) {\n requestOptions.headers['x-jwt-token'] = this.config.token;\n }\n return fetch(new Request(requestOptions.url, {\n headers: new Headers(requestOptions.headers)\n }))\n .then(response => {\n if (!response.ok) {\n return false;\n }\n return response.json();\n })\n .then((results) => {\n return results && results.length;\n })\n .catch(() => false);\n }\n },\n min: {\n key: 'validate.min',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('min'), {\n field: component.errorLabel,\n min: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const min = parseFloat(setting);\n const parsedValue = parseFloat(value);\n if (Number.isNaN(min) || Number.isNaN(parsedValue)) {\n return true;\n }\n return parsedValue >= min;\n }\n },\n max: {\n key: 'validate.max',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('max'), {\n field: component.errorLabel,\n max: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const max = parseFloat(setting);\n const parsedValue = parseFloat(value);\n if (Number.isNaN(max) || Number.isNaN(parsedValue)) {\n return true;\n }\n return parsedValue <= max;\n }\n },\n minSelectedCount: {\n key: 'validate.minSelectedCount',\n message(component, setting) {\n return component.component.minSelectedCountMessage\n ? component.component.minSelectedCountMessage\n : component.t(component.errorMessage('minSelectedCount'), {\n minCount: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const min = parseFloat(setting);\n if (!min) {\n return true;\n }\n const count = Object.keys(value).reduce((total, key) => {\n if (value[key]) {\n total++;\n }\n return total;\n }, 0);\n // Should not be triggered if there is no options selected at all\n return !count || count >= min;\n }\n },\n maxSelectedCount: {\n key: 'validate.maxSelectedCount',\n message(component, setting) {\n return component.component.maxSelectedCountMessage\n ? component.component.maxSelectedCountMessage\n : component.t(component.errorMessage('maxSelectedCount'), {\n minCount: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const max = parseFloat(setting);\n if (!max) {\n return true;\n }\n const count = Object.keys(value).reduce((total, key) => {\n if (value[key]) {\n total++;\n }\n return total;\n }, 0);\n return count <= max;\n }\n },\n minLength: {\n key: 'validate.minLength',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minLength'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const minLength = parseInt(setting, 10);\n if (!value || !minLength || (typeof value !== 'string') || component.isEmpty(value)) {\n return true;\n }\n return (value.length >= minLength);\n }\n },\n maxLength: {\n key: 'validate.maxLength',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxLength'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const maxLength = parseInt(setting, 10);\n if (!maxLength || (typeof value !== 'string')) {\n return true;\n }\n return (value.length <= maxLength);\n }\n },\n maxWords: {\n key: 'validate.maxWords',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxWords'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const maxWords = parseInt(setting, 10);\n if (!maxWords || (typeof value !== 'string')) {\n return true;\n }\n return (value.trim().split(/\\s+/).length <= maxWords);\n }\n },\n minWords: {\n key: 'validate.minWords',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minWords'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const minWords = parseInt(setting, 10);\n if (!minWords || !value || (typeof value !== 'string')) {\n return true;\n }\n return (value.trim().split(/\\s+/).length >= minWords);\n }\n },\n email: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_email'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n /* eslint-disable max-len */\n // From http://stackoverflow.com/questions/46155/validate-email-address-in-javascript\n const re = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n /* eslint-enable max-len */\n // Allow emails to be valid if the component is pristine and no value is provided.\n return !value || re.test(value);\n }\n },\n url: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_url'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n /* eslint-disable max-len */\n // From https://stackoverflow.com/questions/8667070/javascript-regular-expression-to-validate-url\n const re = /^(?:(?:(?:https?|ftp):)?\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#]\\S*)?$/i;\n // From http://stackoverflow.com/questions/46155/validate-email-address-in-javascript\n const emailRe = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n /* eslint-enable max-len */\n // Allow urls to be valid if the component is pristine and no value is provided.\n return !value || (re.test(value) && !emailRe.test(value));\n }\n },\n date: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_date'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!value) {\n return true;\n }\n if (value === 'Invalid date' || value === 'Invalid Date') {\n return false;\n }\n if (typeof value === 'string') {\n value = new Date(value);\n }\n return value instanceof Date === true && value.toString() !== 'Invalid Date';\n }\n },\n day: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_day'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!value) {\n return true;\n }\n const [DAY, MONTH, YEAR] = component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/').map(x => parseInt(x, 10)), day = values[DAY], month = values[MONTH], year = values[YEAR], maxDay = getDaysInMonthCount(month, year);\n if (day < 0 || day > maxDay) {\n return false;\n }\n if (month < 0 || month > 12) {\n return false;\n }\n if (year < 0 || year > 9999) {\n return false;\n }\n return true;\n function isLeapYear(year) {\n // Year is leap if it is evenly divisible by 400 or evenly divisible by 4 and not evenly divisible by 100.\n return !(year % 400) || (!!(year % 100) && !(year % 4));\n }\n function getDaysInMonthCount(month, year) {\n switch (month) {\n case 1: // January\n case 3: // March\n case 5: // May\n case 7: // July\n case 8: // August\n case 10: // October\n case 12: // December\n return 31;\n case 4: // April\n case 6: // June\n case 9: // September\n case 11: // November\n return 30;\n case 2: // February\n return isLeapYear(year) ? 29 : 28;\n default:\n return 31;\n }\n }\n }\n },\n pattern: {\n key: 'validate.pattern',\n hasLabel: true,\n message(component, setting) {\n return component.t(lodash_1.default.get(component, 'component.validate.patternMessage', component.errorMessage('pattern')), {\n field: component.errorLabel,\n pattern: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (component.isEmpty(value))\n return true;\n const pattern = setting;\n if (!pattern) {\n return true;\n }\n const regex = new RegExp(`^${pattern}$`);\n return regex.test(value);\n }\n },\n json: {\n key: 'validate.json',\n check(component, setting, value, data, index, row) {\n if (!setting) {\n return true;\n }\n const valid = component.evaluate(setting, {\n data,\n row,\n rowIndex: index,\n input: value\n });\n if (valid === null) {\n return true;\n }\n return valid;\n }\n },\n mask: {\n key: 'inputMask',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('mask'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n let inputMask;\n if (component.isMultipleMasksField) {\n const maskName = value ? value.maskName : undefined;\n const formioInputMask = component.getMaskByName(maskName);\n if (formioInputMask) {\n inputMask = formioInputMask;\n }\n value = value ? value.value : value;\n }\n else {\n inputMask = setting;\n }\n if (value && inputMask && typeof value === 'string' && component.type === 'textfield') {\n return inputmask_1.default.isValid(value, inputMask);\n }\n inputMask = inputMask ? (0, utils_1.getInputMask)(inputMask) : null;\n if (value && inputMask && !component.skipMaskValidation) {\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n inputMask = inputMask.map((char) => char === component.placeholderChar ? ' ' : char);\n return (0, utils_1.matchInputMask)(value, inputMask);\n }\n return true;\n }\n },\n custom: {\n key: 'validate.custom',\n message(component) {\n return component.t(component.errorMessage('custom'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value, data, index, row) {\n if (!setting) {\n return true;\n }\n const valid = component.evaluate(setting, {\n valid: true,\n data,\n rowIndex: index,\n row,\n input: value\n }, 'valid', true);\n if (valid === null) {\n return true;\n }\n return valid;\n }\n },\n maxDate: {\n key: 'maxDate',\n hasLabel: true,\n message(component, setting) {\n const date = (0, utils_1.getDateSetting)(setting);\n return component.t(component.errorMessage('maxDate'), {\n field: component.errorLabel,\n maxDate: (0, moment_1.default)(date).format(component.format),\n });\n },\n check(component, setting, value) {\n //if any parts of day are missing, skip maxDate validation\n if (component.isPartialDay && component.isPartialDay(value)) {\n return true;\n }\n const date = component.getValidationFormat ? (0, moment_1.default)(value, component.getValidationFormat()) : (0, moment_1.default)(value);\n const maxDate = (0, utils_1.getDateSetting)(setting);\n if (lodash_1.default.isNull(maxDate)) {\n return true;\n }\n else {\n maxDate.setHours(0, 0, 0, 0);\n }\n return date.isBefore(maxDate) || date.isSame(maxDate);\n }\n },\n minDate: {\n key: 'minDate',\n hasLabel: true,\n message(component, setting) {\n const date = (0, utils_1.getDateSetting)(setting);\n return component.t(component.errorMessage('minDate'), {\n field: component.errorLabel,\n minDate: (0, moment_1.default)(date).format(component.format),\n });\n },\n check(component, setting, value) {\n //if any parts of day are missing, skip minDate validation\n if (component.isPartialDay && component.isPartialDay(value)) {\n return true;\n }\n const date = component.getValidationFormat ? (0, moment_1.default)(value, component.getValidationFormat()) : (0, moment_1.default)(value);\n const minDate = (0, utils_1.getDateSetting)(setting);\n if (lodash_1.default.isNull(minDate)) {\n return true;\n }\n else {\n minDate.setHours(0, 0, 0, 0);\n }\n return date.isAfter(minDate) || date.isSame(minDate);\n }\n },\n minYear: {\n key: 'minYear',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minYear'), {\n field: component.errorLabel,\n minYear: setting,\n });\n },\n check(component, setting, value) {\n const minYear = setting;\n let year = /\\d{4}$/.exec(value);\n year = year ? year[0] : null;\n if (!(+minYear) || !(+year)) {\n return true;\n }\n return +year >= +minYear;\n }\n },\n maxYear: {\n key: 'maxYear',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxYear'), {\n field: component.errorLabel,\n maxYear: setting,\n });\n },\n check(component, setting, value) {\n const maxYear = setting;\n let year = /\\d{4}$/.exec(value);\n year = year ? year[0] : null;\n if (!(+maxYear) || !(+year)) {\n return true;\n }\n return +year <= +maxYear;\n }\n },\n calendar: {\n key: 'validate.calendar',\n messageText: '',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.calendar.messageText), {\n field: component.errorLabel,\n maxDate: (0, moment_1.default)(component.dataValue).format(component.format),\n });\n },\n check(component, setting, value, data, index) {\n this.validators.calendar.messageText = '';\n const widget = component.getWidget(index);\n if (!widget) {\n return true;\n }\n const { settings, enteredDate } = widget;\n const { minDate, maxDate, format } = settings;\n const momentFormat = [(0, utils_1.convertFormatToMoment)(format)];\n if (momentFormat[0].match(/M{3,}/g)) {\n momentFormat.push(momentFormat[0].replace(/M{3,}/g, 'MM'));\n }\n if (!value && enteredDate) {\n const { message, result } = (0, calendarUtils_1.checkInvalidDate)(enteredDate, momentFormat, minDate, maxDate);\n if (!result) {\n this.validators.calendar.messageText = message;\n return result;\n }\n }\n if (value && enteredDate) {\n if ((0, moment_1.default)(value).format() !== (0, moment_1.default)(enteredDate, momentFormat, true).format() && enteredDate.match(/_/gi)) {\n this.validators.calendar.messageText = calendarUtils_1.CALENDAR_ERROR_MESSAGES.INCOMPLETE;\n return false;\n }\n else {\n widget.enteredDate = '';\n return true;\n }\n }\n }\n },\n time: {\n key: 'validate.time',\n messageText: 'Invalid time',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.time.messageText), {\n field: component.errorLabel\n });\n },\n check(component, setting, value) {\n if (component.isEmpty(value))\n return true;\n return (0, moment_1.default)(value, component.component.format).isValid();\n }\n },\n availableValueProperty: {\n key: 'validate.availableValueProperty',\n method: 'validateValueProperty',\n messageText: 'Invalid Value Property',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.availableValueProperty.messageText), {\n field: component.errorLabel,\n });\n },\n check(component, setting, value) {\n if (component.component.dataSrc === 'url' && (lodash_1.default.isUndefined(value) || lodash_1.default.isObject(value))) {\n return false;\n }\n return true;\n }\n }\n };\n }\n checkValidator(component, validator, setting, value, data, index, row, async) {\n let resultOrPromise = null;\n // Allow each component to override their own validators by implementing the validator.method\n if (validator.method && (typeof component[validator.method] === 'function')) {\n resultOrPromise = component[validator.method](setting, value, data, index, row, async);\n }\n else {\n resultOrPromise = validator.check.call(this, component, setting, value, data, index, row, async);\n }\n const processResult = result => {\n if (typeof result === 'string') {\n return result;\n }\n if (!result && validator.message) {\n return validator.message.call(this, component, setting, index, row);\n }\n return '';\n };\n if (async) {\n return Promise.resolve(resultOrPromise).then(processResult);\n }\n else {\n return processResult(resultOrPromise);\n }\n }\n validate(component, validatorName, value, data, index, row, async, conditionallyVisible, validationObj) {\n // Skip validation for conditionally hidden components\n if (!conditionallyVisible) {\n return false;\n }\n const validator = this.validators[validatorName];\n const setting = lodash_1.default.get(validationObj || component.component, validator.key, null);\n const resultOrPromise = this.checkValidator(component, validator, setting, value, data, index, row, async);\n const processResult = result => {\n var _a;\n if (result) {\n const resultData = {\n message: (0, utils_1.unescapeHTML)(lodash_1.default.get(result, 'message', result)),\n level: lodash_1.default.get(result, 'level') === 'warning' ? 'warning' : 'error',\n path: (0, utils_1.getArrayFromComponentPath)(component.path || ''),\n context: {\n validator: validatorName,\n hasLabel: validator.hasLabel,\n setting,\n key: component.key,\n label: component.label,\n value,\n index,\n input: (_a = component.refs.input) === null || _a === void 0 ? void 0 : _a[index]\n }\n };\n if (validatorName === 'unique' && component.conflictId) {\n resultData.conflictId = component.conflictId;\n }\n return resultData;\n }\n else {\n return false;\n }\n };\n if (async) {\n return Promise.resolve(resultOrPromise).then(processResult);\n }\n else {\n return processResult(resultOrPromise);\n }\n }\n checkComponent(component, data, row, includeWarnings = false, async = false) {\n var _a;\n const isServerSidePersistent = typeof process !== 'undefined'\n && lodash_1.default.get(process, 'release.name') === 'node'\n && !lodash_1.default.defaultTo(component.component.persistent, true);\n // If we're server-side and it's not a persistent component, don't run validation at all\n if (isServerSidePersistent || component.component.validate === false) {\n return async ? Promise.resolve([]) : [];\n }\n data = data || component.rootValue;\n row = row || component.data;\n const values = (component.component.multiple && Array.isArray(component.validationValue))\n ? component.validationValue\n : [component.validationValue];\n const conditionallyVisible = component.conditionallyVisible();\n const addonsValidations = [];\n if ((_a = component === null || component === void 0 ? void 0 : component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n values.forEach((value) => {\n component.addons.forEach((addon) => {\n if (!addon.checkValidity(value)) {\n addonsValidations.push(...(addon.errors || []));\n }\n });\n });\n }\n // If this component has the new validation system enabled, use it instead.\n const validations = lodash_1.default.get(component, 'component.validations');\n let nextGenResultsOrPromises = [];\n if (validations && Array.isArray(validations) && validations.length) {\n const validationsGroupedByMode = lodash_1.default.chain(validations)\n .groupBy((validation) => validation.mode)\n .value();\n if (component.calculateCondition) {\n includeWarnings = true;\n const uiGroupedValidation = lodash_1.default.chain(validationsGroupedByMode.ui)\n .filter('active')\n .groupBy((validation) => validation.group || null)\n .value();\n const commonValidations = uiGroupedValidation.null || [];\n delete uiGroupedValidation.null;\n commonValidations.forEach(({ condition, message, severity }) => {\n if (!component.calculateCondition(condition)) {\n nextGenResultsOrPromises.push({\n level: severity || 'error',\n message: component.t(message),\n componentInstance: component,\n });\n }\n });\n lodash_1.default.forEach(uiGroupedValidation, (validationGroup) => {\n lodash_1.default.forEach(validationGroup, ({ condition, message, severity }) => {\n if (!component.calculateCondition(condition)) {\n nextGenResultsOrPromises.push({\n level: severity || 'error',\n message: component.t(message),\n componentInstance: component,\n });\n return false;\n }\n });\n });\n }\n else {\n nextGenResultsOrPromises = this.checkValidations(component, validations, data, row, values, async);\n }\n if (component.validators.includes('custom') && validationsGroupedByMode.js) {\n lodash_1.default.each(validationsGroupedByMode.js, (validation) => {\n nextGenResultsOrPromises.push(lodash_1.default.map(values, (value, index) => this.validate(component, 'custom', value, data, index, row, async, conditionallyVisible, validation)));\n });\n }\n if (component.validators.includes('json') && validationsGroupedByMode.json) {\n lodash_1.default.each(validationsGroupedByMode.json, (validation) => {\n nextGenResultsOrPromises.push(lodash_1.default.map(values, (value, index) => this.validate(component, 'json', value, data, index, row, async, conditionallyVisible, validation)));\n });\n }\n }\n const validateCustom = lodash_1.default.get(component, 'component.validate.custom');\n const customErrorMessage = lodash_1.default.get(component, 'component.validate.customMessage');\n // Run primary validators\n const resultsOrPromises = (0, lodash_1.default)(component.validators).chain()\n .map(validatorName => {\n if (!this.validators.hasOwnProperty(validatorName)) {\n return {\n message: `Validator for \"${validatorName}\" is not defined`,\n level: 'warning',\n context: {\n validator: validatorName,\n key: component.key,\n label: component.label\n }\n };\n }\n // Handle the case when there is no values defined and it is required.\n if (validatorName === 'required' && !values.length) {\n return [this.validate(component, validatorName, null, data, 0, row, async, conditionallyVisible)];\n }\n return lodash_1.default.map(values, (value, index) => this.validate(component, validatorName, value, data, index, row, async, conditionallyVisible));\n })\n .flatten()\n .value();\n // Run the \"unique\" pseudo-validator\n component.component.validate = component.component.validate || {};\n component.component.validate.unique = component.component.unique;\n resultsOrPromises.push(this.validate(component, 'unique', component.validationValue, data, 0, data, async, conditionallyVisible));\n // Run the \"multiple\" pseudo-validator\n component.component.validate.multiple = component.component.multiple;\n resultsOrPromises.push(this.validate(component, 'multiple', component.validationValue, data, 0, data, async, conditionallyVisible));\n resultsOrPromises.push(...addonsValidations);\n resultsOrPromises.push(...nextGenResultsOrPromises);\n // Define how results should be formatted\n const formatResults = results => {\n // Condense to a single flat array\n results = (0, lodash_1.default)(results).chain().flatten().compact().value();\n if (customErrorMessage || validateCustom) {\n lodash_1.default.each(results, result => {\n result.message = component.t(customErrorMessage || result.message, {\n field: component.errorLabel,\n data,\n row,\n error: result\n });\n result.context.hasLabel = false;\n });\n }\n return includeWarnings ? results : lodash_1.default.reject(results, result => result.level === 'warning');\n };\n // Wait for results if using async mode, otherwise process and return immediately\n if (async) {\n return Promise.all(resultsOrPromises).then(formatResults);\n }\n else {\n return formatResults(resultsOrPromises);\n }\n }\n /**\n * Use the new validations engine to evaluate any errors.\n *\n * @param component\n * @param validations\n * @param data\n * @param row\n * @param values\n * @returns {any[]}\n */\n checkValidations(component, validations, data, row, values, async) {\n // Get results.\n const results = validations.map((validation) => {\n return this.checkRule(component, validation, data, row, values, async);\n });\n // Flatten array and filter out empty results.\n const messages = results.reduce((prev, result) => {\n if (result) {\n return [...prev, ...result];\n }\n return prev;\n }, []).filter((result) => result);\n // Keep only the last error for each rule.\n const rules = messages.reduce((prev, message) => {\n prev[message.context.validator] = message;\n return prev;\n }, {});\n return Object.values(rules);\n }\n checkRule(component, validation, data, row, values, async) {\n const Rule = Rules_1.default.getRule(validation.rule);\n const results = [];\n if (Rule) {\n const rule = new Rule(component, validation.settings, this.config);\n values.map((value, index) => {\n const result = rule.check(value, data, row, async);\n if (result !== true) {\n results.push({\n level: validation.level || 'error',\n message: component.t(validation.message || rule.defaultMessage, {\n settings: validation.settings,\n field: component.errorLabel,\n data,\n row,\n error: result,\n }),\n context: {\n key: component.key,\n index,\n label: component.label,\n validator: validation.rule,\n },\n });\n }\n });\n }\n // If there are no results, return false so it is removed by filter.\n return results.length === 0 ? false : results;\n }\n get check() {\n return this.checkComponent;\n }\n get() {\n lodash_1.default.get.call(this, arguments);\n }\n each() {\n lodash_1.default.each.call(this, arguments);\n }\n has() {\n lodash_1.default.has.call(this, arguments);\n }\n}\nexports.ValidationChecker = ValidationChecker;\nValidationChecker.config = {\n db: null,\n token: null,\n form: null,\n submission: null\n};\nconst instance = new ValidationChecker();\nexports[\"default\"] = instance;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/validator/Validator.js?");
|
|
6200
|
+
eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.ValidationChecker = exports[\"default\"] = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst inputmask_1 = __importDefault(__webpack_require__(/*! inputmask */ \"./node_modules/inputmask/dist/inputmask.js\"));\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst { fetch, Headers, Request } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\nconst calendarUtils_1 = __webpack_require__(/*! ../utils/calendarUtils */ \"./lib/cjs/utils/calendarUtils.js\");\nconst Rules_1 = __importDefault(__webpack_require__(/*! ./Rules */ \"./lib/cjs/validator/Rules.js\"));\nclass ValidationChecker {\n constructor(config = {}) {\n this.config = lodash_1.default.defaults(config, ValidationChecker.config);\n this.validators = {\n required: {\n key: 'validate.required',\n method: 'validateRequired',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('required'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!(0, utils_1.boolValue)(setting) || component.isValueHidden()) {\n return true;\n }\n const isCalendar = component.validators.some(validator => validator === 'calendar');\n if (!value && isCalendar && component.widget.enteredDate) {\n return !this.validators.calendar.check.call(this, component, setting, value);\n }\n return !component.isEmpty(value);\n }\n },\n onlyAvailableItems: {\n key: 'validate.onlyAvailableItems',\n method: 'validateValueAvailability',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('valueIsNotAvailable'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting) {\n return !(0, utils_1.boolValue)(setting);\n }\n },\n unique: {\n key: 'validate.unique',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('unique'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n // Skip if setting is falsy\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n // Skip if value is empty object or falsy\n if (!value || lodash_1.default.isObjectLike(value) && lodash_1.default.isEmpty(value)) {\n return true;\n }\n // Skip if we don't have a database connection\n if (!this.config.db) {\n return true;\n }\n return new Promise(resolve => {\n var _a;\n const form = this.config.form;\n const submission = this.config.submission;\n const path = `data.${component.path}`;\n const addPathQueryParams = (pathQueryParams, query, path) => {\n const pathArray = path.split(/\\[\\d+\\]?./);\n const needValuesInArray = pathArray.length > 1;\n let pathToValue = path;\n if (needValuesInArray) {\n pathToValue = pathArray.shift();\n const pathQueryObj = {};\n lodash_1.default.reduce(pathArray, (pathQueryPath, pathPart, index) => {\n const isLastPathPart = index === (pathArray.length - 1);\n const obj = lodash_1.default.get(pathQueryObj, pathQueryPath, pathQueryObj);\n const addedPath = `$elemMatch['${pathPart}']`;\n lodash_1.default.set(obj, addedPath, isLastPathPart ? pathQueryParams : {});\n return pathQueryPath ? `${pathQueryPath}.${addedPath}` : addedPath;\n }, '');\n query[pathToValue] = pathQueryObj;\n }\n else {\n query[pathToValue] = pathQueryParams;\n }\n };\n // Build the query\n const query = { form: form._id };\n let collationOptions = {};\n if (lodash_1.default.isString(value)) {\n if (component.component.dbIndex) {\n addPathQueryParams(value, query, path);\n }\n // These are kind of hacky but provides for a more efficient \"unique\" validation when the string is an email,\n // because we (by and large) only have to worry about ASCII and partial unicode; this way, we can use collation-\n // aware indexes with case insensitive email searches to make things like login and registration a whole lot faster\n else if (component.component.type === 'email' ||\n (component.component.type === 'textfield' && ((_a = component.component.validate) === null || _a === void 0 ? void 0 : _a.pattern) === '[A-Za-z0-9]+')) {\n addPathQueryParams(value, query, path);\n collationOptions = { collation: { locale: 'en', strength: 2 } };\n }\n else {\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value)}$`),\n $options: 'i'\n }, query, path);\n }\n }\n // FOR-213 - Pluck the unique location id\n else if (lodash_1.default.isPlainObject(value) &&\n value.address &&\n value.address['address_components'] &&\n value.address['place_id']) {\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value.address['place_id'])}$`),\n $options: 'i'\n }, query, `${path}.address.place_id`);\n }\n // Compare the contents of arrays vs the order.\n else if (lodash_1.default.isArray(value)) {\n addPathQueryParams({ $all: value }, query, path);\n }\n else if (lodash_1.default.isObject(value) || lodash_1.default.isNumber(value)) {\n addPathQueryParams({ $eq: value }, query, path);\n }\n // Only search for non-deleted items\n query.deleted = { $eq: null };\n query.state = 'submitted';\n const uniqueValidationCallback = (err, result) => {\n if (err) {\n return resolve(false);\n }\n else if (result) {\n // Only OK if it matches the current submission\n if (submission._id && (result._id.toString() === submission._id)) {\n resolve(true);\n }\n else {\n component.conflictId = result._id.toString();\n return resolve(false);\n }\n }\n else {\n return resolve(true);\n }\n };\n // Try to find an existing value within the form\n this.config.db.findOne(query, null, collationOptions, (err, result) => {\n if (err && collationOptions.collation) {\n // presume this error comes from db compatibility, try again as regex\n delete query[path];\n addPathQueryParams({\n $regex: new RegExp(`^${(0, utils_1.escapeRegExCharacters)(value)}$`),\n $options: 'i'\n }, query, path);\n this.config.db.findOne(query, uniqueValidationCallback);\n }\n else {\n return uniqueValidationCallback(err, result);\n }\n });\n }).catch(() => false);\n }\n },\n multiple: {\n key: 'validate.multiple',\n hasLabel: true,\n message(component) {\n const shouldBeArray = (0, utils_1.boolValue)(component.component.multiple) || Array.isArray(component.emptyValue);\n const isRequired = component.component.validate.required;\n const messageKey = shouldBeArray ? (isRequired ? 'array_nonempty' : 'array') : 'nonarray';\n return component.t(component.errorMessage(messageKey), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n // Skip multiple validation if the component tells us to\n if (!component.validateMultiple()) {\n return true;\n }\n const shouldBeArray = (0, utils_1.boolValue)(setting);\n const canBeArray = Array.isArray(component.emptyValue);\n const isArray = Array.isArray(value);\n const isRequired = component.component.validate.required;\n if (shouldBeArray) {\n if (isArray) {\n return isRequired ? !!value.length : true;\n }\n else {\n // Null/undefined is ok if this value isn't required; anything else should fail\n return lodash_1.default.isNil(value) ? !isRequired : false;\n }\n }\n else {\n return canBeArray || !isArray;\n }\n }\n },\n select: {\n key: 'validate.select',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('select'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value, data, index, row, async) {\n // Skip if setting is falsy\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n // Skip if value is empty\n if (!value || lodash_1.default.isEmpty(value)) {\n return true;\n }\n // Skip if we're not async-capable\n if (!async) {\n return true;\n }\n const schema = component.component;\n // Initialize the request options\n const requestOptions = {\n url: setting,\n method: 'GET',\n qs: {},\n json: true,\n headers: {}\n };\n // If the url is a boolean value\n if (lodash_1.default.isBoolean(requestOptions.url)) {\n requestOptions.url = !!requestOptions.url;\n if (!requestOptions.url ||\n schema.dataSrc !== 'url' ||\n !schema.data.url ||\n !schema.searchField) {\n return true;\n }\n // Get the validation url\n requestOptions.url = schema.data.url;\n // Add the search field\n requestOptions.qs[schema.searchField] = value;\n // Add the filters\n if (schema.filter) {\n requestOptions.url += (!requestOptions.url.includes('?') ? '?' : '&') + schema.filter;\n }\n // If they only wish to return certain fields.\n if (schema.selectFields) {\n requestOptions.qs.select = schema.selectFields;\n }\n }\n if (!requestOptions.url) {\n return true;\n }\n // Make sure to interpolate.\n requestOptions.url = (0, utils_1.interpolate)(requestOptions.url, { data: component.data });\n // Add query string to URL\n requestOptions.url += (requestOptions.url.includes('?') ? '&' : '?') + lodash_1.default.chain(requestOptions.qs)\n .map((val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`)\n .join('&')\n .value();\n // Set custom headers.\n if (schema.data && schema.data.headers) {\n lodash_1.default.each(schema.data.headers, header => {\n if (header.key) {\n requestOptions.headers[header.key] = header.value;\n }\n });\n }\n // Set form.io authentication.\n if (schema.authenticate && this.config.token) {\n requestOptions.headers['x-jwt-token'] = this.config.token;\n }\n return fetch(new Request(requestOptions.url, {\n headers: new Headers(requestOptions.headers)\n }))\n .then(response => {\n if (!response.ok) {\n return false;\n }\n return response.json();\n })\n .then((results) => {\n return results && results.length;\n })\n .catch(() => false);\n }\n },\n min: {\n key: 'validate.min',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('min'), {\n field: component.errorLabel,\n min: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const min = parseFloat(setting);\n const parsedValue = parseFloat(value);\n if (Number.isNaN(min) || Number.isNaN(parsedValue)) {\n return true;\n }\n return parsedValue >= min;\n }\n },\n max: {\n key: 'validate.max',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('max'), {\n field: component.errorLabel,\n max: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const max = parseFloat(setting);\n const parsedValue = parseFloat(value);\n if (Number.isNaN(max) || Number.isNaN(parsedValue)) {\n return true;\n }\n return parsedValue <= max;\n }\n },\n minSelectedCount: {\n key: 'validate.minSelectedCount',\n message(component, setting) {\n return component.component.minSelectedCountMessage\n ? component.component.minSelectedCountMessage\n : component.t(component.errorMessage('minSelectedCount'), {\n minCount: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const min = parseFloat(setting);\n if (!min) {\n return true;\n }\n const count = Object.keys(value).reduce((total, key) => {\n if (value[key]) {\n total++;\n }\n return total;\n }, 0);\n // Should not be triggered if there is no options selected at all\n return !count || count >= min;\n }\n },\n maxSelectedCount: {\n key: 'validate.maxSelectedCount',\n message(component, setting) {\n return component.component.maxSelectedCountMessage\n ? component.component.maxSelectedCountMessage\n : component.t(component.errorMessage('maxSelectedCount'), {\n minCount: parseFloat(setting),\n data: component.data\n });\n },\n check(component, setting, value) {\n const max = parseFloat(setting);\n if (!max) {\n return true;\n }\n const count = Object.keys(value).reduce((total, key) => {\n if (value[key]) {\n total++;\n }\n return total;\n }, 0);\n return count <= max;\n }\n },\n minLength: {\n key: 'validate.minLength',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minLength'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const minLength = parseInt(setting, 10);\n if (!value || !minLength || (typeof value !== 'string') || component.isEmpty(value)) {\n return true;\n }\n return (value.length >= minLength);\n }\n },\n maxLength: {\n key: 'validate.maxLength',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxLength'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const maxLength = parseInt(setting, 10);\n if (!maxLength || (typeof value !== 'string')) {\n return true;\n }\n return (value.length <= maxLength);\n }\n },\n maxWords: {\n key: 'validate.maxWords',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxWords'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const maxWords = parseInt(setting, 10);\n if (!maxWords || (typeof value !== 'string')) {\n return true;\n }\n return (value.trim().split(/\\s+/).length <= maxWords);\n }\n },\n minWords: {\n key: 'validate.minWords',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minWords'), {\n field: component.errorLabel,\n length: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n const minWords = parseInt(setting, 10);\n if (!minWords || !value || (typeof value !== 'string')) {\n return true;\n }\n return (value.trim().split(/\\s+/).length >= minWords);\n }\n },\n email: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_email'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n /* eslint-disable max-len */\n // From http://stackoverflow.com/questions/46155/validate-email-address-in-javascript\n const re = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n /* eslint-enable max-len */\n // Allow emails to be valid if the component is pristine and no value is provided.\n return !value || re.test(value);\n }\n },\n url: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_url'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n /* eslint-disable max-len */\n // From https://stackoverflow.com/questions/8667070/javascript-regular-expression-to-validate-url\n const re = /^(?:(?:(?:https?|ftp):)?\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:[/?#]\\S*)?$/i;\n // From http://stackoverflow.com/questions/46155/validate-email-address-in-javascript\n const emailRe = /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n /* eslint-enable max-len */\n // Allow urls to be valid if the component is pristine and no value is provided.\n return !value || (re.test(value) && !emailRe.test(value));\n }\n },\n date: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_date'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!value) {\n return true;\n }\n if (value === 'Invalid date' || value === 'Invalid Date') {\n return false;\n }\n if (typeof value === 'string') {\n value = new Date(value);\n }\n return value instanceof Date === true && value.toString() !== 'Invalid Date';\n }\n },\n day: {\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('invalid_day'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (!value) {\n return true;\n }\n const [DAY, MONTH, YEAR] = component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/').map(x => parseInt(x, 10)), day = values[DAY], month = values[MONTH], year = values[YEAR], maxDay = getDaysInMonthCount(month, year);\n if (day < 0 || day > maxDay) {\n return false;\n }\n if (month < 0 || month > 12) {\n return false;\n }\n if (year < 0 || year > 9999) {\n return false;\n }\n return true;\n function isLeapYear(year) {\n // Year is leap if it is evenly divisible by 400 or evenly divisible by 4 and not evenly divisible by 100.\n return !(year % 400) || (!!(year % 100) && !(year % 4));\n }\n function getDaysInMonthCount(month, year) {\n switch (month) {\n case 1: // January\n case 3: // March\n case 5: // May\n case 7: // July\n case 8: // August\n case 10: // October\n case 12: // December\n return 31;\n case 4: // April\n case 6: // June\n case 9: // September\n case 11: // November\n return 30;\n case 2: // February\n return isLeapYear(year) ? 29 : 28;\n default:\n return 31;\n }\n }\n }\n },\n pattern: {\n key: 'validate.pattern',\n hasLabel: true,\n message(component, setting) {\n return component.t(lodash_1.default.get(component, 'component.validate.patternMessage', component.errorMessage('pattern')), {\n field: component.errorLabel,\n pattern: setting,\n data: component.data\n });\n },\n check(component, setting, value) {\n if (component.isEmpty(value))\n return true;\n const pattern = setting;\n if (!pattern) {\n return true;\n }\n const regex = new RegExp(`^${pattern}$`);\n return regex.test(value);\n }\n },\n json: {\n key: 'validate.json',\n check(component, setting, value, data, index, row) {\n if (!setting) {\n return true;\n }\n const valid = component.evaluate(setting, {\n data,\n row,\n rowIndex: index,\n input: value\n });\n if (valid === null) {\n return true;\n }\n return valid;\n }\n },\n mask: {\n key: 'inputMask',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage('mask'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value) {\n let inputMask;\n if (component.isMultipleMasksField) {\n const maskName = value ? value.maskName : undefined;\n const formioInputMask = component.getMaskByName(maskName);\n if (formioInputMask) {\n inputMask = formioInputMask;\n }\n value = value ? value.value : value;\n }\n else {\n inputMask = setting;\n }\n if (value && inputMask && typeof value === 'string' && component.type === 'textfield') {\n return inputmask_1.default.isValid(value, inputMask);\n }\n inputMask = inputMask ? (0, utils_1.getInputMask)(inputMask) : null;\n if (value && inputMask && !component.skipMaskValidation) {\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n inputMask = inputMask.map((char) => char === component.placeholderChar ? ' ' : char);\n return (0, utils_1.matchInputMask)(value, inputMask);\n }\n return true;\n }\n },\n custom: {\n key: 'validate.custom',\n message(component) {\n return component.t(component.errorMessage('custom'), {\n field: component.errorLabel,\n data: component.data\n });\n },\n check(component, setting, value, data, index, row) {\n if (!setting) {\n return true;\n }\n const valid = component.evaluate(setting, {\n valid: true,\n data,\n rowIndex: index,\n row,\n input: value\n }, 'valid', true);\n if (valid === null) {\n return true;\n }\n return valid;\n }\n },\n maxDate: {\n key: 'maxDate',\n hasLabel: true,\n message(component, setting) {\n const date = (0, utils_1.getDateSetting)(setting);\n return component.t(component.errorMessage('maxDate'), {\n field: component.errorLabel,\n maxDate: (0, moment_1.default)(date).format(component.format),\n });\n },\n check(component, setting, value) {\n //if any parts of day are missing, skip maxDate validation\n if (component.isPartialDay && component.isPartialDay(value)) {\n return true;\n }\n const date = component.getValidationFormat ? (0, moment_1.default)(value, component.getValidationFormat()) : (0, moment_1.default)(value);\n const maxDate = (0, utils_1.getDateSetting)(setting);\n if (lodash_1.default.isNull(maxDate)) {\n return true;\n }\n else {\n maxDate.setHours(0, 0, 0, 0);\n }\n return date.isBefore(maxDate) || date.isSame(maxDate);\n }\n },\n minDate: {\n key: 'minDate',\n hasLabel: true,\n message(component, setting) {\n const date = (0, utils_1.getDateSetting)(setting);\n return component.t(component.errorMessage('minDate'), {\n field: component.errorLabel,\n minDate: (0, moment_1.default)(date).format(component.format),\n });\n },\n check(component, setting, value) {\n //if any parts of day are missing, skip minDate validation\n if (component.isPartialDay && component.isPartialDay(value)) {\n return true;\n }\n const date = component.getValidationFormat ? (0, moment_1.default)(value, component.getValidationFormat()) : (0, moment_1.default)(value);\n const minDate = (0, utils_1.getDateSetting)(setting);\n if (lodash_1.default.isNull(minDate)) {\n return true;\n }\n else {\n minDate.setHours(0, 0, 0, 0);\n }\n return date.isAfter(minDate) || date.isSame(minDate);\n }\n },\n minYear: {\n key: 'minYear',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('minYear'), {\n field: component.errorLabel,\n minYear: setting,\n });\n },\n check(component, setting, value) {\n const minYear = setting;\n let year = /\\d{4}$/.exec(value);\n year = year ? year[0] : null;\n if (!(+minYear) || !(+year)) {\n return true;\n }\n return +year >= +minYear;\n }\n },\n maxYear: {\n key: 'maxYear',\n hasLabel: true,\n message(component, setting) {\n return component.t(component.errorMessage('maxYear'), {\n field: component.errorLabel,\n maxYear: setting,\n });\n },\n check(component, setting, value) {\n const maxYear = setting;\n let year = /\\d{4}$/.exec(value);\n year = year ? year[0] : null;\n if (!(+maxYear) || !(+year)) {\n return true;\n }\n return +year <= +maxYear;\n }\n },\n calendar: {\n key: 'validate.calendar',\n messageText: '',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.calendar.messageText), {\n field: component.errorLabel,\n maxDate: (0, moment_1.default)(component.dataValue).format(component.format),\n });\n },\n check(component, setting, value, data, index) {\n this.validators.calendar.messageText = '';\n const widget = component.getWidget(index);\n if (!widget) {\n return true;\n }\n const { settings, enteredDate } = widget;\n const { minDate, maxDate, format } = settings;\n const momentFormat = [(0, utils_1.convertFormatToMoment)(format)];\n if (momentFormat[0].match(/M{3,}/g)) {\n momentFormat.push(momentFormat[0].replace(/M{3,}/g, 'MM'));\n }\n if (!value && enteredDate) {\n const { message, result } = (0, calendarUtils_1.checkInvalidDate)(enteredDate, momentFormat, minDate, maxDate);\n if (!result) {\n this.validators.calendar.messageText = message;\n return result;\n }\n }\n if (value && enteredDate) {\n if ((0, moment_1.default)(value).format() !== (0, moment_1.default)(enteredDate, momentFormat, true).format() && enteredDate.match(/_/gi)) {\n this.validators.calendar.messageText = calendarUtils_1.CALENDAR_ERROR_MESSAGES.INCOMPLETE;\n return false;\n }\n else {\n widget.enteredDate = '';\n return true;\n }\n }\n }\n },\n time: {\n key: 'validate.time',\n messageText: 'Invalid time',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.time.messageText), {\n field: component.errorLabel\n });\n },\n check(component, setting, value) {\n if (component.isEmpty(value))\n return true;\n return (0, moment_1.default)(value, component.component.format).isValid();\n }\n },\n availableValueProperty: {\n key: 'validate.availableValueProperty',\n method: 'validateValueProperty',\n messageText: 'Invalid Value Property',\n hasLabel: true,\n message(component) {\n return component.t(component.errorMessage(this.validators.availableValueProperty.messageText), {\n field: component.errorLabel,\n });\n },\n check(component, setting, value) {\n if (component.component.dataSrc === 'url' && (lodash_1.default.isUndefined(value) || lodash_1.default.isObject(value))) {\n return false;\n }\n return true;\n }\n }\n };\n }\n checkValidator(component, validator, setting, value, data, index, row, async) {\n let resultOrPromise = null;\n // Allow each component to override their own validators by implementing the validator.method\n if (validator.method && (typeof component[validator.method] === 'function')) {\n resultOrPromise = component[validator.method](setting, value, data, index, row, async);\n }\n else {\n resultOrPromise = validator.check.call(this, component, setting, value, data, index, row, async);\n }\n const processResult = result => {\n if (typeof result === 'string') {\n return result;\n }\n if (!result && validator.message) {\n return validator.message.call(this, component, setting, index, row);\n }\n return '';\n };\n if (async) {\n return Promise.resolve(resultOrPromise).then(processResult);\n }\n else {\n return processResult(resultOrPromise);\n }\n }\n validate(component, validatorName, value, data, index, row, async, conditionallyVisible, validationObj) {\n // Skip validation for conditionally hidden components\n if (!conditionallyVisible && !lodash_1.default.get(component.component, 'validateWhenHidden', false)) {\n return false;\n }\n const validator = this.validators[validatorName];\n const setting = lodash_1.default.get(validationObj || component.component, validator.key, null);\n const resultOrPromise = this.checkValidator(component, validator, setting, value, data, index, row, async);\n const processResult = result => {\n var _a;\n if (result) {\n const resultData = {\n message: (0, utils_1.unescapeHTML)(lodash_1.default.get(result, 'message', result)),\n level: lodash_1.default.get(result, 'level') === 'warning' ? 'warning' : 'error',\n path: (0, utils_1.getArrayFromComponentPath)(component.path || ''),\n context: {\n validator: validatorName,\n hasLabel: validator.hasLabel,\n setting,\n key: component.key,\n label: component.label,\n value,\n index,\n input: (_a = component.refs.input) === null || _a === void 0 ? void 0 : _a[index]\n }\n };\n if (validatorName === 'unique' && component.conflictId) {\n resultData.conflictId = component.conflictId;\n }\n return resultData;\n }\n else {\n return false;\n }\n };\n if (async) {\n return Promise.resolve(resultOrPromise).then(processResult);\n }\n else {\n return processResult(resultOrPromise);\n }\n }\n checkComponent(component, data, row, includeWarnings = false, async = false) {\n var _a;\n const isServerSidePersistent = typeof process !== 'undefined'\n && lodash_1.default.get(process, 'release.name') === 'node'\n && !lodash_1.default.defaultTo(component.component.persistent, true);\n // If we're server-side and it's not a persistent component, don't run validation at all\n if (isServerSidePersistent || component.component.validate === false) {\n return async ? Promise.resolve([]) : [];\n }\n data = data || component.rootValue;\n row = row || component.data;\n const values = (component.component.multiple && Array.isArray(component.validationValue))\n ? component.validationValue\n : [component.validationValue];\n const conditionallyVisible = component.conditionallyVisible();\n const addonsValidations = [];\n if ((_a = component === null || component === void 0 ? void 0 : component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n values.forEach((value) => {\n component.addons.forEach((addon) => {\n if (!addon.checkValidity(value)) {\n addonsValidations.push(...(addon.errors || []));\n }\n });\n });\n }\n // If this component has the new validation system enabled, use it instead.\n const validations = lodash_1.default.get(component, 'component.validations');\n let nextGenResultsOrPromises = [];\n if (validations && Array.isArray(validations) && validations.length) {\n const validationsGroupedByMode = lodash_1.default.chain(validations)\n .groupBy((validation) => validation.mode)\n .value();\n if (component.calculateCondition) {\n includeWarnings = true;\n const uiGroupedValidation = lodash_1.default.chain(validationsGroupedByMode.ui)\n .filter('active')\n .groupBy((validation) => validation.group || null)\n .value();\n const commonValidations = uiGroupedValidation.null || [];\n delete uiGroupedValidation.null;\n commonValidations.forEach(({ condition, message, severity }) => {\n if (!component.calculateCondition(condition)) {\n nextGenResultsOrPromises.push({\n level: severity || 'error',\n message: component.t(message),\n componentInstance: component,\n });\n }\n });\n lodash_1.default.forEach(uiGroupedValidation, (validationGroup) => {\n lodash_1.default.forEach(validationGroup, ({ condition, message, severity }) => {\n if (!component.calculateCondition(condition)) {\n nextGenResultsOrPromises.push({\n level: severity || 'error',\n message: component.t(message),\n componentInstance: component,\n });\n return false;\n }\n });\n });\n }\n else {\n nextGenResultsOrPromises = this.checkValidations(component, validations, data, row, values, async);\n }\n if (component.validators.includes('custom') && validationsGroupedByMode.js) {\n lodash_1.default.each(validationsGroupedByMode.js, (validation) => {\n nextGenResultsOrPromises.push(lodash_1.default.map(values, (value, index) => this.validate(component, 'custom', value, data, index, row, async, conditionallyVisible, validation)));\n });\n }\n if (component.validators.includes('json') && validationsGroupedByMode.json) {\n lodash_1.default.each(validationsGroupedByMode.json, (validation) => {\n nextGenResultsOrPromises.push(lodash_1.default.map(values, (value, index) => this.validate(component, 'json', value, data, index, row, async, conditionallyVisible, validation)));\n });\n }\n }\n const validateCustom = lodash_1.default.get(component, 'component.validate.custom');\n const customErrorMessage = lodash_1.default.get(component, 'component.validate.customMessage');\n // Run primary validators\n const resultsOrPromises = (0, lodash_1.default)(component.validators).chain()\n .map(validatorName => {\n if (!this.validators.hasOwnProperty(validatorName)) {\n return {\n message: `Validator for \"${validatorName}\" is not defined`,\n level: 'warning',\n context: {\n validator: validatorName,\n key: component.key,\n label: component.label\n }\n };\n }\n // Handle the case when there is no values defined and it is required.\n if (validatorName === 'required' && !values.length) {\n return [this.validate(component, validatorName, null, data, 0, row, async, conditionallyVisible)];\n }\n return lodash_1.default.map(values, (value, index) => this.validate(component, validatorName, value, data, index, row, async, conditionallyVisible));\n })\n .flatten()\n .value();\n // Run the \"unique\" pseudo-validator\n component.component.validate = component.component.validate || {};\n component.component.validate.unique = component.component.unique;\n resultsOrPromises.push(this.validate(component, 'unique', component.validationValue, data, 0, data, async, conditionallyVisible));\n // Run the \"multiple\" pseudo-validator\n component.component.validate.multiple = component.component.multiple;\n resultsOrPromises.push(this.validate(component, 'multiple', component.validationValue, data, 0, data, async, conditionallyVisible));\n resultsOrPromises.push(...addonsValidations);\n resultsOrPromises.push(...nextGenResultsOrPromises);\n // Define how results should be formatted\n const formatResults = results => {\n // Condense to a single flat array\n results = (0, lodash_1.default)(results).chain().flatten().compact().value();\n if (customErrorMessage || validateCustom) {\n lodash_1.default.each(results, result => {\n result.message = component.t(customErrorMessage || result.message, {\n field: component.errorLabel,\n data,\n row,\n error: result\n });\n result.context.hasLabel = false;\n });\n }\n return includeWarnings ? results : lodash_1.default.reject(results, result => result.level === 'warning');\n };\n // Wait for results if using async mode, otherwise process and return immediately\n if (async) {\n return Promise.all(resultsOrPromises).then(formatResults);\n }\n else {\n return formatResults(resultsOrPromises);\n }\n }\n /**\n * Use the new validations engine to evaluate any errors.\n *\n * @param component\n * @param validations\n * @param data\n * @param row\n * @param values\n * @returns {any[]}\n */\n checkValidations(component, validations, data, row, values, async) {\n // Get results.\n const results = validations.map((validation) => {\n return this.checkRule(component, validation, data, row, values, async);\n });\n // Flatten array and filter out empty results.\n const messages = results.reduce((prev, result) => {\n if (result) {\n return [...prev, ...result];\n }\n return prev;\n }, []).filter((result) => result);\n // Keep only the last error for each rule.\n const rules = messages.reduce((prev, message) => {\n prev[message.context.validator] = message;\n return prev;\n }, {});\n return Object.values(rules);\n }\n checkRule(component, validation, data, row, values, async) {\n const Rule = Rules_1.default.getRule(validation.rule);\n const results = [];\n if (Rule) {\n const rule = new Rule(component, validation.settings, this.config);\n values.map((value, index) => {\n const result = rule.check(value, data, row, async);\n if (result !== true) {\n results.push({\n level: validation.level || 'error',\n message: component.t(validation.message || rule.defaultMessage, {\n settings: validation.settings,\n field: component.errorLabel,\n data,\n row,\n error: result,\n }),\n context: {\n key: component.key,\n index,\n label: component.label,\n validator: validation.rule,\n },\n });\n }\n });\n }\n // If there are no results, return false so it is removed by filter.\n return results.length === 0 ? false : results;\n }\n get check() {\n return this.checkComponent;\n }\n get() {\n lodash_1.default.get.call(this, arguments);\n }\n each() {\n lodash_1.default.each.call(this, arguments);\n }\n has() {\n lodash_1.default.has.call(this, arguments);\n }\n}\nexports.ValidationChecker = ValidationChecker;\nValidationChecker.config = {\n db: null,\n token: null,\n form: null,\n submission: null\n};\nconst instance = new ValidationChecker();\nexports[\"default\"] = instance;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/validator/Validator.js?");
|
|
6201
6201
|
|
|
6202
6202
|
/***/ }),
|
|
6203
6203
|
|
|
@@ -8118,7 +8118,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
|
|
|
8118
8118
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
8119
8119
|
|
|
8120
8120
|
"use strict";
|
|
8121
|
-
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 = void 0;\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return core_1.Formio; } }));\nconst CDN_1 = __importDefault(__webpack_require__(/*! ./CDN */ \"./lib/cjs/CDN.js\"));\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\ncore_1.Formio.cdn = new CDN_1.default();\ncore_1.Formio.Providers = providers_1.default;\ncore_1.Formio.version = '5.0.0-bb.dev.
|
|
8121
|
+
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 = void 0;\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return core_1.Formio; } }));\nconst CDN_1 = __importDefault(__webpack_require__(/*! ./CDN */ \"./lib/cjs/CDN.js\"));\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\ncore_1.Formio.cdn = new CDN_1.default();\ncore_1.Formio.Providers = providers_1.default;\ncore_1.Formio.version = '5.0.0-bb.dev.5';\nconst isNil = (val) => val === null || val === undefined;\ncore_1.Formio.prototype.uploadFile = function (storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) {\n const requestArgs = {\n provider: storage,\n method: 'upload',\n file: file,\n fileName: fileName,\n dir: dir\n };\n fileKey = fileKey || 'file';\n const request = core_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return core_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', storage);\n if (Provider) {\n const provider = new Provider(this);\n if (uploadStartCallback) {\n uploadStartCallback();\n }\n return provider.uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback, multipartOptions);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return core_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\ncore_1.Formio.prototype.downloadFile = function (file, options) {\n const requestArgs = {\n method: 'download',\n file: file\n };\n const request = core_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return core_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.downloadFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return core_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\ncore_1.Formio.prototype.deleteFile = function (file, options) {\n const requestArgs = {\n method: 'delete',\n file: file\n };\n const request = core_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return core_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.deleteFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return core_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\n// For reverse compatability.\ncore_1.Formio.Promise = Promise;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Formio.js?");
|
|
8122
8122
|
|
|
8123
8123
|
/***/ }),
|
|
8124
8124
|
|