@formio/js 5.0.0-dev.5718.37a9ce7 → 5.0.0-dev.5720.5431de8

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.
@@ -5290,7 +5290,7 @@ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ?
5290
5290
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5291
5291
 
5292
5292
  "use strict";
5293
- 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 constructor(elementOrForm, formOrOptions, options = {}) {\n let element, form, formOptions;\n if (elementOrForm instanceof HTMLElement) {\n element = elementOrForm;\n form = formOrOptions;\n formOptions = options;\n }\n else {\n element = null;\n form = elementOrForm;\n formOptions = formOrOptions || {};\n }\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n formOptions = Object.assign(formOptions, Formio_1.Formio.options.form);\n }\n super(formOptions);\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 (element) {\n if (this.element) {\n delete this.element.component;\n }\n this.element = element;\n }\n else {\n this.element = null;\n }\n if (form) {\n this.setForm(form)\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n this.options = formOptions;\n this.options.events = this.events;\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 * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @returns {Webform|Wizard|PDF} - The new form instance for the display.\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 * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @returns {void}\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 /**\n * Check Subdirectories path and provide correct options\n * @param {string} url - The the URL of the form json.\n * @param {import('@formio/core').Form} form - The form json.\n * @returns {object} The initial options with base and project.\n */\n getFormInitOptions(url, form) {\n const options = {};\n const index = url.indexOf(form === null || form === void 0 ? void 0 : form.path);\n // form url doesn't include form path\n if (index === -1) {\n return options;\n }\n const projectUrl = url.substring(0, index - 1);\n const urlParts = Formio_1.Formio.getUrlParts(projectUrl);\n // project url doesn't include subdirectories path\n if (!urlParts || urlParts.filter(part => !!part).length < 4) {\n return options;\n }\n const baseUrl = `${urlParts[1]}${urlParts[2]}`;\n // Skip if baseUrl has already been set\n if (baseUrl !== Formio_1.Formio.baseUrl) {\n return {\n base: baseUrl,\n project: projectUrl,\n };\n }\n return {};\n }\n /**\n * Sets the form to the JSON schema of a form.\n * @param {import('@formio/core').Form} formParam - The form JSON to set this form to.\n * @returns {Promise<Webform|Wizard|PDF>} - The webform instance that was created.\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 const options = this.getFormInitOptions(formParam, form);\n this.instance.setUrl(formParam, options);\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 * @returns {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created after changing the display.\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 * @param {string} dirty - The dirty html string to sanitize.\n * @param {boolean} forceSanitize - If the string should be force sanitized.\n * @returns {string} - The sanitized html string.\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 * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created.\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 * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n * @param {object} elementOrForm - The DOM element you wish to render this form within, or the form definition.\n * @param {object | string | FormOptions} formOrOptions - A Form JSON schema, the URL of a hosted form, or the form options.\n * @param {FormOptions} [options] - The options to create a new form instance.\n * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created.\n * @example\n * import { Formio } from '@formio/js';\n * Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example');\n */\nFormio_1.Formio.createForm = (elementOrForm, formOrOptions, options) => {\n return (new Form(elementOrForm, formOrOptions, options)).ready;\n};\nFormio_1.Formio.Form = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
5293
+ 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\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass Form extends Element_1.default {\n constructor(elementOrForm, formOrOptions, options = {}) {\n let element, form, formOptions;\n if (elementOrForm instanceof HTMLElement) {\n element = elementOrForm;\n form = formOrOptions;\n formOptions = options;\n }\n else {\n element = null;\n form = elementOrForm;\n formOptions = formOrOptions || {};\n }\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n formOptions = Object.assign(formOptions, Formio_1.Formio.options.form);\n }\n super(formOptions);\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 (element) {\n if (this.element) {\n delete this.element.component;\n }\n this.element = element;\n }\n else {\n this.element = null;\n }\n if (form) {\n this.setForm(form)\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n this.options = formOptions;\n this.options.events = this.events;\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 * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @returns {Webform|Wizard|PDF} - The new form instance for the display.\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 * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @returns {void}\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 /**\n * Check Subdirectories path and provide correct options\n * @param {string} url - The the URL of the form json.\n * @param {import('@formio/core').Form} form - The form json.\n * @returns {object} The initial options with base and project.\n */\n getFormInitOptions(url, form) {\n const options = {};\n const index = url.indexOf(form === null || form === void 0 ? void 0 : form.path);\n // form url doesn't include form path\n if (index === -1) {\n return options;\n }\n const projectUrl = url.substring(0, index - 1);\n const urlParts = Formio_1.Formio.getUrlParts(projectUrl);\n // project url doesn't include subdirectories path\n if (!urlParts || urlParts.filter(part => !!part).length < 4) {\n return options;\n }\n const baseUrl = `${urlParts[1]}${urlParts[2]}`;\n // Skip if baseUrl has already been set\n if (baseUrl !== Formio_1.Formio.baseUrl) {\n return {\n base: baseUrl,\n project: projectUrl,\n };\n }\n return {};\n }\n /**\n * Sets the form to the JSON schema of a form.\n * @param {import('@formio/core').Form} formParam - The form JSON to set this form to.\n * @returns {Promise<Webform|Wizard|PDF>} - The webform instance that was created.\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 const options = this.getFormInitOptions(formParam, form);\n this.instance.setUrl(formParam, options);\n lodash_1.default.set(form, 'config.myApiUrl', options.project);\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 * @returns {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created after changing the display.\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 * @param {string} dirty - The dirty html string to sanitize.\n * @param {boolean} forceSanitize - If the string should be force sanitized.\n * @returns {string} - The sanitized html string.\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 * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created.\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 * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n * @param {object} elementOrForm - The DOM element you wish to render this form within, or the form definition.\n * @param {object | string | FormOptions} formOrOptions - A Form JSON schema, the URL of a hosted form, or the form options.\n * @param {FormOptions} [options] - The options to create a new form instance.\n * @returns {Promise<Webform|Wizard|PDF>} - The form instance that was created.\n * @example\n * import { Formio } from '@formio/js';\n * Formio.createForm(document.getElementById('formio'), 'https://examples.form.io/example');\n */\nFormio_1.Formio.createForm = (elementOrForm, formOrOptions, options) => {\n return (new Form(elementOrForm, formOrOptions, options)).ready;\n};\nFormio_1.Formio.Form = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
5294
5294
 
5295
5295
  /***/ }),
5296
5296
 
@@ -5345,7 +5345,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5345
5345
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5346
5346
 
5347
5347
  "use strict";
5348
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ./components/_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst builder_1 = __importDefault(__webpack_require__(/*! ./utils/builder */ \"./lib/cjs/utils/builder.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst dom_autoscroller_1 = __importDefault(__webpack_require__(/*! dom-autoscroller */ \"./node_modules/dom-autoscroller/dist/bundle.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ./templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\n__webpack_require__(/*! ./components/builder */ \"./lib/cjs/components/builder.js\");\n// We need this here because dragula pulls in CustomEvent class that requires global to exist.\nif (typeof window !== 'undefined' && typeof window.global === 'undefined') {\n window.global = window;\n}\nconst dragula_1 = __importDefault(__webpack_require__(/*! dragula */ \"./node_modules/dragula/dragula.js\"));\nclass WebformBuilder extends Component_1.default {\n // eslint-disable-next-line max-statements\n constructor() {\n let element, options;\n if (arguments[0] instanceof HTMLElement || arguments[1]) {\n element = arguments[0];\n options = arguments[1];\n }\n else {\n options = arguments[0];\n }\n // Reset skipInit in case PDFBuilder has set it.\n options.skipInit = false;\n options.display = options.display || 'form';\n super(null, options);\n this.moveHandler = (e) => {\n if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13) {\n e.stopPropagation();\n e.preventDefault();\n }\n if (e.keyCode === 38) {\n this.updateComponentPlacement(true);\n }\n if (e.keyCode === 40) {\n this.updateComponentPlacement(false);\n }\n if (e.keyCode === 13) {\n this.stopMoving(this.selectedComponent);\n }\n };\n this.setElement(element);\n this.dragulaLib = dragula_1.default;\n this.builderHeight = 0;\n this.schemas = {};\n this.repeatablePaths = [];\n this.sideBarScroll = lodash_1.default.get(this.options, 'sideBarScroll', true);\n this.sideBarScrollOffset = lodash_1.default.get(this.options, 'sideBarScrollOffset', 0);\n this.dragDropEnabled = true;\n // Setup the builder options.\n this.builder = lodash_1.default.defaultsDeep({}, this.options.builder, this.defaultGroups);\n // Turn off if explicitely said to do so...\n lodash_1.default.each(this.defaultGroups, (config, key) => {\n if (config === false) {\n this.builder[key] = false;\n }\n });\n // Add the groups.////\n this.groups = {};\n this.groupOrder = [];\n for (const group in this.builder) {\n if (this.builder[group]) {\n this.builder[group].key = group;\n this.groups[group] = this.builder[group];\n this.groups[group].components = this.groups[group].components || {};\n this.groups[group].componentOrder = this.groups[group].componentOrder || [];\n this.groups[group].subgroups = Object.keys(this.groups[group].groups || {}).map((groupKey) => {\n this.groups[group].groups[groupKey].componentOrder = Object.keys(this.groups[group].groups[groupKey].components).map((key) => key);\n return this.groups[group].groups[groupKey];\n });\n this.groupOrder.push(this.groups[group]);\n }\n }\n this.groupOrder = this.groupOrder\n .filter(group => group && !group.ignore)\n .sort((a, b) => a.weight - b.weight)\n .map(group => group.key);\n for (const type in Components_1.default.components) {\n const component = Components_1.default.components[type];\n if (component.builderInfo && component.builderInfo.schema) {\n this.schemas[type] = component.builderInfo.schema;\n component.type = type;\n const builderInfo = component.builderInfo;\n builderInfo.key = component.type;\n this.addBuilderComponentInfo(builderInfo);\n }\n }\n // Filter out any extra components.\n // Add the components in each group.\n for (const group in this.groups) {\n const info = this.groups[group];\n for (const key in info.components) {\n const compKey = group === 'resource' ? `component-${key}` : key;\n let comp = info.components[compKey];\n if (comp === true &&\n Components_1.default.components[key] &&\n Components_1.default.components[key].builderInfo) {\n comp = Components_1.default.components[key].builderInfo;\n }\n if (comp && comp.schema) {\n this.schemas[key] = comp.schema;\n info.components[compKey] = comp;\n info.components[compKey].key = key;\n }\n else {\n // Do not include this component in the components array.\n delete info.components[compKey];\n }\n }\n // Order the components.\n this.orderComponents(info);\n }\n this.options.hooks = this.options.hooks || {};\n this.options.hooks.renderComponent = (html, { component, self }) => {\n var _a, _b;\n if (self.type === 'form' && !self.key) {\n const template = this.hook('renderComponentFormTemplate', html.replace('formio-component-form', ''));\n // The main webform shouldn't have this class as it adds extra styles.\n return template;\n }\n if (this.options.disabled && this.options.disabled.includes(self.key) || self.parent.noDragDrop) {\n return html;\n }\n return this.renderTemplate('builderComponent', {\n html,\n disableBuilderActions: (_a = self === null || self === void 0 ? void 0 : self.component) === null || _a === void 0 ? void 0 : _a.disableBuilderActions,\n childComponent: component,\n design: (_b = self === null || self === void 0 ? void 0 : self.options) === null || _b === void 0 ? void 0 : _b.design\n });\n };\n this.options.hooks.renderComponents = (html, { components, self }) => {\n // if Datagrid and already has a component, don't make it droppable.\n if (self.type === 'datagrid' && components.length > 0 || self.noDragDrop) {\n return html;\n }\n if (!components ||\n (!components.length && !components.nodrop) ||\n (self.type === 'form' && components.length <= 1 && (components.length === 0 || components[0].type === 'button'))) {\n html = this.renderTemplate('builderPlaceholder', {\n position: 0\n }) + html;\n }\n return this.renderTemplate('builderComponents', {\n key: self.key,\n type: self.type,\n html,\n });\n };\n this.options.hooks.renderInput = (html, { self }) => {\n if (self.type === 'hidden') {\n return html + self.name;\n }\n return html;\n };\n this.options.hooks.renderLoading = (html, { self }) => {\n if (self.type === 'form' && self.key) {\n return self.name;\n }\n return html;\n };\n this.options.hooks.attachComponents = (element, components, container, component) => {\n // Don't attach if no element was found or component doesn't participate in drag'n'drop.\n if (!element) {\n return;\n }\n if (component.noDragDrop) {\n return element;\n }\n // Attach container and component to element for later reference.\n const containerElement = element.querySelector(`[${this._referenceAttributeName}=\"${component.component.key}-container\"]`) || element;\n containerElement.formioContainer = container;\n containerElement.formioComponent = component;\n // Add container to draggable list.\n if (this.dragula && this.allowDrop(element)) {\n this.dragula.containers.push(containerElement);\n }\n // If this is an existing datagrid element, don't make it draggable.\n if ((component.type === 'datagrid' || component.type === 'datamap') && components.length > 0) {\n return element;\n }\n // Since we added a wrapper, need to return the original element so that we can find the components inside it.\n return element.children[0];\n };\n this.options.hooks.attachDatagrid = (element, component) => {\n component.loadRefs(element, {\n [`${component.key}-container`]: 'single',\n });\n const dataGridContainer = component.refs[`${component.key}-container`];\n if (dataGridContainer) {\n component.attachComponents(dataGridContainer.parentNode, [], component.component.components);\n }\n // Need to set up horizontal rearrangement of fields.\n };\n this.options.hooks.attachComponent = this.attachComponent.bind(this);\n // Load resources tagged as 'builder'\n const query = {\n params: {\n type: 'resource',\n limit: 1000000,\n select: '_id,title,name,components'\n }\n };\n if (this.options && this.options.resourceTag) {\n query.params.tags = [this.options.resourceTag];\n }\n else if (!this.options || !this.options.hasOwnProperty('resourceTag')) {\n query.params.tags = ['builder'];\n }\n const formio = new Formio_1.Formio(Formio_1.Formio.projectUrl);\n const isResourcesDisabled = this.options.builder && this.options.builder.resource === false;\n formio.loadProject().then((project) => {\n if (project && (lodash_1.default.get(project, 'settings.addConfigToForms', false) || lodash_1.default.get(project, 'addConfigToForms', false))) {\n const config = project.config || {};\n this.options.formConfig = config;\n const pathToFormConfig = 'webform._form.config';\n const webformConfig = lodash_1.default.get(this, pathToFormConfig);\n if (this.webform && !webformConfig) {\n lodash_1.default.set(this, pathToFormConfig, config);\n }\n }\n }).catch((err) => {\n console.warn(`Could not load project settings: ${err.message || err}`);\n });\n if (!formio.noProject && !isResourcesDisabled && formio.formsUrl) {\n const resourceOptions = this.options.builder && this.options.builder.resource;\n formio.loadForms(query)\n .then((resources) => {\n if (resources.length) {\n this.builder.resource = {\n title: resourceOptions ? resourceOptions.title : 'Existing Resource Fields',\n key: 'resource',\n weight: resourceOptions ? resourceOptions.weight : 50,\n subgroups: [],\n components: [],\n componentOrder: []\n };\n this.groups.resource = {\n title: resourceOptions ? resourceOptions.title : 'Existing Resource Fields',\n key: 'resource',\n weight: resourceOptions ? resourceOptions.weight : 50,\n subgroups: [],\n components: [],\n componentOrder: []\n };\n if (!this.groupOrder.includes('resource')) {\n this.groupOrder.push('resource');\n }\n this.addExistingResourceFields(resources);\n }\n });\n }\n // Notify components if they need to modify their render.\n this.options.attachMode = 'builder';\n this.webform = this.webform || this.createForm(this.options);\n this.pathComponentsMapping = {};\n this.arrayDataComponentPaths = [];\n this.nestedDataComponents = [];\n this.arrayDataComponents = [];\n }\n allowDrop() {\n return true;\n }\n addExistingResourceFields(resources) {\n lodash_1.default.each(resources, (resource, index) => {\n const resourceKey = `resource-${resource.name}`;\n const subgroup = {\n key: resourceKey,\n title: resource.title,\n components: [],\n componentOrder: [],\n default: index === 0,\n };\n (0, formUtils_1.eachComponent)(resource.components, (component) => {\n if (component.type === 'button')\n return;\n if (this.options &&\n this.options.resourceFilter &&\n (!component.tags || component.tags.indexOf(this.options.resourceFilter) === -1))\n return;\n let componentName = component.label;\n if (!componentName && component.key) {\n componentName = lodash_1.default.upperFirst(component.key);\n }\n subgroup.componentOrder.push(`component-${component.key}`);\n subgroup.components[`component-${component.key}`] = lodash_1.default.merge((0, utils_1.fastCloneDeep)(Components_1.default.components[component.type]\n ? Components_1.default.components[component.type].builderInfo\n : Components_1.default.components['unknown'].builderInfo), {\n key: component.key,\n title: componentName,\n group: 'resource',\n subgroup: resourceKey,\n }, {\n schema: Object.assign(Object.assign({}, component), { label: component.label, key: component.key, lockKey: true, source: (!this.options.noSource ? resource._id : undefined), isNew: true })\n });\n }, true);\n this.groups.resource.subgroups.push(subgroup);\n });\n this.triggerRedraw();\n }\n attachTooltip(component, title) {\n return (0, tippy_js_1.default)(component, {\n allowHTML: true,\n trigger: 'mouseenter focus',\n placement: 'top',\n delay: [200, 0],\n zIndex: 10000,\n content: title\n });\n }\n attachComponent(element, component) {\n if (component instanceof WebformBuilder) {\n return;\n }\n // Add component to element for later reference.\n element.formioComponent = component;\n component.loadRefs(element, {\n removeComponent: 'single',\n editComponent: 'single',\n moveComponent: 'single',\n copyComponent: 'single',\n pasteComponent: 'single',\n editJson: 'single'\n });\n if (component.refs.copyComponent) {\n this.attachTooltip(component.refs.copyComponent, this.t('Copy'));\n component.addEventListener(component.refs.copyComponent, 'click', () => this.copyComponent(component));\n }\n if (component.refs.pasteComponent) {\n const pasteToolTip = this.attachTooltip(component.refs.pasteComponent, this.t('Paste below'));\n component.addEventListener(component.refs.pasteComponent, 'click', () => {\n pasteToolTip.hide();\n this.pasteComponent(component);\n });\n }\n if (component.refs.moveComponent) {\n this.attachTooltip(component.refs.moveComponent, this.t('Move'));\n if (this.keyboardActionsEnabled) {\n component.addEventListener(component.refs.moveComponent, 'click', () => {\n this.moveComponent(component);\n });\n }\n }\n const parent = this.getParentElement(element);\n if (component.refs.editComponent) {\n this.attachTooltip(component.refs.editComponent, this.t('Edit'));\n component.addEventListener(component.refs.editComponent, 'click', () => this.editComponent(component.schema, parent, false, false, component.component, { inDataGrid: component.isInDataGrid }));\n }\n if (component.refs.editJson) {\n this.attachTooltip(component.refs.editJson, this.t('Edit JSON'));\n component.addEventListener(component.refs.editJson, 'click', () => this.editComponent(component.schema, parent, false, true, component.component));\n }\n if (component.refs.removeComponent) {\n this.attachTooltip(component.refs.removeComponent, this.t('Remove'));\n component.addEventListener(component.refs.removeComponent, 'click', () => this.removeComponent(component.schema, parent, component.component, component));\n }\n return element;\n }\n createForm(options) {\n this.webform = new Webform_1.default(this.element, options);\n if (this.element) {\n this.loadRefs(this.element, {\n form: 'single'\n });\n if (this.refs.form) {\n this.webform.element = this.refs.form;\n }\n }\n return this.webform;\n }\n /**\n * Called when everything is ready.\n * @returns {Promise} - Wait for webform to be ready.\n */\n get ready() {\n return this.webform.ready;\n }\n get defaultGroups() {\n return {\n basic: {\n title: 'Basic',\n weight: 0,\n default: true,\n },\n advanced: {\n title: 'Advanced',\n weight: 10\n },\n layout: {\n title: 'Layout',\n weight: 20\n },\n data: {\n title: 'Data',\n weight: 30\n },\n premium: {\n title: 'Premium',\n weight: 40\n }\n };\n }\n redraw() {\n return Webform_1.default.prototype.redraw.call(this);\n }\n get form() {\n return this.webform.form;\n }\n get schema() {\n return this.webform.schema;\n }\n set form(value) {\n this.setForm(value);\n }\n get container() {\n return this.webform.form.components;\n }\n /**\n * When a component sets its api key, we need to check if it is unique within its namespace. Find the namespace root\n * so we can calculate this correctly.\n * @param {import('@formio/core').Component} component - The component to find the namespace root for.\n * @returns {import('@formio/core').Component[]} - The components root for this namespace.\n */\n findNamespaceRoot(component) {\n const path = (0, utils_1.getArrayFromComponentPath)(component.path);\n // First get the component with nested parents.\n let comp = this.webform.getComponent(path);\n comp = Array.isArray(comp) ? comp[0] : comp;\n const namespaceKey = this.recurseNamespace(comp);\n // If there is no key, it is the root form.\n if (!namespaceKey || this.form.key === namespaceKey) {\n return this.form.components;\n }\n const componentSchema = component.component;\n // If the current component is the namespace, we don't need to find it again.\n if (namespaceKey === component.key) {\n return [...componentSchema.components, componentSchema];\n }\n // Get the namespace component so we have the original object.\n const namespaceComponent = (0, formUtils_1.getComponent)(this.form.components, namespaceKey, true);\n return namespaceComponent ? namespaceComponent.components : comp.components;\n }\n recurseNamespace(component) {\n // If there is no parent, we are at the root level.\n if (!component) {\n return null;\n }\n // Some components are their own namespace.\n if (['address', 'container', 'datagrid', 'editgrid', 'dynamicWizard', 'tree'].includes(component.type) || component.tree || component.arrayTree) {\n return component.key;\n }\n // Anything else, keep going up.\n return this.recurseNamespace(component.parent);\n }\n render() {\n return this.renderTemplate('builder', {\n sidebar: this.renderTemplate('builderSidebar', {\n scrollEnabled: this.sideBarScroll,\n groupOrder: this.groupOrder,\n groupId: `builder-sidebar-${this.id}`,\n groups: this.groupOrder.map((groupKey) => this.renderTemplate('builderSidebarGroup', {\n group: this.groups[groupKey],\n groupKey,\n groupId: `builder-sidebar-${this.id}`,\n subgroups: this.groups[groupKey].subgroups.map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n keyboardActionsEnabled: this.keyboardActionsEnabled,\n })),\n }),\n form: this.webform.render(),\n });\n }\n attach(element) {\n this.on('change', (form) => {\n this.populateCaptchaSettings(form);\n this.webform.setAlert(false);\n });\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n form: 'single',\n sidebar: 'single',\n 'sidebar-search': 'single',\n 'sidebar-groups': 'single',\n 'container': 'multiple',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n 'sidebar-component': 'multiple',\n });\n if (this.sideBarScroll && Templates_1.default.current.handleBuilderSidebarScroll) {\n Templates_1.default.current.handleBuilderSidebarScroll.call(this, this);\n }\n // Add the paste status in form\n if (typeof window !== 'undefined' && window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n this.addClass(this.refs.form, 'builder-paste-mode');\n }\n }\n if (!(0, utils_1.bootstrapVersion)(this.options)) {\n const getAttribute = (anchor, attribute) => {\n let elem = anchor.getAttribute(`data-${attribute}`);\n if (!elem) {\n elem = anchor.getAttribute(`data-bs-${attribute}`);\n }\n return elem;\n };\n const hideShow = (group, show) => {\n if (show) {\n group.classList.add(['show']);\n group.style.display = 'inherit';\n }\n else {\n group.classList.remove(['show']);\n group.style.display = 'none';\n }\n };\n // Initialize\n this.refs['sidebar-group'].forEach((group) => {\n hideShow(group, getAttribute(group, 'default') === 'true');\n });\n // Click event\n this.refs['sidebar-anchor'].forEach((anchor, index) => {\n this.addEventListener(anchor, 'click', () => {\n const clickedParentId = getAttribute(anchor, 'parent').slice('#builder-sidebar-'.length);\n const clickedId = getAttribute(anchor, 'target').slice('#group-'.length);\n this.refs['sidebar-group'].forEach((group, groupIndex) => {\n const openByDefault = getAttribute(group, 'default') === 'true';\n const groupId = group.getAttribute('id').slice('group-'.length);\n const groupParent = getAttribute(group, 'parent').slice('#builder-sidebar-'.length);\n hideShow(group, ((openByDefault && groupParent === clickedId) || groupId === clickedParentId || groupIndex === index));\n });\n }, true);\n });\n }\n if (this.keyboardActionsEnabled) {\n this.refs['sidebar-component'].forEach((component) => {\n this.addEventListener(component, 'keydown', (event) => {\n if (event.keyCode === 13) {\n this.addNewComponent(component);\n }\n });\n });\n }\n this.addEventListener(this.refs['sidebar-search'], 'input', lodash_1.default.debounce((e) => {\n const searchString = e.target.value;\n this.searchFields(searchString);\n }, 300));\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n const drake = this.dragula;\n if (this.refs.form) {\n (0, dom_autoscroller_1.default)([window], {\n margin: 20,\n maxSpeed: 6,\n scrollWhenOutside: true,\n autoScroll: function () {\n return this.down && (drake === null || drake === void 0 ? void 0 : drake.dragging);\n }\n });\n return this.webform.attach(this.refs.form);\n }\n });\n }\n searchFields(searchString = '') {\n const searchValue = searchString.toLowerCase();\n const sidebar = this.refs['sidebar'];\n const sidebarGroups = this.refs['sidebar-groups'];\n if (!sidebar || !sidebarGroups) {\n return;\n }\n const filterGroupBy = (group, searchValue = '') => {\n const result = lodash_1.default.toPlainObject(group);\n const { subgroups = [], components } = result;\n const filteredComponents = [];\n for (const key in components) {\n const isMatchedToTitle = this.t(components[key].title).toLowerCase().match(searchValue);\n const isMatchedToKey = components[key].key.toLowerCase().match(searchValue);\n if (isMatchedToTitle || isMatchedToKey) {\n filteredComponents.push(components[key]);\n }\n }\n this.orderComponents(result, filteredComponents);\n if (searchValue) {\n result.default = true;\n }\n if (result.componentOrder.length || subgroups.length) {\n return result;\n }\n return null;\n };\n const filterGroupOrder = (groupOrder, searchValue) => {\n const result = lodash_1.default.cloneDeep(groupOrder);\n return result.filter(key => filterGroupBy(this.groups[key], searchValue));\n };\n const filterSubgroups = (groups, searchValue) => {\n const result = lodash_1.default.clone(groups);\n return result\n .map(subgroup => filterGroupBy(subgroup, searchValue))\n .filter(subgroup => !lodash_1.default.isNull(subgroup));\n };\n const toTemplate = groupKey => {\n return {\n group: filterGroupBy(this.groups[groupKey], searchValue),\n groupKey,\n groupId: sidebar.id || sidebarGroups.id,\n subgroups: filterSubgroups(this.groups[groupKey].subgroups, searchValue)\n .map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n };\n };\n sidebarGroups.innerHTML = filterGroupOrder(this.groupOrder, searchValue)\n .map(groupKey => this.renderTemplate('builderSidebarGroup', toTemplate(groupKey)))\n .join('');\n this.loadRefs(this.element, {\n 'sidebar-groups': 'single',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n });\n this.updateDragAndDrop();\n if (searchValue === '') {\n this.triggerRedraw();\n }\n }\n orderComponents(groupInfo, foundComponents) {\n const components = foundComponents || groupInfo.components;\n const isResource = groupInfo.key.indexOf('resource-') === 0;\n if (components) {\n groupInfo.componentOrder = Object.keys(components)\n .map(key => components[key])\n .filter(component => component && !component.ignore && !component.ignoreForForm)\n .sort((a, b) => a.weight - b.weight)\n .map(component => isResource ? `component-${component.key}` : component.key);\n }\n }\n updateDragAndDrop() {\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n if (this.refs.form) {\n return this.webform.attach(this.refs.form);\n }\n }\n initDragula() {\n const options = this.options;\n if (this.dragula) {\n this.dragula.destroy();\n }\n const containersArray = Array.prototype.slice.call(this.refs['sidebar-container']).filter(item => {\n return item.id !== 'group-container-resource';\n });\n if (!dragula_1.default) {\n return;\n }\n this.dragula = (0, dragula_1.default)(containersArray, {\n moves(el) {\n let moves = true;\n const list = Array.from(el.classList).filter(item => item.indexOf('formio-component-') === 0);\n list.forEach(item => {\n const key = item.slice('formio-component-'.length);\n if (options.disabled && options.disabled.includes(key)) {\n moves = false;\n }\n });\n if (el.classList.contains('no-drag')) {\n moves = false;\n }\n return moves;\n },\n copy(el) {\n return el.classList.contains('drag-copy');\n },\n accepts(el, target) {\n return !el.contains(target) && !target.classList.contains('no-drop');\n }\n }).on('drop', (element, target, source, sibling) => this.onDrop(element, target, source, sibling));\n }\n detach() {\n if (this.dragula) {\n this.dragula.destroy();\n }\n this.dragula = null;\n if (this.sideBarScroll && Templates_1.default.current.clearBuilderSidebarScroll) {\n Templates_1.default.current.clearBuilderSidebarScroll.call(this, this);\n }\n super.detach();\n }\n getComponentInfo(key, group) {\n let info;\n // Need to check in first order as resource component key can be the same as from webform default components\n if (group && group.slice(0, group.indexOf('-')) === 'resource') {\n // This is an existing resource field.\n const resourceGroups = this.groups.resource.subgroups;\n const resourceGroup = lodash_1.default.find(resourceGroups, { key: group });\n if (resourceGroup && resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n }\n }\n // This is a new component\n else if (this.schemas.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(this.schemas[key]);\n }\n else if (this.groups.hasOwnProperty(group)) {\n const groupComponents = this.groups[group].components;\n if (groupComponents.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(groupComponents[key].schema);\n }\n }\n else if (group === 'searchFields') { //Search components go into this group\n const resourceGroups = this.groups.resource.subgroups;\n for (let ix = 0; ix < resourceGroups.length; ix++) {\n const resourceGroup = resourceGroups[ix];\n if (resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n break;\n }\n }\n }\n if (info) {\n //if this is a custom component that was already assigned a key, don't stomp on it\n if (!Components_1.default.components.hasOwnProperty(info.type) && info.key) {\n return info;\n }\n info.key = this.generateKey(info);\n }\n return info;\n }\n getComponentsPath(component, parent) {\n // Get path to the component in the parent component.\n let path = 'components';\n let columnIndex = 0;\n let tableRowIndex = 0;\n let tableColumnIndex = 0;\n let tabIndex = 0;\n switch (parent.type) {\n case 'table':\n tableRowIndex = lodash_1.default.findIndex(parent.rows, row => row.some(column => column.components.some(comp => comp.key === component.key)));\n tableColumnIndex = lodash_1.default.findIndex(parent.rows[tableRowIndex], (column => column.components.some(comp => comp.key === component.key)));\n path = `rows[${tableRowIndex}][${tableColumnIndex}].components`;\n break;\n case 'columns':\n columnIndex = lodash_1.default.findIndex(parent.columns, column => column.components.some(comp => comp.key === component.key));\n path = `columns[${columnIndex}].components`;\n break;\n case 'tabs':\n tabIndex = lodash_1.default.findIndex(parent.components, tab => tab.components.some(comp => comp.key === component.key));\n path = `components[${tabIndex}].components`;\n break;\n }\n return path;\n }\n /* eslint-disable max-statements */\n onDrop(element, target, source, sibling) {\n var _a;\n if (!target) {\n return;\n }\n // If you try to drop within itself.\n if (element.contains(target)) {\n return;\n }\n const key = element.getAttribute('data-key');\n const type = element.getAttribute('data-type');\n const group = element.getAttribute('data-group');\n let info, isNew, path, index;\n if (key && group) {\n // This is a new component.\n info = this.getComponentInfo(key, group);\n if (!info && type) {\n info = this.getComponentInfo(type, group);\n }\n isNew = true;\n }\n else if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n // Grab and remove the component from the source container.\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n // Since splice returns an array of one object, we need to destructure it.\n info = info[0];\n }\n }\n // If we haven't found the component, stop.\n if (!info) {\n return;\n }\n // Show an error if siblings are disabled for a component and such a component already exists.\n const compKey = (group === 'resource') ? `component-${key}` : key;\n const draggableComponent = ((_a = this.groups[group]) === null || _a === void 0 ? void 0 : _a.components[compKey]) || {};\n if (draggableComponent.disableSiblings) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.type === draggableComponent.schema.type) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.key} component to one page.`);\n return;\n }\n }\n if (draggableComponent.uniqueComponent) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.key === draggableComponent.schema.key) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.title} component to one page.`);\n return;\n }\n }\n if (target !== source) {\n // Ensure the key remains unique in its new container.\n builder_1.default.uniquify(this.findNamespaceRoot(target.formioComponent), info);\n }\n const parent = target.formioComponent;\n // Insert in the new container.\n if (target.formioContainer) {\n if (sibling) {\n if (!sibling.getAttribute('data-noattach')) {\n index = lodash_1.default.findIndex(target.formioContainer, { key: lodash_1.default.get(sibling, 'formioComponent.component.key') });\n index = (index === -1) ? 0 : index;\n }\n else {\n index = sibling.getAttribute('data-position');\n }\n if (index !== -1) {\n target.formioContainer.splice(index, 0, info);\n }\n }\n else {\n target.formioContainer.push(info);\n }\n path = this.getComponentsPath(info, parent.component);\n index = lodash_1.default.findIndex(lodash_1.default.get(parent.schema, path), { key: info.key });\n if (index === -1) {\n index = 0;\n }\n }\n if (parent && parent.addChildComponent) {\n parent.addChildComponent(info, element, target, source, sibling);\n }\n const componentInDataGrid = parent.type === 'datagrid';\n if (isNew && !this.options.noNewEdit && !info.noNewEdit && !(this.options.design && info.type === 'reviewpage')) {\n this.editComponent(info, target, isNew, null, null, { inDataGrid: componentInDataGrid });\n }\n // Only rebuild the parts needing to be rebuilt.\n let rebuild;\n if (target !== source) {\n if (source.formioContainer && source.contains(target)) {\n rebuild = source.formioComponent.rebuild();\n }\n else if (target.contains(source)) {\n rebuild = target.formioComponent.rebuild();\n }\n else {\n if (source.formioContainer) {\n rebuild = source.formioComponent.rebuild();\n }\n rebuild = target.formioComponent.rebuild();\n }\n }\n else {\n // If they are the same, only rebuild one.\n rebuild = target.formioComponent.rebuild();\n }\n if (!rebuild) {\n rebuild = Promise.resolve();\n }\n return rebuild.then(() => {\n this.emit('addComponent', info, parent, path, index, isNew && !this.options.noNewEdit && !info.noNewEdit);\n if (!isNew || this.options.noNewEdit || info.noNewEdit) {\n this.emit('change', this.form);\n }\n });\n }\n setForm(form) {\n var _a;\n if (!form.components) {\n form.components = [];\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n this.keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n const isShowSubmitButton = !this.options.noDefaultSubmitButton\n && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));\n // Ensure there is at least a submit button.\n if (isShowSubmitButton) {\n form.components.push({\n type: 'button',\n label: 'Submit',\n key: 'submit',\n size: 'md',\n block: false,\n action: 'submit',\n disableOnInvalid: true,\n theme: 'primary'\n });\n }\n if (this.webform) {\n const shouldRebuild = !this.webform.form.components ||\n (form.components.length !== this.webform.form.components.length);\n return this.webform.setForm(form, { keepAsReference: true }).then(() => {\n if (this.refs.form) {\n this.builderHeight = this.refs.form.offsetHeight;\n }\n if (!shouldRebuild) {\n return this.form;\n }\n return this.rebuild().then(() => this.form);\n });\n }\n return Promise.resolve(form);\n }\n populateCaptchaSettings(form) {\n //populate isEnabled for captcha form settings\n let isCaptchaEnabled = false;\n if (this.form.components) {\n (0, formUtils_1.eachComponent)(form.components, component => {\n if (isCaptchaEnabled) {\n return;\n }\n if (component.type === 'captcha') {\n isCaptchaEnabled = true;\n return false;\n }\n });\n if (isCaptchaEnabled) {\n lodash_1.default.set(form, 'settings.captcha.isEnabled', true);\n }\n else if (lodash_1.default.get(form, 'settings.captcha.isEnabled')) {\n lodash_1.default.set(form, 'settings.captcha.isEnabled', false);\n }\n }\n }\n removeComponent(component, parent, original, componentInstance) {\n if (!parent) {\n return;\n }\n let remove = true;\n const removingComponentsGroup = !component.skipRemoveConfirm &&\n ((Array.isArray(component.components) && component.components.length) ||\n (Array.isArray(component.rows) && component.rows.length) ||\n (Array.isArray(component.columns) && component.columns.length));\n if (this.options.alwaysConfirmComponentRemoval || removingComponentsGroup) {\n const message = removingComponentsGroup ? 'Removing this component will also remove all of its children. Are you sure you want to do this?'\n : 'Are you sure you want to remove this component?';\n remove = window.confirm(this.t(message));\n }\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parent.formioContainer ? parent.formioContainer.indexOf(original) : 0;\n if (remove && index !== -1) {\n const path = this.getComponentsPath(component, parent.formioComponent.component);\n if (parent.formioContainer) {\n parent.formioContainer.splice(index, 1);\n }\n else if (parent.formioComponent && parent.formioComponent.removeChildComponent) {\n parent.formioComponent.removeChildComponent(component);\n }\n if (component.input && componentInstance && parent.formioComponent) {\n const parentDefaultValue = lodash_1.default.get(parent.formioComponent, 'component.defaultValue', null);\n if (Array.isArray(parentDefaultValue)) {\n parentDefaultValue.forEach(v => lodash_1.default.unset(v, componentInstance.key));\n }\n else if (typeof parentDefaultValue === 'object') {\n lodash_1.default.unset(parentDefaultValue, componentInstance.key);\n }\n }\n const rebuild = parent.formioComponent.rebuild() || Promise.resolve();\n rebuild.then(() => {\n this.emit('removeComponent', component, parent.formioComponent.schema, path, index);\n this.emit('change', this.form);\n });\n }\n return remove;\n }\n replaceDoubleQuotes(data, fieldsToRemoveDoubleQuotes = []) {\n if (data) {\n fieldsToRemoveDoubleQuotes.forEach((key) => {\n if (data[key]) {\n data[key] = data[key].replace(/\"/g, \"'\");\n }\n });\n return data;\n }\n }\n updateComponent(component, changed) {\n const sanitizeConfig = lodash_1.default.get(this.webform, 'form.settings.sanitizeConfig') || lodash_1.default.get(this.webform, 'form.globalSettings.sanitizeConfig');\n // Update the preview.\n if (this.preview) {\n this.preview.form = {\n components: [lodash_1.default.omit(Object.assign({}, component), [\n 'hidden',\n 'conditional',\n 'calculateValue',\n 'logic',\n 'autofocus',\n 'customConditional',\n ])],\n config: this.options.formConfig || {},\n sanitizeConfig,\n };\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.preview.form.components.forEach(component => this.replaceDoubleQuotes(component, fieldsToRemoveDoubleQuotes));\n const previewElement = this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"preview\"]`);\n if (previewElement) {\n this.setContent(previewElement, this.preview.render(), null, sanitizeConfig);\n this.preview.attach(previewElement);\n }\n }\n // Change the \"default value\" field to be reflective of this component.\n const defaultValueComponent = (0, formUtils_1.getComponent)(this.editForm.components, 'defaultValue', true);\n if (defaultValueComponent && component.type !== 'hidden') {\n const defaultChanged = changed && ((changed.component && changed.component.key === 'defaultValue')\n || (changed.instance && defaultValueComponent.hasComponent && defaultValueComponent.hasComponent(changed.instance)));\n if (!defaultChanged) {\n lodash_1.default.assign(defaultValueComponent.component, lodash_1.default.omit(Object.assign({}, component), [\n 'key',\n 'label',\n 'labelPosition',\n 'labelMargin',\n 'labelWidth',\n 'placeholder',\n 'tooltip',\n 'hidden',\n 'autofocus',\n 'validate',\n 'disabled',\n 'defaultValue',\n 'customDefaultValue',\n 'calculateValue',\n 'conditional',\n 'customConditional',\n 'id'\n ]));\n const parentComponent = defaultValueComponent.parent;\n let tabIndex = -1;\n let index = -1;\n parentComponent.tabs.some((tab, tIndex) => {\n tab.some((comp, compIndex) => {\n if (comp.id === defaultValueComponent.id) {\n tabIndex = tIndex;\n index = compIndex;\n return true;\n }\n return false;\n });\n });\n if (tabIndex !== -1 && index !== -1 && changed && !lodash_1.default.isNil(changed.value)) {\n const sibling = parentComponent.tabs[tabIndex][index + 1];\n parentComponent.removeComponent(defaultValueComponent);\n const newComp = parentComponent.addComponent(defaultValueComponent.component, defaultValueComponent.data, sibling);\n lodash_1.default.pull(newComp.validators, 'required');\n parentComponent.tabs[tabIndex].splice(index, 1, newComp);\n newComp.checkValidity = () => true;\n newComp.checkComponentValidity = () => true;\n newComp.build(defaultValueComponent.element);\n }\n }\n else {\n let dataPath = changed.instance._data.key;\n const path = (0, utils_1.getArrayFromComponentPath)(changed.instance.path);\n path.shift();\n if (path.length) {\n path.unshift(component.key);\n dataPath = (0, utils_1.getStringFromComponentPath)(path);\n }\n lodash_1.default.set(this.preview._data, dataPath, changed.value);\n lodash_1.default.set(this.webform._data, dataPath, changed.value);\n }\n }\n // Called when we update a component.\n this.emit('updateComponent', component);\n }\n findRepeatablePaths() {\n const repeatablePaths = [];\n const keys = new Map();\n (0, formUtils_1.eachComponent)(this.form.components, (comp, path) => {\n if (!comp.key) {\n return;\n }\n if (keys.has(comp.key)) {\n if (keys.get(comp.key).includes(path)) {\n repeatablePaths.push(path);\n }\n else {\n keys.set(comp.key, [...keys.get(comp.key), path]);\n }\n }\n else {\n keys.set(comp.key, [path]);\n }\n }, true);\n return repeatablePaths;\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n let hasInvalidComponents = false;\n this.webform.everyComponent((comp) => {\n const path = comp.path;\n if (repeatablePaths.includes(path)) {\n comp.setCustomValidity(this.t('apiKey', { key: comp.key }));\n hasInvalidComponents = true;\n }\n });\n this.emit('builderFormValidityChange', hasInvalidComponents);\n }\n /**\n * Called when a new component is saved.\n * @param {Component} component - The component instance to save.\n * @param {Component} parent - The parent component.\n * @param {boolean} isNew - If this is a new component.\n * @param {Component} original - The original component.\n * @returns {boolean} - If the component was saved.\n */\n saveComponent(component, parent, isNew, original) {\n this.editForm.detach();\n const parentContainer = parent ? parent.formioContainer : this.container;\n const parentComponent = parent ? parent.formioComponent : this;\n this.dialog.close();\n const path = parentContainer ? this.getComponentsPath(component, parentComponent.component) : '';\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parentContainer ? parentContainer.indexOf(original) : 0;\n if (index !== -1) {\n let submissionData = this.editForm.submission.data;\n submissionData = submissionData.componentJson || submissionData;\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.replaceDoubleQuotes(submissionData, fieldsToRemoveDoubleQuotes);\n this.hook('beforeSaveComponentSettings', submissionData);\n let comp = null;\n parentComponent.getComponents().forEach((component) => {\n if (component.component.key === original.key) {\n comp = component;\n }\n });\n const originalComp = comp === null || comp === void 0 ? void 0 : comp.component;\n const originalComponentSchema = comp === null || comp === void 0 ? void 0 : comp.schema;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parentContainer && !isParentSaveChildMethod) {\n parentContainer[index] = submissionData;\n if (comp) {\n comp.component = submissionData;\n }\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(submissionData);\n }\n const rebuild = parentComponent.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n const schema = parentContainer ? parentContainer[index] : (comp ? comp.schema : []);\n this.emitSaveComponentEvent(schema, originalComp, parentComponent.schema, path, index, isNew, originalComponentSchema);\n this.emit('change', this.form);\n this.highlightInvalidComponents();\n if (this.isComponentCreated) {\n const component = parent.formioComponent.components[0];\n this.moveComponent(component);\n this.isComponentCreated = false;\n }\n });\n }\n this.highlightInvalidComponents();\n return Promise.resolve();\n }\n emitSaveComponentEvent(schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema) {\n this.emit('saveComponent', schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema);\n }\n attachEditComponentControls(component, parent, isNew, original, ComponentClass) {\n const cancelButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"cancelButton\"]`);\n cancelButtons.forEach((cancelButton) => {\n this.editForm.addEventListener(cancelButton, 'click', (event) => {\n event.preventDefault();\n this.editForm.detach();\n this.emit('cancelComponent', component);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const removeButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"removeButton\"]`);\n removeButtons.forEach((removeButton) => {\n this.editForm.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n // Since we are already removing the component, don't trigger another remove.\n this.saved = true;\n this.editForm.detach();\n this.removeComponent(component, parent, original);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const saveButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"saveButton\"]`);\n saveButtons.forEach((saveButton) => {\n this.editForm.addEventListener(saveButton, 'click', (event) => {\n event.preventDefault();\n const errors = this.editForm.validate(this.editForm.data, {\n dirty: true\n });\n if (errors.length) {\n this.editForm.setPristine(false);\n this.editForm.showErrors(errors);\n return false;\n }\n this.saved = true;\n this.saveComponent(component, parent, isNew, original);\n });\n });\n const previewButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"previewButton\"]`);\n previewButtons.forEach((previewButton) => {\n this.editForm.addEventListener(previewButton, 'click', (event) => {\n event.preventDefault();\n this.showPreview = !this.showPreview;\n this.editForm.detach();\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks,\n }));\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n });\n });\n }\n editComponent(component, parent, isNew, isJsonEdit, original, flags = {}) {\n var _a, _b;\n if (!component.key) {\n return;\n }\n this.saved = false;\n const componentCopy = (0, utils_1.fastCloneDeep)(component);\n let ComponentClass = Components_1.default.components[componentCopy.type];\n const isCustom = ComponentClass === undefined;\n isJsonEdit = isJsonEdit || isCustom;\n ComponentClass = isCustom ? Components_1.default.components.unknown : ComponentClass;\n // Make sure we only have one dialog open at a time.\n if (this.dialog) {\n this.dialog.close();\n this.highlightInvalidComponents();\n }\n // This is the render step.\n const editFormOptions = lodash_1.default.clone(lodash_1.default.get(this, 'options.editForm', {}));\n if (this.editForm) {\n this.editForm.destroy();\n }\n // Allow editForm overrides per component.\n const overrides = lodash_1.default.get(this.options, `editForm.${componentCopy.type}`, {});\n // Pass along the form being edited.\n editFormOptions.editForm = this.form;\n editFormOptions.editComponent = component;\n editFormOptions.flags = flags;\n this.hook('editComponentParentInstance', editFormOptions, parent);\n this.editForm = new Webform_1.default(Object.assign(Object.assign(Object.assign(Object.assign({}, lodash_1.default.omit(this.options, ['hooks', 'builder', 'events', 'attachMode', 'skipInit'])), { language: this.options.language }), editFormOptions), { evalContext: Object.assign(Object.assign({}, ((editFormOptions === null || editFormOptions === void 0 ? void 0 : editFormOptions.evalContext) || ((_a = this.options) === null || _a === void 0 ? void 0 : _a.evalContext) || {})), { buildingForm: this.form }) }));\n this.hook('editFormProperties', parent);\n this.editForm.form = (isJsonEdit && !isCustom) ? {\n components: [\n {\n type: 'textarea',\n as: 'json',\n editor: 'ace',\n weight: 10,\n input: true,\n key: 'componentJson',\n label: 'Component JSON',\n tooltip: 'Edit the JSON for this component.'\n },\n {\n type: 'checkbox',\n key: 'showFullSchema',\n label: 'Full Schema'\n }\n ]\n } : ComponentClass.editForm(lodash_1.default.cloneDeep(overrides));\n const instanceOptions = {\n inFormBuilder: true,\n };\n this.hook('instanceOptionsPreview', instanceOptions);\n const instance = new ComponentClass(componentCopy, instanceOptions);\n const schema = this.hook('builderComponentSchema', component, instance);\n this.editForm.submission = isJsonEdit ? {\n data: {\n componentJson: schema,\n showFullSchema: this.options.showFullJsonSchema\n },\n } : {\n data: instance.component,\n };\n if (this.preview) {\n this.preview.destroy();\n }\n if (!ComponentClass.builderInfo.hasOwnProperty('preview') || ComponentClass.builderInfo.preview) {\n this.preview = new Webform_1.default(lodash_1.default.omit(Object.assign(Object.assign({}, this.options), { preview: true }), [\n 'hooks',\n 'builder',\n 'events',\n 'attachMode',\n 'calculateValue'\n ]));\n this.hook('previewFormSettitngs', schema, isJsonEdit);\n }\n this.showPreview = (_b = ComponentClass.builderInfo.showPreview) !== null && _b !== void 0 ? _b : true;\n this.componentEdit = this.ce('div', { 'class': 'component-edit-container' });\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks\n }));\n this.dialog = this.createModal(this.componentEdit, lodash_1.default.get(this.options, 'dialogAttr', {}));\n // This is the attach step.\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.hook('editFormWrapper');\n this.updateComponent(componentCopy);\n this.editForm.on('change', (event) => {\n if (event.changed) {\n if (event.changed.component && event.changed.component.key === 'showFullSchema') {\n const { value } = event.changed;\n this.editForm.submission = {\n data: {\n componentJson: value ? instance.component : component,\n showFullSchema: value\n },\n };\n return;\n }\n // See if this is a manually modified key. Treat custom component keys as manually modified\n if ((event.changed.component && (event.changed.component.key === 'key')) || isJsonEdit) {\n componentCopy.keyModified = true;\n }\n let isComponentLabelChanged = false;\n if (event.changed.instance) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.instance.path);\n }\n else if (event.changed.component) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.component.key);\n }\n if (isComponentLabelChanged) {\n // Ensure this component has a key.\n if (isNew) {\n if (!event.data.keyModified) {\n this.editForm.everyComponent(component => {\n if (component.key === 'key' && component.parent.component.key === 'tabs') {\n component.setValue(this.updateComponentKey(event.data));\n return false;\n }\n });\n }\n if (this.form) {\n let formComponents = this.findNamespaceRoot(parent.formioComponent);\n // excluding component which key uniqueness is to be checked to prevent the comparing of the same keys\n formComponents = formComponents.filter(comp => editFormOptions.editComponent.id !== comp.id);\n // Set a unique key for this component.\n builder_1.default.uniquify(formComponents, event.data);\n }\n }\n }\n // If the edit form has any nested form inside, we get a partial data (nested form's data) in the\n // event.data property\n let editFormData;\n if (event.changed.instance && event.changed.instance.root && event.changed.instance.root.id !== this.editForm.id) {\n editFormData = this.editForm.data;\n }\n // Update the component.\n this.updateComponent(event.data.componentJson || editFormData || event.data, event.changed);\n }\n });\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n const dialogClose = () => {\n this.editForm.destroy(true);\n if (this.preview) {\n this.preview.destroy(true);\n this.preview = null;\n }\n if (isNew && !this.saved) {\n this.removeComponent(component, parent, original);\n this.highlightInvalidComponents();\n }\n // Clean up.\n this.removeEventListener(this.dialog, 'close', dialogClose);\n this.dialog = null;\n };\n this.addEventListener(this.dialog, 'close', dialogClose);\n // Called when we edit a component.\n this.emit('editComponent', component);\n }\n updateComponentKey(data) {\n return lodash_1.default.camelCase(data.title ||\n data.label ||\n data.placeholder ||\n data.type).replace(/^[0-9]*/, '');\n }\n moveComponent(component) {\n var _a;\n if (this.selectedComponent) {\n const prevSelected = this.selectedComponent;\n (_a = prevSelected.element) === null || _a === void 0 ? void 0 : _a.classList.remove('builder-component-selected');\n this.removeEventListener(document, 'keydown');\n }\n component.element.focus();\n component.element.classList.add('builder-component-selected');\n this.selectedComponent = component;\n this.addEventListener(document, 'keydown', this.moveHandler.bind(this));\n }\n updateComponentPlacement(direction) {\n const component = this.selectedComponent;\n let index, info;\n const step = direction ? -1 : 1;\n if (component) {\n const element = component.element;\n const sibling = direction ? element.previousElementSibling : element.nextElementSibling;\n const source = element.parentNode;\n const containerLength = source.formioContainer.length;\n if (containerLength && containerLength <= 1) {\n return;\n }\n if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n info = info[0];\n source.removeChild(element);\n }\n }\n const len = source.formioComponent.components.length;\n index = (index === -1) ? 0 : index + step;\n if (index === -1) {\n source.formioContainer.push(info);\n source.appendChild(element);\n }\n else if (index === len) {\n const key = source.formioContainer[0].key;\n index = lodash_1.default.findIndex(source.formioComponent.components, { key: key });\n const firstElement = source.formioComponent.components[index].element;\n source.formioContainer.splice(0, 0, info);\n source.insertBefore(element, firstElement);\n }\n else if (index !== -1) {\n source.formioContainer.splice(index, 0, info);\n direction\n ? source.insertBefore(element, sibling)\n : source.insertBefore(element, sibling.nextElementSibling);\n }\n element.focus();\n }\n }\n stopMoving(comp) {\n const parent = comp.element.parentNode;\n this.removeEventListener(document, 'keydown');\n parent.formioComponent.rebuild();\n this.selectedComponent = null;\n }\n addNewComponent(element) {\n var _a;\n const source = document.querySelector('.formio-builder-form');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const isNew = true;\n let info;\n if (key && group) {\n info = this.getComponentInfo(key, group);\n }\n if (isNew && !this.options.noNewEdit && !info.noNewEdit) {\n builder_1.default.uniquify(this.findNamespaceRoot(source.formioComponent), info);\n this.editComponent(info, source, isNew, null, null);\n }\n const firstComponent = (_a = source.formioComponent.components[0]) === null || _a === void 0 ? void 0 : _a.element;\n if (firstComponent) {\n source.formioContainer.splice(0, 0, info);\n }\n else {\n source.formioContainer.push(info);\n }\n source.formioComponent.rebuild().then(() => {\n this.isComponentCreated = true;\n });\n }\n /**\n * Creates copy of component schema and stores it under sessionStorage.\n * @param {Component} component - The component to copy.\n * @returns {void}\n */\n copyComponent(component) {\n if (!window.sessionStorage) {\n return console.warn('Session storage is not supported in this browser.');\n }\n this.addClass(this.refs.form, 'builder-paste-mode');\n window.sessionStorage.setItem('formio.clipboard', JSON.stringify(component.schema));\n }\n /**\n * Paste copied component after the current component.\n * @param {Component} component - The component to paste after.\n * @returns {void}\n */\n pasteComponent(component) {\n if (!window.sessionStorage) {\n return console.warn('Session storage is not supported in this browser.');\n }\n this.removeClass(this.refs.form, 'builder-paste-mode');\n if (window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n const schema = JSON.parse(data);\n const parent = this.getParentElement(component.element);\n if (parent) {\n builder_1.default.uniquify(this.findNamespaceRoot(parent.formioComponent), schema);\n let path = '';\n let index = 0;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parent.formioContainer && !isParentSaveChildMethod) {\n index = parent.formioContainer.indexOf(component.component);\n path = this.getComponentsPath(schema, parent.formioComponent.component);\n parent.formioContainer.splice(index + 1, 0, schema);\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(schema, false);\n }\n parent.formioComponent.rebuild();\n this.emitSaveComponentEvent(schema, schema, parent.formioComponent.component, path, (index + 1), true, schema);\n }\n this.emit('change', this.form);\n }\n }\n }\n isParentSaveChildMethod(parentComp) {\n return !!(parentComp && parentComp.saveChildComponent);\n }\n getParentElement(element) {\n let container = element;\n do {\n container = container.parentNode;\n } while (container && !container.formioComponent);\n return container;\n }\n addBuilderComponentInfo(component) {\n if (!component || !component.group || !this.groups[component.group]) {\n return;\n }\n component = lodash_1.default.clone(component);\n const groupInfo = this.groups[component.group];\n if (!groupInfo.components.hasOwnProperty(component.key)) {\n groupInfo.components[component.key] = component;\n }\n return component;\n }\n init() {\n if (this.webform) {\n this.webform.init();\n }\n return super.init();\n }\n clear() {\n if (this.webform.initialized) {\n this.webform.clear();\n }\n }\n destroy(all = false) {\n if (this.webform.initialized) {\n this.webform.destroy(all);\n }\n super.destroy(all);\n }\n addBuilderGroup(name, group) {\n if (!this.groups[name]) {\n this.groups[name] = group;\n this.groupOrder.push(name);\n this.triggerRedraw();\n }\n else {\n this.updateBuilderGroup(name, group);\n }\n }\n updateBuilderGroup(name, group) {\n if (this.groups[name]) {\n this.groups[name] = group;\n this.triggerRedraw();\n }\n }\n generateKey(info) {\n return info.key || lodash_1.default.camelCase(info.title ||\n info.label ||\n info.placeholder ||\n info.type);\n }\n}\nexports[\"default\"] = WebformBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/WebformBuilder.js?");
5348
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ./components/_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst builder_1 = __importDefault(__webpack_require__(/*! ./utils/builder */ \"./lib/cjs/utils/builder.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst dom_autoscroller_1 = __importDefault(__webpack_require__(/*! dom-autoscroller */ \"./node_modules/dom-autoscroller/dist/bundle.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ./templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\n__webpack_require__(/*! ./components/builder */ \"./lib/cjs/components/builder.js\");\n// We need this here because dragula pulls in CustomEvent class that requires global to exist.\nif (typeof window !== 'undefined' && typeof window.global === 'undefined') {\n window.global = window;\n}\nconst dragula_1 = __importDefault(__webpack_require__(/*! dragula */ \"./node_modules/dragula/dragula.js\"));\nclass WebformBuilder extends Component_1.default {\n // eslint-disable-next-line max-statements\n constructor() {\n let element, options;\n if (arguments[0] instanceof HTMLElement || arguments[1]) {\n element = arguments[0];\n options = arguments[1];\n }\n else {\n options = arguments[0];\n }\n // Reset skipInit in case PDFBuilder has set it.\n options.skipInit = false;\n options.display = options.display || 'form';\n super(null, options);\n this.moveHandler = (e) => {\n if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13) {\n e.stopPropagation();\n e.preventDefault();\n }\n if (e.keyCode === 38) {\n this.updateComponentPlacement(true);\n }\n if (e.keyCode === 40) {\n this.updateComponentPlacement(false);\n }\n if (e.keyCode === 13) {\n this.stopMoving(this.selectedComponent);\n }\n };\n this.setElement(element);\n this.dragulaLib = dragula_1.default;\n this.builderHeight = 0;\n this.schemas = {};\n this.repeatablePaths = [];\n this.sideBarScroll = lodash_1.default.get(this.options, 'sideBarScroll', true);\n this.sideBarScrollOffset = lodash_1.default.get(this.options, 'sideBarScrollOffset', 0);\n this.dragDropEnabled = true;\n // Setup the builder options.\n this.builder = lodash_1.default.defaultsDeep({}, this.options.builder, this.defaultGroups);\n // Turn off if explicitely said to do so...\n lodash_1.default.each(this.defaultGroups, (config, key) => {\n if (config === false) {\n this.builder[key] = false;\n }\n });\n // Add the groups.////\n this.groups = {};\n this.groupOrder = [];\n for (const group in this.builder) {\n if (this.builder[group]) {\n this.builder[group].key = group;\n this.groups[group] = this.builder[group];\n this.groups[group].components = this.groups[group].components || {};\n this.groups[group].componentOrder = this.groups[group].componentOrder || [];\n this.groups[group].subgroups = Object.keys(this.groups[group].groups || {}).map((groupKey) => {\n this.groups[group].groups[groupKey].componentOrder = Object.keys(this.groups[group].groups[groupKey].components).map((key) => key);\n return this.groups[group].groups[groupKey];\n });\n this.groupOrder.push(this.groups[group]);\n }\n }\n this.groupOrder = this.groupOrder\n .filter(group => group && !group.ignore)\n .sort((a, b) => a.weight - b.weight)\n .map(group => group.key);\n for (const type in Components_1.default.components) {\n const component = Components_1.default.components[type];\n if (component.builderInfo && component.builderInfo.schema) {\n this.schemas[type] = component.builderInfo.schema;\n component.type = type;\n const builderInfo = component.builderInfo;\n builderInfo.key = component.type;\n this.addBuilderComponentInfo(builderInfo);\n }\n }\n // Filter out any extra components.\n // Add the components in each group.\n for (const group in this.groups) {\n const info = this.groups[group];\n for (const key in info.components) {\n const compKey = group === 'resource' ? `component-${key}` : key;\n let comp = info.components[compKey];\n if (comp === true &&\n Components_1.default.components[key] &&\n Components_1.default.components[key].builderInfo) {\n comp = Components_1.default.components[key].builderInfo;\n }\n if (comp && comp.schema) {\n this.schemas[key] = comp.schema;\n info.components[compKey] = comp;\n info.components[compKey].key = key;\n }\n else {\n // Do not include this component in the components array.\n delete info.components[compKey];\n }\n }\n // Order the components.\n this.orderComponents(info);\n }\n this.options.hooks = this.options.hooks || {};\n this.options.hooks.renderComponent = (html, { component, self }) => {\n var _a, _b;\n if (self.type === 'form' && !self.key) {\n const template = this.hook('renderComponentFormTemplate', html.replace('formio-component-form', ''));\n // The main webform shouldn't have this class as it adds extra styles.\n return template;\n }\n if (this.options.disabled && this.options.disabled.includes(self.key) || self.parent.noDragDrop) {\n return html;\n }\n return this.renderTemplate('builderComponent', {\n html,\n disableBuilderActions: (_a = self === null || self === void 0 ? void 0 : self.component) === null || _a === void 0 ? void 0 : _a.disableBuilderActions,\n childComponent: component,\n design: (_b = self === null || self === void 0 ? void 0 : self.options) === null || _b === void 0 ? void 0 : _b.design\n });\n };\n this.options.hooks.renderComponents = (html, { components, self }) => {\n // if Datagrid and already has a component, don't make it droppable.\n if (self.type === 'datagrid' && components.length > 0 || self.noDragDrop) {\n return html;\n }\n if (!components ||\n (!components.length && !components.nodrop) ||\n (self.type === 'form' && components.length <= 1 && (components.length === 0 || components[0].type === 'button'))) {\n html = this.renderTemplate('builderPlaceholder', {\n position: 0\n }) + html;\n }\n return this.renderTemplate('builderComponents', {\n key: self.key,\n type: self.type,\n html,\n });\n };\n this.options.hooks.renderInput = (html, { self }) => {\n if (self.type === 'hidden') {\n return html + self.name;\n }\n return html;\n };\n this.options.hooks.renderLoading = (html, { self }) => {\n if (self.type === 'form' && self.key) {\n return self.name;\n }\n return html;\n };\n this.options.hooks.attachComponents = (element, components, container, component) => {\n // Don't attach if no element was found or component doesn't participate in drag'n'drop.\n if (!element) {\n return;\n }\n if (component.noDragDrop) {\n return element;\n }\n // Attach container and component to element for later reference.\n const containerElement = element.querySelector(`[${this._referenceAttributeName}=\"${component.component.key}-container\"]`) || element;\n containerElement.formioContainer = container;\n containerElement.formioComponent = component;\n // Add container to draggable list.\n if (this.dragula && this.allowDrop(element)) {\n this.dragula.containers.push(containerElement);\n }\n // If this is an existing datagrid element, don't make it draggable.\n if ((component.type === 'datagrid' || component.type === 'datamap') && components.length > 0) {\n return element;\n }\n // Since we added a wrapper, need to return the original element so that we can find the components inside it.\n return element.children[0];\n };\n this.options.hooks.attachDatagrid = (element, component) => {\n component.loadRefs(element, {\n [`${component.key}-container`]: 'single',\n });\n const dataGridContainer = component.refs[`${component.key}-container`];\n if (dataGridContainer) {\n component.attachComponents(dataGridContainer.parentNode, [], component.component.components);\n }\n // Need to set up horizontal rearrangement of fields.\n };\n this.options.hooks.attachComponent = this.attachComponent.bind(this);\n // Load resources tagged as 'builder'\n const query = {\n params: {\n type: 'resource',\n limit: 1000000,\n select: '_id,title,name,components'\n }\n };\n if (this.options && this.options.resourceTag) {\n query.params.tags = [this.options.resourceTag];\n }\n else if (!this.options || !this.options.hasOwnProperty('resourceTag')) {\n query.params.tags = ['builder'];\n }\n const formio = new Formio_1.Formio(Formio_1.Formio.projectUrl);\n const isResourcesDisabled = this.options.builder && this.options.builder.resource === false;\n formio.loadProject().then((project) => {\n if (project && (lodash_1.default.get(project, 'settings.addConfigToForms', false) || lodash_1.default.get(project, 'addConfigToForms', false))) {\n const config = project.config || {};\n this.options.formConfig = config;\n const pathToFormConfig = 'webform._form.config';\n const webformConfig = lodash_1.default.get(this, pathToFormConfig);\n if (this.webform && !webformConfig) {\n lodash_1.default.set(this, pathToFormConfig, config);\n }\n }\n }).catch((err) => {\n console.warn(`Could not load project settings: ${err.message || err}`);\n });\n if (!formio.noProject && !isResourcesDisabled && formio.formsUrl) {\n const resourceOptions = this.options.builder && this.options.builder.resource;\n formio.loadForms(query)\n .then((resources) => {\n if (resources.length) {\n this.builder.resource = {\n title: resourceOptions ? resourceOptions.title : 'Existing Resource Fields',\n key: 'resource',\n weight: resourceOptions ? resourceOptions.weight : 50,\n subgroups: [],\n components: [],\n componentOrder: []\n };\n this.groups.resource = {\n title: resourceOptions ? resourceOptions.title : 'Existing Resource Fields',\n key: 'resource',\n weight: resourceOptions ? resourceOptions.weight : 50,\n subgroups: [],\n components: [],\n componentOrder: []\n };\n if (!this.groupOrder.includes('resource')) {\n this.groupOrder.push('resource');\n }\n this.addExistingResourceFields(resources);\n }\n });\n }\n // Notify components if they need to modify their render.\n this.options.attachMode = 'builder';\n this.webform = this.webform || this.createForm(this.options);\n this.pathComponentsMapping = {};\n this.arrayDataComponentPaths = [];\n this.nestedDataComponents = [];\n this.arrayDataComponents = [];\n }\n allowDrop() {\n return true;\n }\n addExistingResourceFields(resources) {\n lodash_1.default.each(resources, (resource, index) => {\n const resourceKey = `resource-${resource.name}`;\n const subgroup = {\n key: resourceKey,\n title: resource.title,\n components: [],\n componentOrder: [],\n default: index === 0,\n };\n (0, formUtils_1.eachComponent)(resource.components, (component) => {\n if (component.type === 'button')\n return;\n if (this.options &&\n this.options.resourceFilter &&\n (!component.tags || component.tags.indexOf(this.options.resourceFilter) === -1))\n return;\n let componentName = component.label;\n if (!componentName && component.key) {\n componentName = lodash_1.default.upperFirst(component.key);\n }\n subgroup.componentOrder.push(`component-${component.key}`);\n subgroup.components[`component-${component.key}`] = lodash_1.default.merge((0, utils_1.fastCloneDeep)(Components_1.default.components[component.type]\n ? Components_1.default.components[component.type].builderInfo\n : Components_1.default.components['unknown'].builderInfo), {\n key: component.key,\n title: componentName,\n group: 'resource',\n subgroup: resourceKey,\n }, {\n schema: Object.assign(Object.assign({}, component), { label: component.label, key: component.key, lockKey: true, source: (!this.options.noSource ? resource._id : undefined), isNew: true })\n });\n }, true);\n this.groups.resource.subgroups.push(subgroup);\n });\n this.triggerRedraw();\n }\n attachTooltip(component, title) {\n return (0, tippy_js_1.default)(component, {\n allowHTML: true,\n trigger: 'mouseenter focus',\n placement: 'top',\n delay: [200, 0],\n zIndex: 10000,\n content: title\n });\n }\n attachComponent(element, component) {\n if (component instanceof WebformBuilder) {\n return;\n }\n // Add component to element for later reference.\n element.formioComponent = component;\n component.loadRefs(element, {\n removeComponent: 'single',\n editComponent: 'single',\n moveComponent: 'single',\n copyComponent: 'single',\n pasteComponent: 'single',\n editJson: 'single'\n });\n if (component.refs.copyComponent) {\n this.attachTooltip(component.refs.copyComponent, this.t('Copy'));\n component.addEventListener(component.refs.copyComponent, 'click', () => this.copyComponent(component));\n }\n if (component.refs.pasteComponent) {\n const pasteToolTip = this.attachTooltip(component.refs.pasteComponent, this.t('Paste below'));\n component.addEventListener(component.refs.pasteComponent, 'click', () => {\n pasteToolTip.hide();\n this.pasteComponent(component);\n });\n }\n if (component.refs.moveComponent) {\n this.attachTooltip(component.refs.moveComponent, this.t('Move'));\n if (this.keyboardActionsEnabled) {\n component.addEventListener(component.refs.moveComponent, 'click', () => {\n this.moveComponent(component);\n });\n }\n }\n const parent = this.getParentElement(element);\n if (component.refs.editComponent) {\n this.attachTooltip(component.refs.editComponent, this.t('Edit'));\n component.addEventListener(component.refs.editComponent, 'click', () => this.editComponent(component.schema, parent, false, false, component.component, { inDataGrid: component.isInDataGrid }));\n }\n if (component.refs.editJson) {\n this.attachTooltip(component.refs.editJson, this.t('Edit JSON'));\n component.addEventListener(component.refs.editJson, 'click', () => this.editComponent(component.schema, parent, false, true, component.component));\n }\n if (component.refs.removeComponent) {\n this.attachTooltip(component.refs.removeComponent, this.t('Remove'));\n component.addEventListener(component.refs.removeComponent, 'click', () => this.removeComponent(component.schema, parent, component.component, component));\n }\n return element;\n }\n createForm(options) {\n this.webform = new Webform_1.default(this.element, options);\n if (this.element) {\n this.loadRefs(this.element, {\n form: 'single'\n });\n if (this.refs.form) {\n this.webform.element = this.refs.form;\n }\n }\n return this.webform;\n }\n /**\n * Called when everything is ready.\n * @returns {Promise} - Wait for webform to be ready.\n */\n get ready() {\n return this.webform.ready;\n }\n get defaultGroups() {\n return {\n basic: {\n title: 'Basic',\n weight: 0,\n default: true,\n },\n advanced: {\n title: 'Advanced',\n weight: 10\n },\n layout: {\n title: 'Layout',\n weight: 20\n },\n data: {\n title: 'Data',\n weight: 30\n },\n premium: {\n title: 'Premium',\n weight: 40\n }\n };\n }\n redraw() {\n return Webform_1.default.prototype.redraw.call(this);\n }\n get form() {\n return this.webform.form;\n }\n get schema() {\n return this.webform.schema;\n }\n set form(value) {\n this.setForm(value);\n }\n get container() {\n return this.webform.form.components;\n }\n /**\n * When a component sets its api key, we need to check if it is unique within its namespace. Find the namespace root\n * so we can calculate this correctly.\n * @param {import('@formio/core').Component} component - The component to find the namespace root for.\n * @returns {import('@formio/core').Component[]} - The components root for this namespace.\n */\n findNamespaceRoot(component) {\n const path = (0, utils_1.getArrayFromComponentPath)(component.path);\n // First get the component with nested parents.\n let comp = this.webform.getComponent(path);\n comp = Array.isArray(comp) ? comp[0] : comp;\n const namespaceKey = this.recurseNamespace(comp);\n // If there is no key, it is the root form.\n if (!namespaceKey || this.form.key === namespaceKey) {\n return this.form.components;\n }\n const componentSchema = component.component;\n // If the current component is the namespace, we don't need to find it again.\n if (namespaceKey === component.key) {\n return [...componentSchema.components, componentSchema];\n }\n // Get the namespace component so we have the original object.\n const namespaceComponent = (0, formUtils_1.getComponent)(this.form.components, namespaceKey, true);\n return namespaceComponent ? namespaceComponent.components : comp.components;\n }\n recurseNamespace(component) {\n // If there is no parent, we are at the root level.\n if (!component) {\n return null;\n }\n // Some components are their own namespace.\n if (['address', 'container', 'datagrid', 'editgrid', 'dynamicWizard', 'tree'].includes(component.type) || component.tree || component.arrayTree) {\n return component.key;\n }\n // Anything else, keep going up.\n return this.recurseNamespace(component.parent);\n }\n render() {\n return this.renderTemplate('builder', {\n sidebar: this.renderTemplate('builderSidebar', {\n scrollEnabled: this.sideBarScroll,\n groupOrder: this.groupOrder,\n groupId: `builder-sidebar-${this.id}`,\n groups: this.groupOrder.map((groupKey) => this.renderTemplate('builderSidebarGroup', {\n group: this.groups[groupKey],\n groupKey,\n groupId: `builder-sidebar-${this.id}`,\n subgroups: this.groups[groupKey].subgroups.map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n keyboardActionsEnabled: this.keyboardActionsEnabled,\n })),\n }),\n form: this.webform.render(),\n });\n }\n attach(element) {\n this.on('change', (form) => {\n this.populateCaptchaSettings(form);\n this.webform.setAlert(false);\n });\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n form: 'single',\n sidebar: 'single',\n 'sidebar-search': 'single',\n 'sidebar-groups': 'single',\n 'container': 'multiple',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n 'sidebar-component': 'multiple',\n });\n if (this.sideBarScroll && Templates_1.default.current.handleBuilderSidebarScroll) {\n Templates_1.default.current.handleBuilderSidebarScroll.call(this, this);\n }\n // Add the paste status in form\n if (typeof window !== 'undefined' && window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n this.addClass(this.refs.form, 'builder-paste-mode');\n }\n }\n if (!(0, utils_1.bootstrapVersion)(this.options)) {\n const getAttribute = (anchor, attribute) => {\n let elem = anchor.getAttribute(`data-${attribute}`);\n if (!elem) {\n elem = anchor.getAttribute(`data-bs-${attribute}`);\n }\n return elem;\n };\n const hideShow = (group, show) => {\n if (show) {\n group.classList.add(['show']);\n group.style.display = 'inherit';\n }\n else {\n group.classList.remove(['show']);\n group.style.display = 'none';\n }\n };\n // Initialize\n this.refs['sidebar-group'].forEach((group) => {\n hideShow(group, getAttribute(group, 'default') === 'true');\n });\n // Click event\n this.refs['sidebar-anchor'].forEach((anchor, index) => {\n this.addEventListener(anchor, 'click', () => {\n const clickedParentId = getAttribute(anchor, 'parent').slice('#builder-sidebar-'.length);\n const clickedId = getAttribute(anchor, 'target').slice('#group-'.length);\n this.refs['sidebar-group'].forEach((group, groupIndex) => {\n const openByDefault = getAttribute(group, 'default') === 'true';\n const groupId = group.getAttribute('id').slice('group-'.length);\n const groupParent = getAttribute(group, 'parent').slice('#builder-sidebar-'.length);\n hideShow(group, ((openByDefault && groupParent === clickedId) || groupId === clickedParentId || groupIndex === index));\n });\n }, true);\n });\n }\n if (this.keyboardActionsEnabled) {\n this.refs['sidebar-component'].forEach((component) => {\n this.addEventListener(component, 'keydown', (event) => {\n if (event.keyCode === 13) {\n this.addNewComponent(component);\n }\n });\n });\n }\n this.addEventListener(this.refs['sidebar-search'], 'input', lodash_1.default.debounce((e) => {\n const searchString = e.target.value;\n this.searchFields(searchString);\n }, 300));\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n const drake = this.dragula;\n if (this.refs.form) {\n (0, dom_autoscroller_1.default)([window], {\n margin: 20,\n maxSpeed: 6,\n scrollWhenOutside: true,\n autoScroll: function () {\n return this.down && (drake === null || drake === void 0 ? void 0 : drake.dragging);\n }\n });\n return this.webform.attach(this.refs.form);\n }\n });\n }\n searchFields(searchString = '') {\n const searchValue = searchString.toLowerCase();\n const sidebar = this.refs['sidebar'];\n const sidebarGroups = this.refs['sidebar-groups'];\n if (!sidebar || !sidebarGroups) {\n return;\n }\n const filterGroupBy = (group, searchValue = '') => {\n const result = lodash_1.default.toPlainObject(group);\n const { subgroups = [], components } = result;\n const filteredComponents = [];\n for (const key in components) {\n const isMatchedToTitle = this.t(components[key].title).toLowerCase().match(searchValue);\n const isMatchedToKey = components[key].key.toLowerCase().match(searchValue);\n if (isMatchedToTitle || isMatchedToKey) {\n filteredComponents.push(components[key]);\n }\n }\n this.orderComponents(result, filteredComponents);\n if (searchValue) {\n result.default = true;\n }\n if (result.componentOrder.length || subgroups.length) {\n return result;\n }\n return null;\n };\n const filterGroupOrder = (groupOrder, searchValue) => {\n const result = lodash_1.default.cloneDeep(groupOrder);\n return result.filter(key => filterGroupBy(this.groups[key], searchValue));\n };\n const filterSubgroups = (groups, searchValue) => {\n const result = lodash_1.default.clone(groups);\n return result\n .map(subgroup => filterGroupBy(subgroup, searchValue))\n .filter(subgroup => !lodash_1.default.isNull(subgroup));\n };\n const toTemplate = groupKey => {\n return {\n group: filterGroupBy(this.groups[groupKey], searchValue),\n groupKey,\n groupId: sidebar.id || sidebarGroups.id,\n subgroups: filterSubgroups(this.groups[groupKey].subgroups, searchValue)\n .map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n };\n };\n sidebarGroups.innerHTML = filterGroupOrder(this.groupOrder, searchValue)\n .map(groupKey => this.renderTemplate('builderSidebarGroup', toTemplate(groupKey)))\n .join('');\n this.loadRefs(this.element, {\n 'sidebar-groups': 'single',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n });\n this.updateDragAndDrop();\n if (searchValue === '') {\n this.triggerRedraw();\n }\n }\n orderComponents(groupInfo, foundComponents) {\n const components = foundComponents || groupInfo.components;\n const isResource = groupInfo.key.indexOf('resource-') === 0;\n if (components) {\n groupInfo.componentOrder = Object.keys(components)\n .map(key => components[key])\n .filter(component => component && !component.ignore && !component.ignoreForForm)\n .sort((a, b) => a.weight - b.weight)\n .map(component => isResource ? `component-${component.key}` : component.key);\n }\n }\n updateDragAndDrop() {\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n if (this.refs.form) {\n return this.webform.attach(this.refs.form);\n }\n }\n initDragula() {\n const options = this.options;\n if (this.dragula) {\n this.dragula.destroy();\n }\n const containersArray = Array.prototype.slice.call(this.refs['sidebar-container']).filter(item => {\n return item.id !== 'group-container-resource';\n });\n if (!dragula_1.default) {\n return;\n }\n this.dragula = (0, dragula_1.default)(containersArray, {\n moves(el) {\n let moves = true;\n const list = Array.from(el.classList).filter(item => item.indexOf('formio-component-') === 0);\n list.forEach(item => {\n const key = item.slice('formio-component-'.length);\n if (options.disabled && options.disabled.includes(key)) {\n moves = false;\n }\n });\n if (el.classList.contains('no-drag')) {\n moves = false;\n }\n return moves;\n },\n copy(el) {\n return el.classList.contains('drag-copy');\n },\n accepts(el, target) {\n return !el.contains(target) && !target.classList.contains('no-drop');\n }\n }).on('drop', (element, target, source, sibling) => this.onDrop(element, target, source, sibling));\n }\n detach() {\n if (this.dragula) {\n this.dragula.destroy();\n }\n this.dragula = null;\n if (this.sideBarScroll && Templates_1.default.current.clearBuilderSidebarScroll) {\n Templates_1.default.current.clearBuilderSidebarScroll.call(this, this);\n }\n super.detach();\n }\n getComponentInfo(key, group) {\n let info;\n // Need to check in first order as resource component key can be the same as from webform default components\n if (group && group.slice(0, group.indexOf('-')) === 'resource') {\n // This is an existing resource field.\n const resourceGroups = this.groups.resource.subgroups;\n const resourceGroup = lodash_1.default.find(resourceGroups, { key: group });\n if (resourceGroup && resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n }\n }\n // This is a new component\n else if (this.schemas.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(this.schemas[key]);\n }\n else if (this.groups.hasOwnProperty(group)) {\n const groupComponents = this.groups[group].components;\n if (groupComponents.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(groupComponents[key].schema);\n }\n }\n else if (group === 'searchFields') { //Search components go into this group\n const resourceGroups = this.groups.resource.subgroups;\n for (let ix = 0; ix < resourceGroups.length; ix++) {\n const resourceGroup = resourceGroups[ix];\n if (resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n break;\n }\n }\n }\n if (info) {\n //if this is a custom component that was already assigned a key, don't stomp on it\n if (!Components_1.default.components.hasOwnProperty(info.type) && info.key) {\n return info;\n }\n info.key = this.generateKey(info);\n }\n return info;\n }\n getComponentsPath(component, parent) {\n // Get path to the component in the parent component.\n let path = 'components';\n let columnIndex = 0;\n let tableRowIndex = 0;\n let tableColumnIndex = 0;\n let tabIndex = 0;\n switch (parent.type) {\n case 'table':\n tableRowIndex = lodash_1.default.findIndex(parent.rows, row => row.some(column => column.components.some(comp => comp.key === component.key)));\n tableColumnIndex = lodash_1.default.findIndex(parent.rows[tableRowIndex], (column => column.components.some(comp => comp.key === component.key)));\n path = `rows[${tableRowIndex}][${tableColumnIndex}].components`;\n break;\n case 'columns':\n columnIndex = lodash_1.default.findIndex(parent.columns, column => column.components.some(comp => comp.key === component.key));\n path = `columns[${columnIndex}].components`;\n break;\n case 'tabs':\n tabIndex = lodash_1.default.findIndex(parent.components, tab => tab.components.some(comp => comp.key === component.key));\n path = `components[${tabIndex}].components`;\n break;\n }\n return path;\n }\n /* eslint-disable max-statements */\n onDrop(element, target, source, sibling) {\n var _a;\n if (!target) {\n return;\n }\n // If you try to drop within itself.\n if (element.contains(target)) {\n return;\n }\n const key = element.getAttribute('data-key');\n const type = element.getAttribute('data-type');\n const group = element.getAttribute('data-group');\n let info, isNew, path, index;\n if (key && group) {\n // This is a new component.\n info = this.getComponentInfo(key, group);\n if (!info && type) {\n info = this.getComponentInfo(type, group);\n }\n isNew = true;\n }\n else if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n // Grab and remove the component from the source container.\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n // Since splice returns an array of one object, we need to destructure it.\n info = info[0];\n }\n }\n // If we haven't found the component, stop.\n if (!info) {\n return;\n }\n // Show an error if siblings are disabled for a component and such a component already exists.\n const compKey = (group === 'resource') ? `component-${key}` : key;\n const draggableComponent = ((_a = this.groups[group]) === null || _a === void 0 ? void 0 : _a.components[compKey]) || {};\n if (draggableComponent.disableSiblings) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.type === draggableComponent.schema.type) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.key} component to one page.`);\n return;\n }\n }\n if (draggableComponent.uniqueComponent) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.key === draggableComponent.schema.key) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.title} component to one page.`);\n return;\n }\n }\n if (target !== source) {\n // Ensure the key remains unique in its new container.\n builder_1.default.uniquify(this.findNamespaceRoot(target.formioComponent), info);\n }\n const parent = target.formioComponent;\n // Insert in the new container.\n if (target.formioContainer) {\n if (sibling) {\n if (!sibling.getAttribute('data-noattach')) {\n index = lodash_1.default.findIndex(target.formioContainer, { key: lodash_1.default.get(sibling, 'formioComponent.component.key') });\n index = (index === -1) ? 0 : index;\n }\n else {\n index = sibling.getAttribute('data-position');\n }\n if (index !== -1) {\n target.formioContainer.splice(index, 0, info);\n }\n }\n else {\n target.formioContainer.push(info);\n }\n path = this.getComponentsPath(info, parent.component);\n index = lodash_1.default.findIndex(lodash_1.default.get(parent.schema, path), { key: info.key });\n if (index === -1) {\n index = 0;\n }\n }\n if (parent && parent.addChildComponent) {\n parent.addChildComponent(info, element, target, source, sibling);\n }\n const componentInDataGrid = parent.type === 'datagrid';\n if (isNew && !this.options.noNewEdit && !info.noNewEdit && !(this.options.design && info.type === 'reviewpage')) {\n this.editComponent(info, target, isNew, null, null, { inDataGrid: componentInDataGrid });\n }\n // Only rebuild the parts needing to be rebuilt.\n let rebuild;\n if (target !== source) {\n if (source.formioContainer && source.contains(target)) {\n rebuild = source.formioComponent.rebuild();\n }\n else if (target.contains(source)) {\n rebuild = target.formioComponent.rebuild();\n }\n else {\n if (source.formioContainer) {\n rebuild = source.formioComponent.rebuild();\n }\n rebuild = target.formioComponent.rebuild();\n }\n }\n else {\n // If they are the same, only rebuild one.\n rebuild = target.formioComponent.rebuild();\n }\n if (!rebuild) {\n rebuild = Promise.resolve();\n }\n return rebuild.then(() => {\n this.emit('addComponent', info, parent, path, index, isNew && !this.options.noNewEdit && !info.noNewEdit);\n if (!isNew || this.options.noNewEdit || info.noNewEdit) {\n this.emit('change', this.form);\n }\n });\n }\n setForm(form) {\n var _a;\n if (!form.components) {\n form.components = [];\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n this.keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n const isShowSubmitButton = !this.options.noDefaultSubmitButton\n && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));\n // Ensure there is at least a submit button.\n if (isShowSubmitButton) {\n form.components.push({\n type: 'button',\n label: 'Submit',\n key: 'submit',\n size: 'md',\n block: false,\n action: 'submit',\n disableOnInvalid: true,\n theme: 'primary'\n });\n }\n if (this.webform) {\n const shouldRebuild = !this.webform.form.components ||\n (form.components.length !== this.webform.form.components.length);\n return this.webform.setForm(form, { keepAsReference: true }).then(() => {\n if (this.refs.form) {\n this.builderHeight = this.refs.form.offsetHeight;\n }\n if (!shouldRebuild) {\n return this.form;\n }\n return this.rebuild().then(() => this.form);\n });\n }\n return Promise.resolve(form);\n }\n populateCaptchaSettings(form) {\n //populate isEnabled for captcha form settings\n let isCaptchaEnabled = false;\n if (this.form.components) {\n (0, formUtils_1.eachComponent)(form.components, component => {\n if (isCaptchaEnabled) {\n return;\n }\n if (component.type === 'captcha') {\n isCaptchaEnabled = true;\n return false;\n }\n });\n if (isCaptchaEnabled) {\n lodash_1.default.set(form, 'settings.captcha.isEnabled', true);\n }\n else if (lodash_1.default.get(form, 'settings.captcha.isEnabled')) {\n lodash_1.default.set(form, 'settings.captcha.isEnabled', false);\n }\n }\n }\n removeComponent(component, parent, original, componentInstance) {\n if (!parent) {\n return;\n }\n let remove = true;\n const removingComponentsGroup = !component.skipRemoveConfirm &&\n ((Array.isArray(component.components) && component.components.length) ||\n (Array.isArray(component.rows) && component.rows.length) ||\n (Array.isArray(component.columns) && component.columns.length));\n if (this.options.alwaysConfirmComponentRemoval || removingComponentsGroup) {\n const message = removingComponentsGroup ? 'Removing this component will also remove all of its children. Are you sure you want to do this?'\n : 'Are you sure you want to remove this component?';\n remove = window.confirm(this.t(message));\n }\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parent.formioContainer ? parent.formioContainer.indexOf(original) : 0;\n if (remove && index !== -1) {\n const path = this.getComponentsPath(component, parent.formioComponent.component);\n if (parent.formioContainer) {\n parent.formioContainer.splice(index, 1);\n }\n else if (parent.formioComponent && parent.formioComponent.removeChildComponent) {\n parent.formioComponent.removeChildComponent(component);\n }\n if (component.input && componentInstance && parent.formioComponent) {\n const parentDefaultValue = lodash_1.default.get(parent.formioComponent, 'component.defaultValue', null);\n if (Array.isArray(parentDefaultValue)) {\n parentDefaultValue.forEach(v => lodash_1.default.unset(v, componentInstance.key));\n }\n else if (typeof parentDefaultValue === 'object') {\n lodash_1.default.unset(parentDefaultValue, componentInstance.key);\n }\n }\n const rebuild = parent.formioComponent.rebuild() || Promise.resolve();\n rebuild.then(() => {\n this.emit('removeComponent', component, parent.formioComponent.schema, path, index);\n this.emit('change', this.form);\n });\n }\n return remove;\n }\n replaceDoubleQuotes(data, fieldsToRemoveDoubleQuotes = []) {\n if (data) {\n fieldsToRemoveDoubleQuotes.forEach((key) => {\n if (data[key]) {\n data[key] = data[key].replace(/\"/g, \"'\");\n }\n });\n return data;\n }\n }\n updateComponent(component, changed) {\n const sanitizeConfig = lodash_1.default.get(this.webform, 'form.settings.sanitizeConfig') || lodash_1.default.get(this.webform, 'form.globalSettings.sanitizeConfig');\n // Update the preview.\n if (this.preview) {\n this.preview.form = {\n components: [lodash_1.default.omit(Object.assign({}, component), [\n 'hidden',\n 'conditional',\n 'calculateValue',\n 'logic',\n 'autofocus',\n 'customConditional',\n ])],\n config: this.options.formConfig || {},\n sanitizeConfig,\n };\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.preview.form.components.forEach(component => this.replaceDoubleQuotes(component, fieldsToRemoveDoubleQuotes));\n const previewElement = this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"preview\"]`);\n if (previewElement) {\n this.setContent(previewElement, this.preview.render(), null, sanitizeConfig);\n this.preview.attach(previewElement);\n }\n }\n // Change the \"default value\" field to be reflective of this component.\n const defaultValueComponent = (0, formUtils_1.getComponent)(this.editForm.components, 'defaultValue', true);\n if (defaultValueComponent && component.type !== 'hidden') {\n const defaultChanged = changed && ((changed.component && changed.component.key === 'defaultValue')\n || (changed.instance && defaultValueComponent.hasComponent && defaultValueComponent.hasComponent(changed.instance)));\n if (!defaultChanged) {\n lodash_1.default.assign(defaultValueComponent.component, lodash_1.default.omit(Object.assign({}, component), [\n 'key',\n 'label',\n 'labelPosition',\n 'labelMargin',\n 'labelWidth',\n 'placeholder',\n 'tooltip',\n 'hidden',\n 'autofocus',\n 'validate',\n 'disabled',\n 'defaultValue',\n 'customDefaultValue',\n 'calculateValue',\n 'conditional',\n 'customConditional',\n 'id'\n ]));\n const parentComponent = defaultValueComponent.parent;\n let tabIndex = -1;\n let index = -1;\n parentComponent.tabs.some((tab, tIndex) => {\n tab.some((comp, compIndex) => {\n if (comp.id === defaultValueComponent.id) {\n tabIndex = tIndex;\n index = compIndex;\n return true;\n }\n return false;\n });\n });\n if (tabIndex !== -1 && index !== -1 && changed && !lodash_1.default.isNil(changed.value)) {\n const sibling = parentComponent.tabs[tabIndex][index + 1];\n parentComponent.removeComponent(defaultValueComponent);\n const newComp = parentComponent.addComponent(defaultValueComponent.component, defaultValueComponent.data, sibling);\n lodash_1.default.pull(newComp.validators, 'required');\n parentComponent.tabs[tabIndex].splice(index, 1, newComp);\n newComp.checkValidity = () => true;\n newComp.build(defaultValueComponent.element);\n }\n }\n else {\n let dataPath = changed.instance._data.key;\n const path = (0, utils_1.getArrayFromComponentPath)(changed.instance.path);\n path.shift();\n if (path.length) {\n path.unshift(component.key);\n dataPath = (0, utils_1.getStringFromComponentPath)(path);\n }\n lodash_1.default.set(this.preview._data, dataPath, changed.value);\n lodash_1.default.set(this.webform._data, dataPath, changed.value);\n }\n }\n // Called when we update a component.\n this.emit('updateComponent', component);\n }\n findRepeatablePaths() {\n const repeatablePaths = [];\n const keys = new Map();\n (0, formUtils_1.eachComponent)(this.form.components, (comp, path) => {\n if (!comp.key) {\n return;\n }\n if (keys.has(comp.key)) {\n if (keys.get(comp.key).includes(path)) {\n repeatablePaths.push(path);\n }\n else {\n keys.set(comp.key, [...keys.get(comp.key), path]);\n }\n }\n else {\n keys.set(comp.key, [path]);\n }\n }, true);\n return repeatablePaths;\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n let hasInvalidComponents = false;\n this.webform.everyComponent((comp) => {\n const path = comp.path;\n if (repeatablePaths.includes(path)) {\n comp.setCustomValidity(this.t('apiKey', { key: comp.key }));\n hasInvalidComponents = true;\n }\n });\n this.emit('builderFormValidityChange', hasInvalidComponents);\n }\n /**\n * Called when a new component is saved.\n * @param {Component} component - The component instance to save.\n * @param {Component} parent - The parent component.\n * @param {boolean} isNew - If this is a new component.\n * @param {Component} original - The original component.\n * @returns {boolean} - If the component was saved.\n */\n saveComponent(component, parent, isNew, original) {\n this.editForm.detach();\n const parentContainer = parent ? parent.formioContainer : this.container;\n const parentComponent = parent ? parent.formioComponent : this;\n this.dialog.close();\n const path = parentContainer ? this.getComponentsPath(component, parentComponent.component) : '';\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parentContainer ? parentContainer.indexOf(original) : 0;\n if (index !== -1) {\n let submissionData = this.editForm.submission.data;\n submissionData = submissionData.componentJson || submissionData;\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.replaceDoubleQuotes(submissionData, fieldsToRemoveDoubleQuotes);\n this.hook('beforeSaveComponentSettings', submissionData);\n let comp = null;\n parentComponent.getComponents().forEach((component) => {\n if (component.component.key === original.key) {\n comp = component;\n }\n });\n const originalComp = comp === null || comp === void 0 ? void 0 : comp.component;\n const originalComponentSchema = comp === null || comp === void 0 ? void 0 : comp.schema;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parentContainer && !isParentSaveChildMethod) {\n parentContainer[index] = submissionData;\n if (comp) {\n comp.component = submissionData;\n }\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(submissionData);\n }\n const rebuild = parentComponent.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n const schema = parentContainer ? parentContainer[index] : (comp ? comp.schema : []);\n this.emitSaveComponentEvent(schema, originalComp, parentComponent.schema, path, index, isNew, originalComponentSchema);\n this.emit('change', this.form);\n this.highlightInvalidComponents();\n if (this.isComponentCreated) {\n const component = parent.formioComponent.components[0];\n this.moveComponent(component);\n this.isComponentCreated = false;\n }\n });\n }\n this.highlightInvalidComponents();\n return Promise.resolve();\n }\n emitSaveComponentEvent(schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema) {\n this.emit('saveComponent', schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema);\n }\n attachEditComponentControls(component, parent, isNew, original, ComponentClass) {\n const cancelButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"cancelButton\"]`);\n cancelButtons.forEach((cancelButton) => {\n this.editForm.addEventListener(cancelButton, 'click', (event) => {\n event.preventDefault();\n this.editForm.detach();\n this.emit('cancelComponent', component);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const removeButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"removeButton\"]`);\n removeButtons.forEach((removeButton) => {\n this.editForm.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n // Since we are already removing the component, don't trigger another remove.\n this.saved = true;\n this.editForm.detach();\n this.removeComponent(component, parent, original);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const saveButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"saveButton\"]`);\n saveButtons.forEach((saveButton) => {\n this.editForm.addEventListener(saveButton, 'click', (event) => {\n event.preventDefault();\n const errors = this.editForm.validate(this.editForm.data, {\n dirty: true\n });\n if (errors.length) {\n this.editForm.setPristine(false);\n this.editForm.showErrors(errors);\n return false;\n }\n this.saved = true;\n this.saveComponent(component, parent, isNew, original);\n });\n });\n const previewButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"previewButton\"]`);\n previewButtons.forEach((previewButton) => {\n this.editForm.addEventListener(previewButton, 'click', (event) => {\n event.preventDefault();\n this.showPreview = !this.showPreview;\n this.editForm.detach();\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks,\n }));\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n });\n });\n }\n editComponent(component, parent, isNew, isJsonEdit, original, flags = {}) {\n var _a, _b;\n if (!component.key) {\n return;\n }\n this.saved = false;\n const componentCopy = (0, utils_1.fastCloneDeep)(component);\n let ComponentClass = Components_1.default.components[componentCopy.type];\n const isCustom = ComponentClass === undefined;\n isJsonEdit = isJsonEdit || isCustom;\n ComponentClass = isCustom ? Components_1.default.components.unknown : ComponentClass;\n // Make sure we only have one dialog open at a time.\n if (this.dialog) {\n this.dialog.close();\n this.highlightInvalidComponents();\n }\n // This is the render step.\n const editFormOptions = lodash_1.default.clone(lodash_1.default.get(this, 'options.editForm', {}));\n if (this.editForm) {\n this.editForm.destroy();\n }\n // Allow editForm overrides per component.\n const overrides = lodash_1.default.get(this.options, `editForm.${componentCopy.type}`, {});\n // Pass along the form being edited.\n editFormOptions.editForm = this.form;\n editFormOptions.editComponent = component;\n editFormOptions.flags = flags;\n this.hook('editComponentParentInstance', editFormOptions, parent);\n this.editForm = new Webform_1.default(Object.assign(Object.assign(Object.assign(Object.assign({}, lodash_1.default.omit(this.options, ['hooks', 'builder', 'events', 'attachMode', 'skipInit'])), { language: this.options.language }), editFormOptions), { evalContext: Object.assign(Object.assign({}, ((editFormOptions === null || editFormOptions === void 0 ? void 0 : editFormOptions.evalContext) || ((_a = this.options) === null || _a === void 0 ? void 0 : _a.evalContext) || {})), { buildingForm: this.form }) }));\n this.hook('editFormProperties', parent);\n this.editForm.form = (isJsonEdit && !isCustom) ? {\n components: [\n {\n type: 'textarea',\n as: 'json',\n editor: 'ace',\n weight: 10,\n input: true,\n key: 'componentJson',\n label: 'Component JSON',\n tooltip: 'Edit the JSON for this component.'\n },\n {\n type: 'checkbox',\n key: 'showFullSchema',\n label: 'Full Schema'\n }\n ]\n } : ComponentClass.editForm(lodash_1.default.cloneDeep(overrides));\n const instanceOptions = {\n inFormBuilder: true,\n };\n this.hook('instanceOptionsPreview', instanceOptions);\n const instance = new ComponentClass(componentCopy, instanceOptions);\n const schema = this.hook('builderComponentSchema', component, instance);\n this.editForm.submission = isJsonEdit ? {\n data: {\n componentJson: schema,\n showFullSchema: this.options.showFullJsonSchema\n },\n } : {\n data: instance.component,\n };\n if (this.preview) {\n this.preview.destroy();\n }\n if (!ComponentClass.builderInfo.hasOwnProperty('preview') || ComponentClass.builderInfo.preview) {\n this.preview = new Webform_1.default(lodash_1.default.omit(Object.assign(Object.assign({}, this.options), { preview: true }), [\n 'hooks',\n 'builder',\n 'events',\n 'attachMode',\n 'calculateValue'\n ]));\n this.hook('previewFormSettitngs', schema, isJsonEdit);\n }\n this.showPreview = (_b = ComponentClass.builderInfo.showPreview) !== null && _b !== void 0 ? _b : true;\n this.componentEdit = this.ce('div', { 'class': 'component-edit-container' });\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks\n }));\n this.dialog = this.createModal(this.componentEdit, lodash_1.default.get(this.options, 'dialogAttr', {}));\n // This is the attach step.\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.hook('editFormWrapper');\n this.updateComponent(componentCopy);\n this.editForm.on('change', (event) => {\n if (event.changed) {\n if (event.changed.component && event.changed.component.key === 'showFullSchema') {\n const { value } = event.changed;\n this.editForm.submission = {\n data: {\n componentJson: value ? instance.component : component,\n showFullSchema: value\n },\n };\n return;\n }\n // See if this is a manually modified key. Treat custom component keys as manually modified\n if ((event.changed.component && (event.changed.component.key === 'key')) || isJsonEdit) {\n componentCopy.keyModified = true;\n }\n let isComponentLabelChanged = false;\n if (event.changed.instance) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.instance.path);\n }\n else if (event.changed.component) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.component.key);\n }\n if (isComponentLabelChanged) {\n // Ensure this component has a key.\n if (isNew) {\n if (!event.data.keyModified) {\n this.editForm.everyComponent(component => {\n if (component.key === 'key' && component.parent.component.key === 'tabs') {\n component.setValue(this.updateComponentKey(event.data));\n return false;\n }\n });\n }\n if (this.form) {\n let formComponents = this.findNamespaceRoot(parent.formioComponent);\n // excluding component which key uniqueness is to be checked to prevent the comparing of the same keys\n formComponents = formComponents.filter(comp => editFormOptions.editComponent.id !== comp.id);\n // Set a unique key for this component.\n builder_1.default.uniquify(formComponents, event.data);\n }\n }\n }\n // If the edit form has any nested form inside, we get a partial data (nested form's data) in the\n // event.data property\n let editFormData;\n if (event.changed.instance && event.changed.instance.root && event.changed.instance.root.id !== this.editForm.id) {\n editFormData = this.editForm.data;\n }\n // Update the component.\n this.updateComponent(event.data.componentJson || editFormData || event.data, event.changed);\n }\n });\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n const dialogClose = () => {\n this.editForm.destroy(true);\n if (this.preview) {\n this.preview.destroy(true);\n this.preview = null;\n }\n if (isNew && !this.saved) {\n this.removeComponent(component, parent, original);\n this.highlightInvalidComponents();\n }\n // Clean up.\n this.removeEventListener(this.dialog, 'close', dialogClose);\n this.dialog = null;\n };\n this.addEventListener(this.dialog, 'close', dialogClose);\n // Called when we edit a component.\n this.emit('editComponent', component);\n }\n updateComponentKey(data) {\n return lodash_1.default.camelCase(data.title ||\n data.label ||\n data.placeholder ||\n data.type).replace(/^[0-9]*/, '');\n }\n moveComponent(component) {\n var _a;\n if (this.selectedComponent) {\n const prevSelected = this.selectedComponent;\n (_a = prevSelected.element) === null || _a === void 0 ? void 0 : _a.classList.remove('builder-component-selected');\n this.removeEventListener(document, 'keydown');\n }\n component.element.focus();\n component.element.classList.add('builder-component-selected');\n this.selectedComponent = component;\n this.addEventListener(document, 'keydown', this.moveHandler.bind(this));\n }\n updateComponentPlacement(direction) {\n const component = this.selectedComponent;\n let index, info;\n const step = direction ? -1 : 1;\n if (component) {\n const element = component.element;\n const sibling = direction ? element.previousElementSibling : element.nextElementSibling;\n const source = element.parentNode;\n const containerLength = source.formioContainer.length;\n if (containerLength && containerLength <= 1) {\n return;\n }\n if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n info = info[0];\n source.removeChild(element);\n }\n }\n const len = source.formioComponent.components.length;\n index = (index === -1) ? 0 : index + step;\n if (index === -1) {\n source.formioContainer.push(info);\n source.appendChild(element);\n }\n else if (index === len) {\n const key = source.formioContainer[0].key;\n index = lodash_1.default.findIndex(source.formioComponent.components, { key: key });\n const firstElement = source.formioComponent.components[index].element;\n source.formioContainer.splice(0, 0, info);\n source.insertBefore(element, firstElement);\n }\n else if (index !== -1) {\n source.formioContainer.splice(index, 0, info);\n direction\n ? source.insertBefore(element, sibling)\n : source.insertBefore(element, sibling.nextElementSibling);\n }\n element.focus();\n }\n }\n stopMoving(comp) {\n const parent = comp.element.parentNode;\n this.removeEventListener(document, 'keydown');\n parent.formioComponent.rebuild();\n this.selectedComponent = null;\n }\n addNewComponent(element) {\n var _a;\n const source = document.querySelector('.formio-builder-form');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const isNew = true;\n let info;\n if (key && group) {\n info = this.getComponentInfo(key, group);\n }\n if (isNew && !this.options.noNewEdit && !info.noNewEdit) {\n builder_1.default.uniquify(this.findNamespaceRoot(source.formioComponent), info);\n this.editComponent(info, source, isNew, null, null);\n }\n const firstComponent = (_a = source.formioComponent.components[0]) === null || _a === void 0 ? void 0 : _a.element;\n if (firstComponent) {\n source.formioContainer.splice(0, 0, info);\n }\n else {\n source.formioContainer.push(info);\n }\n source.formioComponent.rebuild().then(() => {\n this.isComponentCreated = true;\n });\n }\n /**\n * Creates copy of component schema and stores it under sessionStorage.\n * @param {Component} component - The component to copy.\n * @returns {void}\n */\n copyComponent(component) {\n if (!window.sessionStorage) {\n return console.warn('Session storage is not supported in this browser.');\n }\n this.addClass(this.refs.form, 'builder-paste-mode');\n window.sessionStorage.setItem('formio.clipboard', JSON.stringify(component.schema));\n }\n /**\n * Paste copied component after the current component.\n * @param {Component} component - The component to paste after.\n * @returns {void}\n */\n pasteComponent(component) {\n if (!window.sessionStorage) {\n return console.warn('Session storage is not supported in this browser.');\n }\n this.removeClass(this.refs.form, 'builder-paste-mode');\n if (window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n const schema = JSON.parse(data);\n const parent = this.getParentElement(component.element);\n if (parent) {\n builder_1.default.uniquify(this.findNamespaceRoot(parent.formioComponent), schema);\n let path = '';\n let index = 0;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parent.formioContainer && !isParentSaveChildMethod) {\n index = parent.formioContainer.indexOf(component.component);\n path = this.getComponentsPath(schema, parent.formioComponent.component);\n parent.formioContainer.splice(index + 1, 0, schema);\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(schema, false);\n }\n parent.formioComponent.rebuild();\n this.emitSaveComponentEvent(schema, schema, parent.formioComponent.component, path, (index + 1), true, schema);\n }\n this.emit('change', this.form);\n }\n }\n }\n isParentSaveChildMethod(parentComp) {\n return !!(parentComp && parentComp.saveChildComponent);\n }\n getParentElement(element) {\n let container = element;\n do {\n container = container.parentNode;\n } while (container && !container.formioComponent);\n return container;\n }\n addBuilderComponentInfo(component) {\n if (!component || !component.group || !this.groups[component.group]) {\n return;\n }\n component = lodash_1.default.clone(component);\n const groupInfo = this.groups[component.group];\n if (!groupInfo.components.hasOwnProperty(component.key)) {\n groupInfo.components[component.key] = component;\n }\n return component;\n }\n init() {\n if (this.webform) {\n this.webform.init();\n }\n return super.init();\n }\n clear() {\n if (this.webform.initialized) {\n this.webform.clear();\n }\n }\n destroy(all = false) {\n if (this.webform.initialized) {\n this.webform.destroy(all);\n }\n super.destroy(all);\n }\n addBuilderGroup(name, group) {\n if (!this.groups[name]) {\n this.groups[name] = group;\n this.groupOrder.push(name);\n this.triggerRedraw();\n }\n else {\n this.updateBuilderGroup(name, group);\n }\n }\n updateBuilderGroup(name, group) {\n if (this.groups[name]) {\n this.groups[name] = group;\n this.triggerRedraw();\n }\n }\n generateKey(info) {\n return info.key || lodash_1.default.camelCase(info.title ||\n info.label ||\n info.placeholder ||\n info.type);\n }\n}\nexports[\"default\"] = WebformBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/WebformBuilder.js?");
5349
5349
 
5350
5350
  /***/ }),
5351
5351