@formio/js 5.0.0-rc.82 → 5.0.0-rc.83

Sign up to get free protection for your applications and to get access to all the features.
@@ -5347,7 +5347,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5347
5347
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5348
5348
 
5349
5349
  "use strict";
5350
- 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 let keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n if (typeof keyboardActionsEnabled === 'string') {\n keyboardActionsEnabled = keyboardActionsEnabled === 'true';\n }\n this.keyboardActionsEnabled = keyboardActionsEnabled;\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 'fields.day.required',\n 'fields.month.required',\n 'fields.year.required',\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 var _a;\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.updateComponent((_a = this.editForm.submission.data) !== null && _a !== void 0 ? _a : component);\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?");
5350
+ 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 let keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n if (typeof keyboardActionsEnabled === 'string') {\n keyboardActionsEnabled = keyboardActionsEnabled === 'true';\n }\n this.keyboardActionsEnabled = keyboardActionsEnabled;\n const isSubmitButton = (comp) => {\n return (comp.type === 'button') && ((comp.action === 'submit') || !comp.action);\n };\n const isShowSubmitButton = !this.options.noDefaultSubmitButton\n && (!form.components.length || !form.components.find(comp => isSubmitButton(comp)));\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 'fields.day.required',\n 'fields.month.required',\n 'fields.year.required',\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 var _a;\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.updateComponent((_a = this.editForm.submission.data) !== null && _a !== void 0 ? _a : component);\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?");
5351
5351
 
5352
5352
  /***/ }),
5353
5353
 
@@ -5468,7 +5468,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5468
5468
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5469
5469
 
5470
5470
  "use strict";
5471
- eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/* globals Quill, ClassicEditor, CKEDITOR */\nconst vanilla_text_mask_1 = __webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\");\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst ismobilejs_1 = __importDefault(__webpack_require__(/*! ismobilejs */ \"./node_modules/ismobilejs/esm/index.js\"));\nconst process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nconst Formio_1 = __webpack_require__(/*! ../../../Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Element_1 = __importDefault(__webpack_require__(/*! ../../../Element */ \"./lib/cjs/Element.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst addons_1 = __importDefault(__webpack_require__(/*! ../../../addons */ \"./lib/cjs/addons/index.js\"));\nconst uploadAdapter_1 = __webpack_require__(/*! ../../../providers/storage/uploadAdapter */ \"./lib/cjs/providers/storage/uploadAdapter.js\");\nconst en_1 = __importDefault(__webpack_require__(/*! ../../../translations/en */ \"./lib/cjs/translations/en.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ../../../templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nconst isIEBrowser = FormioUtils.getBrowserInfo().ie;\n/**\n * This is the Component class\n which all elements within the FormioForm derive from.\n */\nclass Component extends Element_1.default {\n static schema(...sources) {\n return lodash_1.default.merge({\n /**\n * Determines if this component provides an input.\n */\n input: true,\n /**\n * The data key for this component (how the data is stored in the database).\n */\n key: '',\n /**\n * The input placeholder for this component.\n */\n placeholder: '',\n /**\n * The input prefix\n */\n prefix: '',\n /**\n * The custom CSS class to provide to this component.\n */\n customClass: '',\n /**\n * The input suffix.\n */\n suffix: '',\n /**\n * If this component should allow an array of values to be captured.\n */\n multiple: false,\n /**\n * The default value of this component.\n */\n defaultValue: null,\n /**\n * If the data of this component should be protected (no GET api requests can see the data)\n */\n protected: false,\n /**\n * Validate if the value of this component should be unique within the form.\n */\n unique: false,\n /**\n * If the value of this component should be persisted within the backend api database.\n */\n persistent: true,\n /**\n * Determines if the component should be within the form, but not visible.\n */\n hidden: false,\n /**\n * If the component should be cleared when hidden.\n */\n clearOnHide: true,\n /**\n * This will refresh this component options when this field changes.\n */\n refreshOn: '',\n /**\n * This will redraw the component when this field changes.\n */\n redrawOn: '',\n /**\n * If this component should be included as a column within a submission table.\n */\n tableView: false,\n /**\n * If this component should be rendering in modal.\n */\n modalEdit: false,\n /**\n * The input label provided to this component.\n */\n label: '',\n dataGridLabel: false,\n labelPosition: 'top',\n description: '',\n errorLabel: '',\n tooltip: '',\n hideLabel: false,\n tabindex: '',\n disabled: false,\n autofocus: false,\n dbIndex: false,\n customDefaultValue: '',\n calculateValue: '',\n calculateServer: false,\n widget: null,\n /**\n * Attributes that will be assigned to the input elements of this component.\n */\n attributes: {},\n /**\n * This will perform the validation on either \"change\" or \"blur\" of the input element.\n */\n validateOn: 'change',\n /**\n * The validation criteria for this component.\n */\n validate: {\n /**\n * If this component is required.\n */\n required: false,\n /**\n * Custom JavaScript validation.\n */\n custom: '',\n /**\n * If the custom validation should remain private (only the backend will see it and execute it).\n */\n customPrivate: false,\n /**\n * If this component should implement a strict date validation if the Calendar widget is implemented.\n */\n strictDateValidation: false,\n multiple: false,\n unique: false\n },\n /**\n * The simple conditional settings for a component.\n */\n conditional: {\n show: null,\n when: null,\n eq: ''\n },\n overlay: {\n style: '',\n left: '',\n top: '',\n width: '',\n height: '',\n },\n allowCalculateOverride: false,\n encrypted: false,\n showCharCount: false,\n showWordCount: false,\n properties: {},\n allowMultipleMasks: false,\n addons: [],\n }, ...sources);\n }\n /**\n * Return the simple condition settings as part of the component.\n * @returns {object} - The simple conditional settings.\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n * @param schema\n * @returns {Array}\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n * @param {object} component - The component JSON you wish to initialize.\n * @param {object} options - The options for this component.\n * @param {object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * The data path to this specific component instance.\n * @type {string}\n */\n this.path = (component === null || component === void 0 ? void 0 : component.key) || '';\n /**\n * An array of all the children components errors.\n */\n this.childErrors = [];\n /**\n * Last validation errors that have occured.\n */\n this._errors = [];\n this._visibleErrors = [];\n /**\n * The Form.io component JSON schema.\n * @type {*}\n */\n this.component = this.mergeSchema(component || {});\n // Add the id to the component.\n this.component.id = this.id;\n this.afterComponentAssign();\n // Save off the original component to be used in logic.\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n /**\n * If the component has been attached\n */\n this.attached = false;\n /**\n * If the component has been rendered\n */\n this.rendered = false;\n /**\n * The data object in which this component resides.\n * @type {*}\n */\n this._data = data || {};\n /**\n * Tool tip text after processing\n * @type {string}\n */\n this.tooltip = '';\n /**\n * The row path of this component.\n * @type {number}\n */\n this.row = this.options.row;\n /**\n * Points to a flat map of child components (if applicable).\n * @type {object}\n */\n this.childComponentsMap = {};\n /**\n * Determines if this component is disabled, or not.\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n * @type {Component}\n */\n this.root = this.options.root || this;\n this.localRoot = this.options.localRoot || this;\n /**\n * If this input has been input and provided value.\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n this._path = '';\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n /**\n * Determines if this component is visible, or not.\n */\n this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;\n this._visible = this._parentVisible && this.conditionallyVisible(null, data);\n this._parentDisabled = false;\n /**\n * The reference attribute name for this component\n */\n this._referenceAttributeName = 'ref';\n /**\n * Used to trigger a new change in this component.\n * @type {Function} - Call to trigger a change in this component.\n */\n let changes = [];\n let lastChanged = null;\n let triggerArgs = [];\n const _triggerChange = lodash_1.default.debounce((...args) => {\n if (this.root) {\n this.root.changing = false;\n }\n triggerArgs = [];\n if (!args[1] && lastChanged) {\n // Set the changed component if one isn't provided.\n args[1] = lastChanged;\n }\n if (lodash_1.default.isEmpty(args[0]) && lastChanged) {\n // Set the flags if it is empty and lastChanged exists.\n args[0] = lastChanged.flags;\n }\n lastChanged = null;\n args[3] = changes;\n const retVal = this.onChange(...args);\n changes = [];\n return retVal;\n }, 100);\n this.triggerChange = (...args) => {\n if (args[1]) {\n // Make sure that during the debounce that we always track lastChanged component, even if they\n // don't provide one later.\n lastChanged = args[1];\n changes.push(lastChanged);\n }\n if (this.root) {\n this.root.changing = true;\n }\n if (args.length) {\n triggerArgs = args;\n }\n return _triggerChange(...triggerArgs);\n };\n /**\n * Used to trigger a redraw event within this component.\n * @type {Function}\n */\n this.triggerRedraw = lodash_1.default.debounce(this.redraw.bind(this), 100);\n /**\n * list of attached tooltips\n * @type {Array}\n */\n this.tooltips = [];\n /**\n * List of attached addons\n * @type {Array}\n */\n this.addons = [];\n // To force this component to be invalid.\n this.invalid = false;\n if (this.component) {\n this.type = this.component.type;\n if (this.allowData && this.key) {\n this.options.name += `[${this.key}]`;\n // If component is visible or not set to clear on hide, set the default value.\n if (this.visible || !this.component.clearOnHide) {\n if (!this.hasValue()) {\n if (this.shouldAddDefaultValue) {\n this.dataValue = this.defaultValue;\n }\n }\n else {\n // Ensure the dataValue is set.\n /* eslint-disable no-self-assign */\n this.dataValue = this.dataValue;\n /* eslint-enable no-self-assign */\n }\n }\n }\n /**\n * The element information for creating the input element.\n * @type {*}\n */\n this.info = this.elementInfo();\n }\n // Allow anyone to hook into the component creation.\n this.hook('component');\n if (!this.options.skipInit) {\n this.init();\n }\n }\n /* eslint-enable max-statements */\n get componentsMap() {\n var _a;\n if ((_a = this.localRoot) === null || _a === void 0 ? void 0 : _a.childComponentsMap) {\n return this.localRoot.childComponentsMap;\n }\n const localMap = {};\n localMap[this.path] = this;\n return localMap;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n }\n mergeSchema(component = {}) {\n return lodash_1.default.defaultsDeep(component, this.defaultSchema);\n }\n // Allow componets to notify when ready.\n get ready() {\n return Promise.resolve(this);\n }\n get isPDFReadOnlyMode() {\n return this.parent &&\n this.parent.form &&\n (this.parent.form.display === 'pdf') &&\n this.options.readOnly;\n }\n get labelInfo() {\n const label = {};\n label.hidden = this.labelIsHidden();\n label.className = '';\n label.labelPosition = this.component.labelPosition;\n label.tooltipClass = `${this.iconClass('question-sign')} text-muted`;\n const isPDFReadOnlyMode = this.isPDFReadOnlyMode;\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required) && !isPDFReadOnlyMode) {\n label.className += ' field-required';\n }\n if (label.hidden) {\n label.className += ' control-label--hidden';\n }\n if (this.info.attr.id) {\n label.for = this.info.attr.id;\n }\n return label;\n }\n init() {\n var _a;\n this.disabled = this.shouldDisabled;\n this._visible = this.conditionallyVisible(null, null);\n if ((_a = this.component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n this.component.addons.forEach((addon) => this.createAddon(addon));\n }\n }\n afterComponentAssign() {\n //implement in extended classes\n }\n createAddon(addonConfiguration) {\n var _a;\n const name = addonConfiguration.name;\n if (!name) {\n return;\n }\n const settings = ((_a = addonConfiguration.settings) === null || _a === void 0 ? void 0 : _a.data) || {};\n const Addon = addons_1.default[name.value];\n let addon = null;\n if (Addon) {\n const supportedComponents = Addon.info.supportedComponents;\n const supportsThisComponentType = !(supportedComponents === null || supportedComponents === void 0 ? void 0 : supportedComponents.length) ||\n supportedComponents.indexOf(this.component.type) !== -1;\n if (supportsThisComponentType) {\n addon = new Addon(settings, this);\n this.addons.push(addon);\n }\n else {\n console.warn(`Addon ${name.label} does not support component of type ${this.component.type}.`);\n }\n }\n return addon;\n }\n teardown() {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n delete this._currentForm;\n delete this.parent;\n delete this.root;\n delete this.triggerChange;\n delete this.triggerRedraw;\n if (this.options) {\n delete this.options.root;\n delete this.options.parent;\n delete this.options.i18next;\n }\n super.teardown();\n }\n destroy(all = false) {\n super.destroy(all);\n this.detach();\n this.addons.forEach((addon) => addon.destroy());\n if (all) {\n this.teardown();\n }\n }\n get shouldDisabled() {\n return this.options.readOnly || this.component.disabled || (this.options.hasOwnProperty('disabled') && this.options.disabled[this.key]);\n }\n get isInputComponent() {\n return !this.component.hasOwnProperty('input') || this.component.input;\n }\n get allowData() {\n return this.hasInput;\n }\n get hasInput() {\n return this.isInputComponent || (this.refs.input && this.refs.input.length);\n }\n get defaultSchema() {\n return Component.schema();\n }\n get key() {\n return lodash_1.default.get(this.component, 'key', '');\n }\n set parentVisible(value) {\n this._parentVisible = value;\n }\n get parentVisible() {\n return this._parentVisible;\n }\n set parentDisabled(value) {\n this._parentDisabled = value;\n }\n get parentDisabled() {\n return this._parentDisabled;\n }\n shouldForceVisibility(component, visibility) {\n if (!this.options[visibility]) {\n return false;\n }\n if (!component) {\n component = this.component;\n }\n if (lodash_1.default.isArray(this.options[visibility])) {\n return this.options[visibility].includes(component.key);\n }\n return this.options[visibility][component.key];\n }\n shouldForceHide(component) {\n return this.shouldForceVisibility(component, 'hide');\n }\n shouldForceShow(component) {\n return this.shouldForceVisibility(component, 'show');\n }\n /**\n * Sets the component visibility.\n * @param {boolean} value - Whether the component should be visible or not.\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n * Returns the component visibility\n * @returns {boolean} - Whether the component is visible or not.\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n * @param {object} schema - The \"full\" json schema for the component.\n * @param {object} defaultSchema - The \"default\" json schema for the component.\n * @param {boolean} recursion - If we are currently in a recursive loop.\n * @returns {object} - The minified json schema for this component.\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n * @returns {object} - The JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n * @returns {boolean} - True if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n * @param {string} text - The i18n identifier.\n * @param {object} params - The i18n parameters to use for translation.\n * @param {...any} args - Additional arguments to pass to the translation library.\n * @returns {string} - The translated text.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = params.data || this.rootValue;\n params.row = params.row || this.data;\n params.component = params.component || this.component;\n return super.t(text, params, ...args);\n }\n labelIsHidden() {\n return !this.component.label ||\n ((!this.isInDataGrid && this.component.hideLabel) ||\n (this.isInDataGrid && !this.component.dataGridLabel) ||\n this.options.floatingLabels ||\n this.options.inputsOnly) && !this.builderMode;\n }\n transform(type, value) {\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n return frameworkTemplates.hasOwnProperty('transform')\n ? frameworkTemplates.transform(type, value, this)\n : (type, value) => value;\n }\n getTemplate(names, modes) {\n modes = Array.isArray(modes) ? modes : [modes];\n names = Array.isArray(names) ? names : [names];\n if (!modes.includes('form')) {\n modes.push('form');\n }\n let result = null;\n if (this.options.templates) {\n result = this.checkTemplate(this.options.templates, names, modes);\n if (result) {\n return result;\n }\n }\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n result = this.checkTemplate(frameworkTemplates, names, modes);\n if (result) {\n return result;\n }\n // Default back to bootstrap if not defined.\n const name = names[names.length - 1];\n const templatesByName = Templates_1.default.defaultTemplates[name];\n if (!templatesByName) {\n return { template: `Unknown template: ${name}` };\n }\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return { template: templateByMode };\n }\n return { template: templatesByName.form };\n }\n checkTemplate(templates, names, modes) {\n for (const name of names) {\n const templatesByName = templates[name];\n if (templatesByName) {\n const { referenceAttributeName } = templatesByName;\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return { template: templateByMode, referenceAttributeName };\n }\n }\n }\n return null;\n }\n checkTemplateMode(templatesByName, modes) {\n for (const mode of modes) {\n const templateByMode = templatesByName[mode];\n if (templateByMode) {\n return templateByMode;\n }\n }\n return null;\n }\n getFormattedAttribute(attr) {\n return attr ? this.t(attr, { _userInput: true }).replace(/\"/g, '&quot;') : '';\n }\n getFormattedTooltip(tooltipValue) {\n const tooltip = this.interpolate(tooltipValue || '').replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n return this.getFormattedAttribute(tooltip);\n }\n isHtmlRenderMode() {\n return this.options.renderMode === 'html';\n }\n renderTemplate(name, data = {}, modeOption = '') {\n // Need to make this fall back to form if renderMode is not found similar to how we search templates.\n const mode = modeOption || this.options.renderMode || 'form';\n data.component = this.component;\n data.self = this;\n data.options = this.options;\n data.readOnly = this.options.readOnly;\n data.iconClass = this.iconClass.bind(this);\n data.size = this.size.bind(this);\n data.t = this.t.bind(this);\n data.transform = this.transform.bind(this);\n data.id = data.id || this.id;\n data.key = data.key || this.key;\n data.value = data.value || this.dataValue;\n data.disabled = this.disabled;\n data.builder = this.builderMode;\n data.render = (...args) => {\n console.warn(`Form.io 'render' template function is deprecated.\n If you need to render template (template A) inside of another template (template B),\n pass pre-compiled template A (use this.renderTemplate('template_A_name') as template context variable for template B`);\n return this.renderTemplate(...args);\n };\n data.label = data.labelInfo || this.labelInfo;\n data.tooltip = this.getFormattedTooltip(this.component.tooltip);\n // Allow more specific template names\n const names = [\n `${name}-${this.component.type}-${this.key}`,\n `${name}-${this.component.type}`,\n `${name}-${this.key}`,\n `${name}`,\n ];\n // Allow template alters.\n const { referenceAttributeName, template } = this.getTemplate(names, mode);\n if (referenceAttributeName) {\n this._referenceAttributeName = referenceAttributeName;\n }\n return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(template, data), data, mode);\n }\n /**\n * Sanitize an html string.\n * @param {string} dirty - The dirty html string to sanitize.\n * @param {boolean} forceSanitize - If we should force the sanitize to occur.\n * @param {object} options - The options for the sanitize.\n * @returns {*} - The sanitized html string.\n */\n sanitize(dirty, forceSanitize = false, options = {}) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n * @param {string} template - The template to render.\n * @param {object} data - The data to provide to the template.\n * @returns {HTMLElement | string} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n /**\n * Allows for modification of the component value prior to submission.\n * @param {*} input - The input to be modified.\n * @returns {*} - The modified input mapping for the extended component.\n */\n performInputMapping(input) {\n return input;\n }\n /**\n * Returns the component \"widget\" if one is available.\n * @returns {Widget|null} - The widget instance. null if not available.\n */\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n /**\n * Returns the native supported browser language.\n * @returns {string|null} - The native browser language that is supported.\n */\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components to perform special functions.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the next/previous page navigation.\n */\n beforePage() {\n return Promise.resolve(true);\n }\n /**\n * Called before the next page is triggered allowing the components to hook into the page navigation and perform tasks.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the next page navigation.\n */\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components to perform special async functions.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the submission.\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n * @returns {string} - The submission timezone.\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n /**\n * Return the current timezone.\n * @returns {string} - The current timezone.\n */\n get timezone() {\n return this.getTimezone(this.component);\n }\n /**\n * Return the current timezone.\n * @param {object} settings - Settings to control how the timezone should be returned.\n * @returns {string} - The current timezone.\n */\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n /**\n *\n * @param {HTMLElement} element - The containing DOM element to query for the ref value.\n * @param {object} refs - The references to load.\n * @param {string} [referenceAttributeName] - The attribute name to use for the reference.\n */\n loadRefs(element, refs, referenceAttributeName) {\n if (!element) {\n return;\n }\n for (const ref in refs) {\n const refType = refs[ref];\n const isString = typeof refType === 'string';\n const selector = isString && refType.includes('scope')\n ? `:scope > [${referenceAttributeName || this._referenceAttributeName || 'ref'}=\"${ref}\"]`\n : `[${referenceAttributeName || this._referenceAttributeName || 'ref'}=\"${ref}\"]`;\n if (isString && refType.startsWith('single')) {\n this.refs[ref] = element.querySelector(selector);\n }\n else {\n this.refs[ref] = element.querySelectorAll(selector);\n }\n }\n }\n /**\n * Opens the modal element.\n * @param {string} template - The template to use for the modal dialog.\n */\n setOpenModalElement(template = null) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n /**\n * Returns the modal preview template.\n * @returns {string} - The modal preview template.\n */\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n let modalLabel;\n if (this.hasInput && ((_a = this.component.validate) === null || _a === void 0 ? void 0 : _a.required) && !this.isPDFReadOnlyMode) {\n modalLabel = { className: 'field-required' };\n }\n return this.renderTemplate('modalPreview', {\n previewText: this.getValueAsString(dataValue, { modalPreview: true }) || this.t('Click to set value'),\n messages: '',\n labelInfo: modalLabel,\n });\n }\n /**\n * Performs a complete build of a component, which empties, renders, sets the content in the DOM, and then finally attaches events.\n * @param {HTMLElement} element - The element to attach this component to.\n * @returns {Promise<void>} - A promise that resolves when the component has been built.\n */\n build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n /**\n * Renders a component as an HTML string.\n * @param {string} children - The contents of all the children HTML as a string.\n * @param {boolean} topLevel - If this is the topmost component that is being rendered.\n * @returns {string} - The rendered HTML string of a component.\n */\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n /**\n * Attaches all the tooltips provided the refs object.\n * @param {object} toolTipsRefs - The refs for the tooltips within your template.\n * @returns {void}\n */\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n /**\n * Create a new component modal for this component.\n * @param {HTMLElement} element - The element to attach the modal to.\n * @param {boolean} modalShouldBeOpened - TRUE if the modal should open immediately.\n * @param {any} currentValue - The current value of the component.\n * @returns {ComponentModal} - The created component modal.\n */\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\n }\n /**\n * Attaches all event listensers for this component to the DOM elements that were rendered.\n * @param {HTMLElement} element - The element to attach the listeners to.\n * @returns {Promise<void>} - Resolves when the component is done attaching to the DOM.\n */\n attach(element) {\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n const openModalTemplate = this.componentModal && modalShouldBeOpened\n ? this.componentModal.openModalTemplate\n : null;\n this.componentModal = this.createComponentModal(element, modalShouldBeOpened, currentValue);\n this.setOpenModalElement(openModalTemplate);\n }\n this.attached = true;\n this.setElement(element);\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n /**\n * Restors the \"focus\" on a component after a redraw event has occured.\n */\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n /**\n * Adds a keyboard shortcut to this component.\n * @param {HTMLElement} element - The element to attach the keyboard shortcut to.\n * @param {string} shortcut - The keyboard shortcut to add.\n * @returns {void}\n */\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n /**\n * Removes a keyboard shortcut from this component.\n * @param {HTMLElement} element - The element to remove the keyboard shortcut from.\n * @param {string} shortcut - The keyboard shortcut to remove.\n * @returns {void}\n */\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n // First iterate through each ref and delete the component so there are no dangling component references.\n lodash_1.default.each(this.refs, (ref) => {\n if (typeof ref === NodeList) {\n ref.forEach((elem) => {\n delete elem.component;\n });\n }\n else if (ref) {\n delete ref.component;\n }\n });\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n /**\n * Determines if the component should be refreshed based on the path of another component that changed.\n * @param {string} refreshData - The path of the data that needs to trigger a refresh.\n * @param {boolean} changed - Flag that is true if the data has been changed.\n * @param {any} flags - The flags for the checkData procedure.\n * @returns {void}\n */\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n /**\n * Iterates over a list of changes, and determines if the component should be refreshed if it is configured to refresh on any of those components.\n * @param {Array<any>} changes - The list of components that have changed.\n * @param {any} flags - The checkData flags.\n * @returns {void}\n */\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n * @param {any} value - The latest value of the component to check if it needs to be refreshed.\n * @returns {void}\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n * @param {any} component - The component to check if it is in the same context as this component.\n * @returns {boolean} - TRUE if the component is in the same context as this component.\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n /**\n * Determines if we are in \"view\" only mode.\n * @returns {boolean} - TRUE if we are in \"view\" only mode.\n */\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n /**\n * Sets the HTMLElement for this component.\n * @param {HTMLElement} element - The element that is attached to this component.\n * @returns {void}\n */\n setElement(element) {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n this.element = element;\n }\n /**\n * Creates an element to hold the \"view only\" version of this component.\n * @returns {HTMLElement} - The element for this component.\n */\n createViewOnlyElement() {\n this.setElement(this.ce('dl', {\n id: this.id\n }));\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n /**\n * The default value for the \"view only\" mode of a component if the value is not provided.\n * @returns {string} - The default value for this component.\n */\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n * @param {any} value - The current value of the component.\n * @param {any} options - The options for getValueAsString.\n * @returns {any|Array<any>} - The value as a string.\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n /**\n * Returns the value of the component as a string.\n * @param {any} value - The value for this component.\n * @param {any} options - The options for this component.\n * @returns {string} - The string representation of the value of this component.\n */\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n /**\n * Returns the string representation \"view\" of the component value.\n * @param {any} value - The value of the component.\n * @param {any} options - The options for this component.\n * @returns {string} - The string representation of the value of this component.\n */\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n /**\n * Updates the items list for this component. Useful for Select and other List component types.\n * @param {...any} args - The arguments to pass to the onChange event.\n * @returns {void}\n */\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * Returns the value for a specific item in a List type component.\n * @param {any} data - The data for this component.\n * @param {boolean} [forceUseValue] - if true, return 'value' property of the data\n * @returns {any} - The value of the item.\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n /**\n * Returns the item value for html mode.\n * @param {any} value - The value for this component.\n * @returns {any} - The value of the item for html mode.\n */\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n /**\n * Creates a modal to input the value of this component.\n * @param {HTMLElement} element - The element to attach the modal to.\n * @param {any} attr - A list of attributes to add to the modal.\n * @param {boolean} confirm - If we should add a confirmation to the modal that keeps it from closing unless confirmed.\n * @returns {HTMLElement} - The created modal element.\n */\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n /**\n * Uses CSS classes to show or hide an element.\n * @returns {boolean} - TRUE if the element has been css removed.\n */\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @returns {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n /**\n * Returns the component condition operator settings if available.\n * @returns {object} - The component condition operator settings.\n */\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n /**\n * Returns if the application is on a mobile device.\n * @returns {boolean} - TRUE if the application is on a mobile device.\n */\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement} - The wrapping element of this component.\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n * @param {any} additional - Additional context to provide.\n * @returns {any} - The evaluation context.\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n * @param {boolean} pristine - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n /**\n * Returns if the component is pristine.\n * @returns {boolean} - TRUE if the component is pristine.\n */\n get isPristine() {\n return this.pristine;\n }\n /**\n * Sets the dirty flag for this component.\n * @param {boolean} dirty - TRUE to make dirty, FALSE not dirty.\n */\n setDirty(dirty) {\n this.dirty = dirty;\n }\n /**\n * Returns if the component is dirty.\n * @returns {boolean} - TRUE if the component is dirty.\n */\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n /**\n * Returns the icon class for a given icon name.\n * @param {string} name - The name of the icon you wish to fetch provided the icon class. This is the \"font awesome\" version of the name of the icon.\n * @param {boolean} spinning - If the component should be spinning.\n * @returns {string} - The icon class for the equivalent icon in the iconset we are using.\n */\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n /**\n * Returns the size css class names for our current template.\n * @param {string} size - The size class name for the default iconset.\n * @returns {string} - The size class for our component.\n */\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n /**\n * Returns the visible errors for this component.\n * @returns {Array<object>} - The visible errors for this component.\n */\n get visibleErrors() {\n return this._visibleErrors;\n }\n /**\n * Returns all the errors for this component, visible or not.\n * @returns {Array<object>} - All the errors for this component.\n */\n get errors() {\n return this._errors;\n }\n /**\n * Returns the error label for this component.\n * @returns {string} - The error label for this component.\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param {string} type - The type of error to fetch the message for.\n * @returns {string} - The error message configured for this component.\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n /**\n * Sets the content, innerHTML, of an element to the sanitized content.\n * @param {HTMLElement} element - The element to set the innerHTML to.\n * @param {string} content - The HTML string content that we wish to set.\n * @param {boolean} forceSanitize - If we should force the content to be sanitized.\n * @param {any} sanitizeOptions - The options for the sanitize function.\n * @returns {boolean} - TRUE if the content was sanitized and set.\n */\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n /**\n * Restores the caret position in the input element after a refresh occurs.\n */\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n /**\n * Redraw the component.\n * @returns {Promise<void>} - A promise that resolves when the component is done redrawing.\n */\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.setElement(parent.children[index]);\n return this.attach(this.element);\n }\n /**\n * Rebuild and redraw a component.\n * @returns {Promise<void>} - A promise that resolves when the component is done rebuilding and redrawing.\n */\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n /**\n * Removes all event listeners attached to this component.\n */\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n /**\n * Returns if the dom node has the classes provided.\n * @param {HTMLElement} element - The element to check for the class.\n * @param {string} className - The name of the class to check.\n * @returns {boolean|void} - TRUE if the element has the class.\n */\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n /**\n * Adds a class to an HTML element.\n * @param {HTMLElement} element - The dom element to add the class to.\n * @param {string} className - The class name you wish to add.\n * @returns {this|void} - The component instance.\n */\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n /**\n * Removes a class from an element.\n * @param {HTMLElement} element - The element to remove the class from.\n * @param {string} className - The class name to remove.\n * @returns {this|void} - The component instance.\n */\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n * @returns {boolean} - TRUE if the component has a condition defined.\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n * @param {any} data - The data to check against.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is conditionally visible.\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n * @param {any} row - The row contextual data.\n * @param {any} data - The global data object.\n * @returns {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n * @param {any} data - The data to check against.\n * @param {any} flags - The flags passed to checkData function.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is visible.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param {any} data - The data to check against.\n * @param {any} flags - The flags passed to checkData function.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is visible.\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n /**\n * Returns the component logic if applicable.\n * @returns {Array<object>} - The component logic.\n */\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n * @param {any} data - The data to check against.\n * @param {any} row - The row data to check against.\n * @returns {boolean|void} - TRUE if the component was altered.\n */\n fieldLogic(data = this.rootValue, row = this.data) {\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n /**\n * Retuns if the browser is Internet Explorer.\n * @returns {boolean} - TRUE if the browser is IE.\n */\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n /**\n * Defines the logic action value through evaluation.\n * @param {object} action - The action within the Logic system to perform.\n * @param {object} argsObject - The arguments to pass to the evaluation.\n * @returns {any} - The result of the evaluation.\n */\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n /**\n * Apply the actions of Logic for a component once the conditions have been met.\n * @param {object} newComponent - The new component to apply the actions to.\n * @param {Array<object>} actions - An array of actions\n * @param {any} result - The result of the conditional check in order to evaluate the actions.\n * @param {any} row - The contextual row data for this component.\n * @param {any} data - The global data object for the submission.\n * @returns {boolean} - TRUE if the component was altered.\n */\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n * @param {Array<object>|string} messages - An array of messages to add to the element.\n * @returns {void}\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n return this.renderTemplate('message', Object.assign({}, message));\n }).join(''));\n }\n }\n /**\n * Sets the form input widget error classes.\n * @param {Array<HTMLElement>} elements - An array of DOM elements to set the error classes on.\n * @param {boolean} dirty - If the input is dirty.\n * @param {boolean} hasErrors - If the input has errors.\n * @param {boolean} hasMessages - If the input has messages.\n * @param {HTMLElement} element - The wrapper element for all the other elements passed in first argument.\n * @returns {void}\n */\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n // do not set error classes for hidden components\n if (!this.visible) {\n return;\n }\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n /**\n * Adds the classes necessary to mark an element as invalid.\n * @param {HTMLElement} element - The element you wish to add the invalid classes to.\n * @param {boolean} invalid - TRUE if the component is invalid, FALSE otherwise.\n * @returns {void}\n */\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n /**\n * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.\n */\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n /**\n * Triggers a debounced onChange event for the root component (usually Webform).\n * @param {...any} args - The arguments to pass to the onChange event.\n */\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root && this.root.triggerChange) {\n this.root.triggerChange(...args);\n }\n }\n /**\n * Called when the component value has been changed. This will then trigger the root level onChange handler which\n * propagates the checkData methods for the full component tree.\n * @param {any} flags - The flags for the change event propagation.\n * @param {boolean} fromRoot - If the change event is from the root component.\n * @returns {boolean} - TRUE if the component has changed.\n */\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur' || this.component.validateOn === 'submit') {\n flags.noValidate = true;\n }\n if (this.component.onChange) {\n this.evaluate(this.component.onChange, {\n flags\n });\n }\n // Set the changed variable.\n const changed = {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: flags\n };\n // Emit the change.\n this.emit('componentChange', changed);\n // Do not propogate the modified flag.\n let modified = false;\n if (flags.modified) {\n modified = true;\n delete flags.modified;\n }\n // Bubble this change up to the top.\n if (!fromRoot) {\n this.triggerRootChange(flags, changed, modified);\n }\n return changed;\n }\n get wysiwygDefault() {\n return {\n quill: {\n theme: 'snow',\n placeholder: this.t(this.component.placeholder, { _userInput: true }),\n modules: {\n toolbar: [\n [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown\n [{ 'header': [1, 2, 3, 4, 5, 6, false] }],\n [{ 'font': [] }],\n ['bold', 'italic', 'underline', 'strike', { 'script': 'sub' }, { 'script': 'super' }, 'clean'],\n [{ 'color': [] }, { 'background': [] }],\n [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }, { 'align': [] }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video', 'formula', 'source']\n ]\n }\n },\n ace: {\n theme: 'ace/theme/xcode',\n maxLines: 12,\n minLines: 12,\n tabSize: 2,\n mode: 'ace/mode/javascript',\n placeholder: this.t(this.component.placeholder, { _userInput: true })\n },\n ckeditor: {\n image: {\n toolbar: [\n 'imageTextAlternative',\n '|',\n 'imageStyle:full',\n 'imageStyle:alignLeft',\n 'imageStyle:alignCenter',\n 'imageStyle:alignRight'\n ],\n styles: [\n 'full',\n 'alignLeft',\n 'alignCenter',\n 'alignRight'\n ]\n },\n extraPlugins: []\n },\n default: {}\n };\n }\n addCKE(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? {} : settings;\n settings.base64Upload = this.component.isUploadEnabled ? false : true;\n settings.mediaEmbed = { previewsInData: true };\n settings = lodash_1.default.merge(this.wysiwygDefault.ckeditor, lodash_1.default.get(this.options, 'editors.ckeditor.settings', {}), settings);\n if (this.component.isUploadEnabled) {\n settings.extraPlugins.push((0, uploadAdapter_1.getFormioUploadAdapterPlugin)(this.fileService, this));\n }\n return Formio_1.Formio.requireLibrary('ckeditor', isIEBrowser ? 'CKEDITOR' : 'ClassicEditor', lodash_1.default.get(this.options, 'editors.ckeditor.src', `${Formio_1.Formio.cdn.ckeditor}/ckeditor.js`), true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n if (isIEBrowser) {\n const editor = CKEDITOR.replace(element);\n editor.on('change', () => onChange(editor.getData()));\n return Promise.resolve(editor);\n }\n else {\n return ClassicEditor.create(element, settings).then(editor => {\n editor.model.document.on('change', () => onChange(editor.data.get()));\n return editor;\n });\n }\n });\n }\n addQuill(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? this.wysiwygDefault.quill : settings;\n settings = lodash_1.default.merge(this.wysiwygDefault.quill, lodash_1.default.get(this.options, 'editors.quill.settings', {}), settings);\n settings = Object.assign(Object.assign({}, settings), { modules: Object.assign({ table: true }, settings.modules) });\n // Lazy load the quill css.\n Formio_1.Formio.requireLibrary(`quill-css-${settings.theme}`, 'Quill', [\n { type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` }\n ], true);\n // Lazy load the quill library.\n return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.min.js`), true)\n .then(() => {\n return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);\n /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */\n const txtArea = document.createElement('textarea');\n txtArea.setAttribute('class', 'quill-source-code');\n this.quill.addContainer('ql-custom').appendChild(txtArea);\n const qlSource = element.parentNode.querySelector('.ql-source');\n if (qlSource) {\n this.addEventListener(qlSource, 'click', (event) => {\n event.preventDefault();\n if (txtArea.style.display === 'inherit') {\n this.quill.setContents(this.quill.clipboard.convert({ html: txtArea.value }));\n }\n txtArea.style.display = (txtArea.style.display === 'none') ? 'inherit' : 'none';\n });\n }\n /** END CODEBLOCK */\n // Make sure to select cursor when they click on the element.\n this.addEventListener(element, 'click', () => this.quill.focus());\n // Allows users to skip toolbar items when tabbing though form\n const elm = document.querySelectorAll('.ql-formats > button');\n for (let i = 0; i < elm.length; i++) {\n elm[i].setAttribute('tabindex', '-1');\n }\n this.quill.on('text-change', () => {\n txtArea.value = this.quill.root.innerHTML;\n onChange(txtArea);\n });\n return this.quill;\n });\n });\n }\n get shouldSanitizeValue() {\n var _a;\n // Sanitize value if sanitizing for thw whole content is turned off\n return (((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitize) !== false);\n }\n addAce(element, settings, onChange) {\n if (!settings || (settings.theme === 'snow')) {\n const mode = settings ? settings.mode : '';\n settings = {};\n if (mode) {\n settings.mode = mode;\n }\n }\n settings = lodash_1.default.merge(this.wysiwygDefault.ace, lodash_1.default.get(this.options, 'editors.ace.settings', {}), settings || {});\n return Formio_1.Formio.requireLibrary('ace', 'ace', lodash_1.default.get(this.options, 'editors.ace.src', `${Formio_1.Formio.cdn.ace}/ace.js`), true)\n .then((editor) => {\n editor = editor.edit(element);\n editor.removeAllListeners('change');\n editor.setOptions(settings);\n editor.getSession().setMode(settings.mode);\n editor.on('change', () => onChange(editor.getValue()));\n if (settings.isUseWorkerDisabled) {\n editor.session.setUseWorker(false);\n }\n return editor;\n });\n }\n get tree() {\n return this.component.tree || false;\n }\n /**\n * The empty value for this component.\n * @returns {null} - The empty value for this component.\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n * @param {any} data - The global data object.\n * @returns {boolean} - TRUE if a value is set.\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n * @returns {*} - The root value for the component, typically the Webform data object.\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @returns {*} - The value for this component.\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n * @param {*} value - The value to set for this component.\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n * @param {number} index - The index to splice for an array component values.\n * @param {*} flags - The flags to use when splicing the value.\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n * @returns {*} - The value for the component.\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - For an array component or multiple values, this returns the value at a specific index.\n * @returns {*} - The value at the specified index.\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n * @param {*} value - The value to set for this component.\n * @param {*} flags - The flags to use when setting the value.\n * @returns {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n * @param {number} index - The index to set the value at.\n * @param {*} value - The value to set at the specified index.\n * @param {*} flags - The flags to use when setting the value.\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n * @param {*} value - The value to normalize before setting.\n * @returns {*} - The normalized value.\n */\n normalizeValue(value) {\n if (this.component.multiple && !Array.isArray(value)) {\n value = value ? [value] : [];\n }\n return value;\n }\n /**\n * Update a value of this component.\n * @param {*} value - The value to update.\n * @param {*} flags - The flags to use when updating the value.\n * @returns {boolean} - If the value changed.\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n * @param {...any} args - The arguments to pass to updateValue.\n * @returns {boolean} - If the value changed.\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.defaultValue || this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n * @param {*} newValue - The new value to check.\n * @param {*} oldValue - The existing value of the component.\n * @returns {boolean} - TRUE if the value has changed.\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n * @param {*} flags - The flags to use when triggering the on change event.\n * @param {boolean} changed - If the value has changed.\n * @returns {boolean} - If the value changed.\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n if (flags.fromSubmission) {\n // Reset the errors when a submission has been made and allow it to revalidate.\n this._errors = [];\n }\n this.triggerChange(flags);\n return true;\n }\n return false;\n }\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set or in builder mode\n if (this.builderMode || lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n this.calculatedValue = null;\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified && this.root.initialized) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n * @param {*} data - The data to perform the calculation with.\n * @param {*} flags - The flags to use when calculating the value.\n * @param {*} row - The contextual row data to use when performing the calculation.\n * @returns {boolean} - TRUE if the value changed.\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n * @returns {string} - The label text for this component.\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n * @param {string} value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n * @returns {*} root - The root component to search from.\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.\n * @param {*} row - Contextual row data for this component.\n * @returns {string} - The message to show when the component is invalid.\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n const validationScope = { errors: [] };\n (0, process_1.processOneSync)({\n component: this.component,\n data,\n row,\n path: this.path || this.component.key,\n scope: validationScope,\n instance: this,\n processors: [\n process_1.validateProcessInfo\n ]\n });\n const errors = validationScope.errors;\n const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this));\n return lodash_1.default.map(interpolatedErrors, 'message').join('\\n\\n');\n }\n /**\n * Returns if the component is valid or not.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @returns {boolean} - TRUE if the component is valid.\n */\n isValid(data, dirty) {\n return !this.invalidMessage(data, dirty);\n }\n setComponentValidity(errors, dirty, silentCheck) {\n if (silentCheck) {\n return [];\n }\n const messages = errors.filter(message => !message.fromServer);\n if (errors.length && !!messages.length && (!this.isEmpty(this.defaultValue) || dirty || !this.pristine)) {\n return this.setCustomValidity(messages, dirty);\n }\n else {\n return this.setCustomValidity('');\n }\n }\n /**\n * Interpolate errors from the validation methods.\n * @param {Array<any>} errors - An array of errors to interpolate.\n * @returns {Array<any>} - The interpolated errors.\n */\n interpolateErrors(errors) {\n var _a;\n const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this));\n return ((_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.length) ? [...interpolatedErrors, ...this.serverErrors] : interpolatedErrors;\n }\n /**\n * Show component validation errors.\n * @param {*} errors - An array of errors that have occured.\n * @param {*} data - The root submission data.\n * @param {*} row - The contextual row data.\n * @param {*} flags - The flags to perform validation.\n * @returns {boolean} - TRUE if the component is valid.\n */\n showValidationErrors(errors, data, row, flags) {\n if (flags.silentCheck) {\n return [];\n }\n if (this.options.alwaysDirty) {\n flags.dirty = true;\n }\n if (flags.fromSubmission && this.hasValue(data)) {\n flags.dirty = true;\n }\n this.setDirty(flags.dirty);\n return this.setComponentValidity(errors, flags.dirty, flags.silentCheck, flags.fromSubmission);\n }\n /**\n * Perform a component validation.\n * @param {*} data - The root data you wish to use for this component.\n * @param {*} row - The contextual row data you wish to use for this component.\n * @param {*} flags - The flags to control the behavior of the validation.\n * @returns {Array<any>} - An array of errors if the component is invalid.\n */\n validateComponent(data = null, row = null, flags = {}) {\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false } = flags;\n if (this.shouldSkipValidation(data, row, flags)) {\n return async ? Promise.resolve([]) : [];\n }\n const processContext = {\n component: this.component,\n data,\n row,\n value: this.validationValue,\n path: this.path || this.component.key,\n instance: this,\n scope: { errors: [] },\n processors: [\n process_1.validateProcessInfo\n ]\n };\n if (async) {\n return (0, process_1.processOne)(processContext).then(() => {\n this._errors = this.interpolateErrors(processContext.scope.errors);\n return this._errors;\n });\n }\n (0, process_1.processOneSync)(processContext);\n this._errors = this.interpolateErrors(processContext.scope.errors);\n return this._errors;\n }\n /**\n * Checks the validity of this component and sets the error message if it is invalid.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {*} row - The contextual row data for this component.\n * @param {*} flags - The flags to use when checking the validity.\n * @param {Array<any>} allErrors - An array of all errors that have occured so that it can be appended when another one occurs here.\n * @returns {boolean} - TRUE if the component is valid.\n */\n checkComponentValidity(data = null, dirty = false, row = null, flags = {}, allErrors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n flags.dirty = dirty || false;\n if (flags.async) {\n return this.validateComponent(data, row, flags).then((errors) => {\n allErrors.push(...errors);\n if (this.parent && this.parent.childErrors) {\n if (errors.length) {\n this.parent.childErrors.push(...errors);\n }\n else {\n lodash_1.default.remove(this.parent.childErrors, (err) => { var _a, _b; return (((_a = err === null || err === void 0 ? void 0 : err.component) === null || _a === void 0 ? void 0 : _a.key) || ((_b = err === null || err === void 0 ? void 0 : err.context) === null || _b === void 0 ? void 0 : _b.key)) === this.component.key; });\n }\n }\n this.showValidationErrors(errors, data, row, flags);\n return errors.length === 0;\n });\n }\n else {\n const errors = this.validateComponent(data, row, flags);\n this.showValidationErrors(errors, data, row, flags);\n allErrors.push(...errors);\n if (this.parent && this.parent.childErrors) {\n if (errors.length) {\n this.parent.childErrors.push(...errors);\n }\n else {\n lodash_1.default.remove(this.parent.childErrors, (err) => { var _a, _b; return (((_a = err === null || err === void 0 ? void 0 : err.component) === null || _a === void 0 ? void 0 : _a.key) || ((_b = err === null || err === void 0 ? void 0 : err.context) === null || _b === void 0 ? void 0 : _b.key)) === this.component.key; });\n }\n }\n return errors.length === 0;\n }\n }\n /**\n * Checks the validity of the component.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {*} row - The contextual row data for this component.\n * @param {boolean} silentCheck - If the check should be silent and not set the error messages.\n * @param {Array<any>} errors - An array of all errors that have occured so that it can be appended when another one occurs here.\n * @returns {boolean} - TRUE if the component is valid.\n */\n checkValidity(data = null, dirty = false, row = null, silentCheck = false, errors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n return this.checkComponentValidity(data, dirty, row, { silentCheck }, errors);\n }\n checkAsyncValidity(data = null, dirty = false, row = null, silentCheck = false, errors = []) {\n return this.checkComponentValidity(data, dirty, row, { async: true, silentCheck }, errors);\n }\n /**\n * Check the conditions, calculations, and validity of a single component and triggers an update if\n * something changed.\n * @param {*} data - The root data of the change event.\n * @param {*} flags - The flags from this change event.\n * @param {*} row - The contextual row data for this component.\n * @returns {void|boolean} - TRUE if no check should be performed on the component.\n */\n checkData(data = null, flags = null, row = null) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n }\n checkModal(errors = [], dirty = false) {\n const messages = errors.filter(error => !error.fromServer);\n const isValid = errors.length === 0;\n if (!this.component.modalEdit || !this.componentModal) {\n return;\n }\n if (dirty && !isValid) {\n this.setErrorClasses([this.refs.openModal], dirty, !isValid, !!messages.length, this.refs.openModalWrapper);\n }\n else {\n this.clearErrorClasses(this.refs.openModalWrapper);\n }\n }\n get validationValue() {\n return this.dataValue;\n }\n isEmpty(value = this.dataValue) {\n const isEmptyArray = (lodash_1.default.isArray(value) && value.length === 1) ? lodash_1.default.isEqual(value[0], this.emptyValue) : false;\n return value == null || value.length === 0 || lodash_1.default.isEqual(value, this.emptyValue) || isEmptyArray;\n }\n isEqual(valueA, valueB = this.dataValue) {\n return (this.isEmpty(valueA) && this.isEmpty(valueB)) || lodash_1.default.isEqual(valueA, valueB);\n }\n /**\n * Check if a component is eligible for multiple validation\n * @returns {boolean} - TRUE if the component is eligible for multiple validation.\n */\n validateMultiple() {\n return true;\n }\n clearErrorClasses(element = this.element) {\n this.removeClass(element, this.options.componentErrorClass);\n this.removeClass(element, 'alert alert-danger');\n this.removeClass(element, 'has-error');\n this.removeClass(element, 'has-message');\n }\n setInputWidgetErrorClasses(inputRefs, hasErrors) {\n if (!this.isInputComponent || !this.component.widget || !(inputRefs === null || inputRefs === void 0 ? void 0 : inputRefs.length)) {\n return;\n }\n inputRefs.forEach((input) => {\n if ((input === null || input === void 0 ? void 0 : input.widget) && input.widget.setErrorClasses) {\n input.widget.setErrorClasses(hasErrors);\n }\n });\n }\n addFocusBlurEvents(element) {\n this.addEventListener(element, 'focus', () => {\n if (this.root.focusedComponent !== this) {\n if (this.root.pendingBlur) {\n this.root.pendingBlur();\n }\n this.root.focusedComponent = this;\n this.emit('focus', this);\n }\n else if (this.root.focusedComponent === this && this.root.pendingBlur) {\n this.root.pendingBlur.cancel();\n this.root.pendingBlur = null;\n }\n });\n this.addEventListener(element, 'blur', () => {\n this.root.pendingBlur = FormioUtils.delay(() => {\n this.emit('blur', this);\n if (this.component.validateOn === 'blur') {\n this.root.triggerChange({ fromBlur: true }, {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: { fromBlur: true }\n });\n }\n this.root.focusedComponent = null;\n this.root.pendingBlur = null;\n });\n });\n }\n // eslint-disable-next-line max-statements\n setCustomValidity(messages, dirty, external) {\n const inputRefs = this.isInputComponent ? this.refs.input || [] : null;\n if (typeof messages === 'string' && messages) {\n messages = {\n level: 'error',\n message: messages,\n component: this.component,\n };\n }\n if (!Array.isArray(messages)) {\n if (messages) {\n messages = [messages];\n }\n else {\n messages = [];\n }\n }\n const errors = messages.filter(message => message.level === 'error');\n let invalidInputRefs = inputRefs;\n // Filter the invalid input refs in multiple components\n if (this.component.multiple) {\n const refsArray = Array.from(inputRefs);\n refsArray.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), false);\n });\n this.setInputWidgetErrorClasses(refsArray, false);\n invalidInputRefs = refsArray.filter((ref, index) => {\n var _a;\n return (_a = messages.some) === null || _a === void 0 ? void 0 : _a.call(messages, (msg) => {\n var _a;\n return ((_a = msg === null || msg === void 0 ? void 0 : msg.context) === null || _a === void 0 ? void 0 : _a.index) === index;\n });\n });\n }\n if (messages.length) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n this.emit('componentError', {\n instance: this,\n component: this.component,\n message: messages[0].message,\n messages,\n external: !!external,\n });\n this.addMessages(messages, dirty, invalidInputRefs);\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, !!errors.length, !!messages.length);\n }\n }\n else if (!errors.length || (errors[0].external === !!external)) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n if (this.refs.modalMessageContainer) {\n this.empty(this.refs.modalMessageContainer);\n }\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, !!errors.length, !!messages.length);\n }\n this.clearErrorClasses();\n }\n this._visibleErrors = messages;\n return messages;\n }\n /**\n * Determines if the value of this component is hidden from the user as if it is coming from the server, but is\n * protected.\n * @returns {boolean|*} - TRUE if the value is hidden.\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, row, flags = {}) {\n const { validateWhenHidden = false } = this.component || {};\n const forceValidOnHidden = (!this.visible || !this.checkCondition(row, data)) && !validateWhenHidden;\n if (forceValidOnHidden) {\n // If this component is forced valid when it is hidden, then we also need to reset the errors for this component.\n this._errors = [];\n }\n const rules = [\n // Do not validate if the flags say not too.\n () => flags.noValidate,\n // Force valid if component is read-only\n () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !this.hasInput,\n // Check to see if we are editing and if so, check component persistence.\n () => this.isValueHidden(),\n // Force valid if component is hidden.\n () => forceValidOnHidden\n ];\n return rules.some(pred => pred());\n }\n // Maintain reverse compatibility.\n whenReady() {\n console.warn('The whenReady() method has been deprecated. Please use the dataReady property instead.');\n return this.dataReady;\n }\n get dataReady() {\n return Promise.resolve();\n }\n /**\n * Prints out the value of this component as a string value.\n * @param {*} value - The value to print out.\n * @returns {string} - The string representation of the value.\n */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @returns {boolean} - TRUE if the component is disabled.\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n * @param {boolean} disabled - TRUE to disable the component.\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n * @returns {*} - The components \"input\" DOM element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index = (this.refs.input.length - 1)) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = this.refs.input[index];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n * @returns {import('@formio/core').Formio} - The Formio instance file service.\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = (0, utils_1.getScriptPlugin)(property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n src = Array.isArray(src) ? src : [src];\n src.forEach((lib) => {\n let attrs = {};\n let elementType = '';\n if (typeof lib === 'string') {\n lib = {\n type: 'script',\n src: lib\n };\n }\n switch (lib.type) {\n case 'script':\n elementType = 'script';\n attrs = {\n src: lib.src,\n type: 'text/javascript',\n defer: true,\n async: true\n };\n break;\n case 'styles':\n elementType = 'link';\n attrs = {\n href: lib.src,\n rel: 'stylesheet'\n };\n break;\n }\n // Add the script to the top page.\n const script = document.createElement(elementType);\n for (const attr in attrs) {\n script.setAttribute(attr, attrs[attr]);\n }\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n setTimeout(function checkLibrary() {\n const plugin = (0, utils_1.getScriptPlugin)(property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n // check again after 200 ms.\n setTimeout(checkLibrary, 200);\n }\n }, 200);\n }\n }\n }\n return Component.externalLibraries[name].ready;\n};\nComponent.libraryReady = function (name) {\n if (Component.externalLibraries.hasOwnProperty(name) &&\n Component.externalLibraries[name].ready) {\n return Component.externalLibraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/Component.js?");
5471
+ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/* globals Quill, ClassicEditor, CKEDITOR */\nconst vanilla_text_mask_1 = __webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\");\nconst tippy_js_1 = __importDefault(__webpack_require__(/*! tippy.js */ \"./node_modules/tippy.js/dist/tippy.esm.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst ismobilejs_1 = __importDefault(__webpack_require__(/*! ismobilejs */ \"./node_modules/ismobilejs/esm/index.js\"));\nconst process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nconst Formio_1 = __webpack_require__(/*! ../../../Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Element_1 = __importDefault(__webpack_require__(/*! ../../../Element */ \"./lib/cjs/Element.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst addons_1 = __importDefault(__webpack_require__(/*! ../../../addons */ \"./lib/cjs/addons/index.js\"));\nconst uploadAdapter_1 = __webpack_require__(/*! ../../../providers/storage/uploadAdapter */ \"./lib/cjs/providers/storage/uploadAdapter.js\");\nconst en_1 = __importDefault(__webpack_require__(/*! ../../../translations/en */ \"./lib/cjs/translations/en.js\"));\nconst Templates_1 = __importDefault(__webpack_require__(/*! ../../../templates/Templates */ \"./lib/cjs/templates/Templates.js\"));\nconst isIEBrowser = FormioUtils.getBrowserInfo().ie;\n/**\n * This is the Component class\n which all elements within the FormioForm derive from.\n */\nclass Component extends Element_1.default {\n static schema(...sources) {\n return lodash_1.default.merge({\n /**\n * Determines if this component provides an input.\n */\n input: true,\n /**\n * The data key for this component (how the data is stored in the database).\n */\n key: '',\n /**\n * The input placeholder for this component.\n */\n placeholder: '',\n /**\n * The input prefix\n */\n prefix: '',\n /**\n * The custom CSS class to provide to this component.\n */\n customClass: '',\n /**\n * The input suffix.\n */\n suffix: '',\n /**\n * If this component should allow an array of values to be captured.\n */\n multiple: false,\n /**\n * The default value of this component.\n */\n defaultValue: null,\n /**\n * If the data of this component should be protected (no GET api requests can see the data)\n */\n protected: false,\n /**\n * Validate if the value of this component should be unique within the form.\n */\n unique: false,\n /**\n * If the value of this component should be persisted within the backend api database.\n */\n persistent: true,\n /**\n * Determines if the component should be within the form, but not visible.\n */\n hidden: false,\n /**\n * If the component should be cleared when hidden.\n */\n clearOnHide: true,\n /**\n * This will refresh this component options when this field changes.\n */\n refreshOn: '',\n /**\n * This will redraw the component when this field changes.\n */\n redrawOn: '',\n /**\n * If this component should be included as a column within a submission table.\n */\n tableView: false,\n /**\n * If this component should be rendering in modal.\n */\n modalEdit: false,\n /**\n * The input label provided to this component.\n */\n label: '',\n dataGridLabel: false,\n labelPosition: 'top',\n description: '',\n errorLabel: '',\n tooltip: '',\n hideLabel: false,\n tabindex: '',\n disabled: false,\n autofocus: false,\n dbIndex: false,\n customDefaultValue: '',\n calculateValue: '',\n calculateServer: false,\n widget: null,\n /**\n * Attributes that will be assigned to the input elements of this component.\n */\n attributes: {},\n /**\n * This will perform the validation on either \"change\" or \"blur\" of the input element.\n */\n validateOn: 'change',\n /**\n * The validation criteria for this component.\n */\n validate: {\n /**\n * If this component is required.\n */\n required: false,\n /**\n * Custom JavaScript validation.\n */\n custom: '',\n /**\n * If the custom validation should remain private (only the backend will see it and execute it).\n */\n customPrivate: false,\n /**\n * If this component should implement a strict date validation if the Calendar widget is implemented.\n */\n strictDateValidation: false,\n multiple: false,\n unique: false\n },\n /**\n * The simple conditional settings for a component.\n */\n conditional: {\n show: null,\n when: null,\n eq: ''\n },\n overlay: {\n style: '',\n left: '',\n top: '',\n width: '',\n height: '',\n },\n allowCalculateOverride: false,\n encrypted: false,\n showCharCount: false,\n showWordCount: false,\n properties: {},\n allowMultipleMasks: false,\n addons: [],\n }, ...sources);\n }\n /**\n * Return the simple condition settings as part of the component.\n * @returns {object} - The simple conditional settings.\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n * @param schema\n * @returns {Array}\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n * @param {object} component - The component JSON you wish to initialize.\n * @param {object} options - The options for this component.\n * @param {object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * The data path to this specific component instance.\n * @type {string}\n */\n this.path = (component === null || component === void 0 ? void 0 : component.key) || '';\n /**\n * An array of all the children components errors.\n */\n this.childErrors = [];\n /**\n * Last validation errors that have occured.\n */\n this._errors = [];\n this._visibleErrors = [];\n /**\n * The Form.io component JSON schema.\n * @type {*}\n */\n this.component = this.mergeSchema(component || {});\n // Add the id to the component.\n this.component.id = this.id;\n this.afterComponentAssign();\n // Save off the original component to be used in logic.\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n /**\n * If the component has been attached\n */\n this.attached = false;\n /**\n * If the component has been rendered\n */\n this.rendered = false;\n /**\n * The data object in which this component resides.\n * @type {*}\n */\n this._data = data || {};\n /**\n * Tool tip text after processing\n * @type {string}\n */\n this.tooltip = '';\n /**\n * The row path of this component.\n * @type {number}\n */\n this.row = this.options.row;\n /**\n * Points to a flat map of child components (if applicable).\n * @type {object}\n */\n this.childComponentsMap = {};\n /**\n * Determines if this component is disabled, or not.\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n * @type {Component}\n */\n this.root = this.options.root || this;\n this.localRoot = this.options.localRoot || this;\n /**\n * If this input has been input and provided value.\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n this._path = '';\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n /**\n * Determines if this component is visible, or not.\n */\n this._parentVisible = this.options.hasOwnProperty('parentVisible') ? this.options.parentVisible : true;\n this._visible = this._parentVisible && this.conditionallyVisible(null, data);\n this._parentDisabled = false;\n /**\n * The reference attribute name for this component\n */\n this._referenceAttributeName = 'ref';\n /**\n * Used to trigger a new change in this component.\n * @type {Function} - Call to trigger a change in this component.\n */\n let changes = [];\n let lastChanged = null;\n let triggerArgs = [];\n const _triggerChange = lodash_1.default.debounce((...args) => {\n if (this.root) {\n this.root.changing = false;\n }\n triggerArgs = [];\n if (!args[1] && lastChanged) {\n // Set the changed component if one isn't provided.\n args[1] = lastChanged;\n }\n if (lodash_1.default.isEmpty(args[0]) && lastChanged) {\n // Set the flags if it is empty and lastChanged exists.\n args[0] = lastChanged.flags;\n }\n lastChanged = null;\n args[3] = changes;\n const retVal = this.onChange(...args);\n changes = [];\n return retVal;\n }, 100);\n this.triggerChange = (...args) => {\n if (args[1]) {\n // Make sure that during the debounce that we always track lastChanged component, even if they\n // don't provide one later.\n lastChanged = args[1];\n changes.push(lastChanged);\n }\n if (this.root) {\n this.root.changing = true;\n }\n if (args.length) {\n triggerArgs = args;\n }\n return _triggerChange(...triggerArgs);\n };\n /**\n * Used to trigger a redraw event within this component.\n * @type {Function}\n */\n this.triggerRedraw = lodash_1.default.debounce(this.redraw.bind(this), 100);\n /**\n * list of attached tooltips\n * @type {Array}\n */\n this.tooltips = [];\n /**\n * List of attached addons\n * @type {Array}\n */\n this.addons = [];\n // To force this component to be invalid.\n this.invalid = false;\n if (this.component) {\n this.type = this.component.type;\n if (this.allowData && this.key) {\n this.options.name += `[${this.key}]`;\n // If component is visible or not set to clear on hide, set the default value.\n if (this.visible || !this.component.clearOnHide) {\n if (!this.hasValue()) {\n if (this.shouldAddDefaultValue) {\n this.dataValue = this.defaultValue;\n }\n }\n else {\n // Ensure the dataValue is set.\n /* eslint-disable no-self-assign */\n this.dataValue = this.dataValue;\n /* eslint-enable no-self-assign */\n }\n }\n }\n /**\n * The element information for creating the input element.\n * @type {*}\n */\n this.info = this.elementInfo();\n }\n // Allow anyone to hook into the component creation.\n this.hook('component');\n if (!this.options.skipInit) {\n this.init();\n }\n }\n /* eslint-enable max-statements */\n get componentsMap() {\n var _a;\n if ((_a = this.localRoot) === null || _a === void 0 ? void 0 : _a.childComponentsMap) {\n return this.localRoot.childComponentsMap;\n }\n const localMap = {};\n localMap[this.path] = this;\n return localMap;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n }\n mergeSchema(component = {}) {\n return lodash_1.default.defaultsDeep(component, this.defaultSchema);\n }\n // Allow componets to notify when ready.\n get ready() {\n return Promise.resolve(this);\n }\n get isPDFReadOnlyMode() {\n return this.parent &&\n this.parent.form &&\n (this.parent.form.display === 'pdf') &&\n this.options.readOnly;\n }\n get labelInfo() {\n const label = {};\n label.hidden = this.labelIsHidden();\n label.className = '';\n label.labelPosition = this.component.labelPosition;\n label.tooltipClass = `${this.iconClass('question-sign')} text-muted`;\n const isPDFReadOnlyMode = this.isPDFReadOnlyMode;\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required) && !isPDFReadOnlyMode) {\n label.className += ' field-required';\n }\n if (label.hidden) {\n label.className += ' control-label--hidden';\n }\n if (this.info.attr.id) {\n label.for = this.info.attr.id;\n }\n return label;\n }\n init() {\n var _a;\n this.disabled = this.shouldDisabled;\n this._visible = this.conditionallyVisible(null, null);\n if ((_a = this.component.addons) === null || _a === void 0 ? void 0 : _a.length) {\n this.component.addons.forEach((addon) => this.createAddon(addon));\n }\n }\n afterComponentAssign() {\n //implement in extended classes\n }\n createAddon(addonConfiguration) {\n var _a;\n const name = addonConfiguration.name;\n if (!name) {\n return;\n }\n const settings = ((_a = addonConfiguration.settings) === null || _a === void 0 ? void 0 : _a.data) || {};\n const Addon = addons_1.default[name.value];\n let addon = null;\n if (Addon) {\n const supportedComponents = Addon.info.supportedComponents;\n const supportsThisComponentType = !(supportedComponents === null || supportedComponents === void 0 ? void 0 : supportedComponents.length) ||\n supportedComponents.indexOf(this.component.type) !== -1;\n if (supportsThisComponentType) {\n addon = new Addon(settings, this);\n this.addons.push(addon);\n }\n else {\n console.warn(`Addon ${name.label} does not support component of type ${this.component.type}.`);\n }\n }\n return addon;\n }\n teardown() {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n delete this._currentForm;\n delete this.parent;\n delete this.root;\n delete this.triggerChange;\n delete this.triggerRedraw;\n if (this.options) {\n delete this.options.root;\n delete this.options.parent;\n delete this.options.i18next;\n }\n super.teardown();\n }\n destroy(all = false) {\n super.destroy(all);\n this.detach();\n this.addons.forEach((addon) => addon.destroy());\n if (all) {\n this.teardown();\n }\n }\n get shouldDisabled() {\n return this.options.readOnly || this.component.disabled || (this.options.hasOwnProperty('disabled') && this.options.disabled[this.key]);\n }\n get isInputComponent() {\n return !this.component.hasOwnProperty('input') || this.component.input;\n }\n get allowData() {\n return this.hasInput;\n }\n get hasInput() {\n return this.isInputComponent || (this.refs.input && this.refs.input.length);\n }\n get defaultSchema() {\n return Component.schema();\n }\n get key() {\n return lodash_1.default.get(this.component, 'key', '');\n }\n set parentVisible(value) {\n this._parentVisible = value;\n }\n get parentVisible() {\n return this._parentVisible;\n }\n set parentDisabled(value) {\n this._parentDisabled = value;\n }\n get parentDisabled() {\n return this._parentDisabled;\n }\n shouldForceVisibility(component, visibility) {\n if (!this.options[visibility]) {\n return false;\n }\n if (!component) {\n component = this.component;\n }\n if (lodash_1.default.isArray(this.options[visibility])) {\n return this.options[visibility].includes(component.key);\n }\n return this.options[visibility][component.key];\n }\n shouldForceHide(component) {\n return this.shouldForceVisibility(component, 'hide');\n }\n shouldForceShow(component) {\n return this.shouldForceVisibility(component, 'show');\n }\n /**\n * Sets the component visibility.\n * @param {boolean} value - Whether the component should be visible or not.\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n * Returns the component visibility\n * @returns {boolean} - Whether the component is visible or not.\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n * @param {object} schema - The \"full\" json schema for the component.\n * @param {object} defaultSchema - The \"default\" json schema for the component.\n * @param {boolean} recursion - If we are currently in a recursive loop.\n * @returns {object} - The minified json schema for this component.\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n * @returns {object} - The JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n * @returns {boolean} - True if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n * @param {string} text - The i18n identifier.\n * @param {object} params - The i18n parameters to use for translation.\n * @param {...any} args - Additional arguments to pass to the translation library.\n * @returns {string} - The translated text.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = params.data || this.rootValue;\n params.row = params.row || this.data;\n params.component = params.component || this.component;\n return super.t(text, params, ...args);\n }\n labelIsHidden() {\n return !this.component.label ||\n ((!this.isInDataGrid && this.component.hideLabel) ||\n (this.isInDataGrid && !this.component.dataGridLabel) ||\n this.options.floatingLabels ||\n this.options.inputsOnly) && !this.builderMode;\n }\n transform(type, value) {\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n return frameworkTemplates.hasOwnProperty('transform')\n ? frameworkTemplates.transform(type, value, this)\n : (type, value) => value;\n }\n getTemplate(names, modes) {\n modes = Array.isArray(modes) ? modes : [modes];\n names = Array.isArray(names) ? names : [names];\n if (!modes.includes('form')) {\n modes.push('form');\n }\n let result = null;\n if (this.options.templates) {\n result = this.checkTemplate(this.options.templates, names, modes);\n if (result) {\n return result;\n }\n }\n const frameworkTemplates = this.options.template ? Templates_1.default.templates[this.options.template] : Templates_1.default.current;\n result = this.checkTemplate(frameworkTemplates, names, modes);\n if (result) {\n return result;\n }\n // Default back to bootstrap if not defined.\n const name = names[names.length - 1];\n const templatesByName = Templates_1.default.defaultTemplates[name];\n if (!templatesByName) {\n return { template: `Unknown template: ${name}` };\n }\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return { template: templateByMode };\n }\n return { template: templatesByName.form };\n }\n checkTemplate(templates, names, modes) {\n for (const name of names) {\n const templatesByName = templates[name];\n if (templatesByName) {\n const { referenceAttributeName } = templatesByName;\n const templateByMode = this.checkTemplateMode(templatesByName, modes);\n if (templateByMode) {\n return { template: templateByMode, referenceAttributeName };\n }\n }\n }\n return null;\n }\n checkTemplateMode(templatesByName, modes) {\n for (const mode of modes) {\n const templateByMode = templatesByName[mode];\n if (templateByMode) {\n return templateByMode;\n }\n }\n return null;\n }\n getFormattedAttribute(attr) {\n return attr ? this.t(attr, { _userInput: true }).replace(/\"/g, '&quot;') : '';\n }\n getFormattedTooltip(tooltipValue) {\n const tooltip = this.interpolate(tooltipValue || '').replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n return this.getFormattedAttribute(tooltip);\n }\n isHtmlRenderMode() {\n return this.options.renderMode === 'html';\n }\n renderTemplate(name, data = {}, modeOption = '') {\n // Need to make this fall back to form if renderMode is not found similar to how we search templates.\n const mode = modeOption || this.options.renderMode || 'form';\n data.component = this.component;\n data.self = this;\n data.options = this.options;\n data.readOnly = this.options.readOnly;\n data.iconClass = this.iconClass.bind(this);\n data.size = this.size.bind(this);\n data.t = this.t.bind(this);\n data.transform = this.transform.bind(this);\n data.id = data.id || this.id;\n data.key = data.key || this.key;\n data.value = data.value || this.dataValue;\n data.disabled = this.disabled;\n data.builder = this.builderMode;\n data.render = (...args) => {\n console.warn(`Form.io 'render' template function is deprecated.\n If you need to render template (template A) inside of another template (template B),\n pass pre-compiled template A (use this.renderTemplate('template_A_name') as template context variable for template B`);\n return this.renderTemplate(...args);\n };\n data.label = data.labelInfo || this.labelInfo;\n data.tooltip = this.getFormattedTooltip(this.component.tooltip);\n // Allow more specific template names\n const names = [\n `${name}-${this.component.type}-${this.key}`,\n `${name}-${this.component.type}`,\n `${name}-${this.key}`,\n `${name}`,\n ];\n // Allow template alters.\n const { referenceAttributeName, template } = this.getTemplate(names, mode);\n if (referenceAttributeName) {\n this._referenceAttributeName = referenceAttributeName;\n }\n return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(template, data), data, mode);\n }\n /**\n * Sanitize an html string.\n * @param {string} dirty - The dirty html string to sanitize.\n * @param {boolean} forceSanitize - If we should force the sanitize to occur.\n * @param {object} options - The options for the sanitize.\n * @returns {*} - The sanitized html string.\n */\n sanitize(dirty, forceSanitize = false, options = {}) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n * @param {string} template - The template to render.\n * @param {object} data - The data to provide to the template.\n * @returns {HTMLElement | string} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n /**\n * Allows for modification of the component value prior to submission.\n * @param {*} input - The input to be modified.\n * @returns {*} - The modified input mapping for the extended component.\n */\n performInputMapping(input) {\n return input;\n }\n /**\n * Returns the component \"widget\" if one is available.\n * @returns {Widget|null} - The widget instance. null if not available.\n */\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n /**\n * Returns the native supported browser language.\n * @returns {string|null} - The native browser language that is supported.\n */\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components to perform special functions.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the next/previous page navigation.\n */\n beforePage() {\n return Promise.resolve(true);\n }\n /**\n * Called before the next page is triggered allowing the components to hook into the page navigation and perform tasks.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the next page navigation.\n */\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components to perform special async functions.\n * @returns {Promise<boolean>} - A promise to resolve when the component is no longer blocking the submission.\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n * @returns {string} - The submission timezone.\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n /**\n * Return the current timezone.\n * @returns {string} - The current timezone.\n */\n get timezone() {\n return this.getTimezone(this.component);\n }\n /**\n * Return the current timezone.\n * @param {object} settings - Settings to control how the timezone should be returned.\n * @returns {string} - The current timezone.\n */\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n /**\n *\n * @param {HTMLElement} element - The containing DOM element to query for the ref value.\n * @param {object} refs - The references to load.\n * @param {string} [referenceAttributeName] - The attribute name to use for the reference.\n */\n loadRefs(element, refs, referenceAttributeName) {\n if (!element) {\n return;\n }\n for (const ref in refs) {\n const refType = refs[ref];\n const isString = typeof refType === 'string';\n const selector = isString && refType.includes('scope')\n ? `:scope > [${referenceAttributeName || this._referenceAttributeName || 'ref'}=\"${ref}\"]`\n : `[${referenceAttributeName || this._referenceAttributeName || 'ref'}=\"${ref}\"]`;\n if (isString && refType.startsWith('single')) {\n this.refs[ref] = element.querySelector(selector);\n }\n else {\n this.refs[ref] = element.querySelectorAll(selector);\n }\n }\n }\n /**\n * Opens the modal element.\n * @param {string} template - The template to use for the modal dialog.\n */\n setOpenModalElement(template = null) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n /**\n * Returns the modal preview template.\n * @returns {string} - The modal preview template.\n */\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n let modalLabel;\n if (this.hasInput && ((_a = this.component.validate) === null || _a === void 0 ? void 0 : _a.required) && !this.isPDFReadOnlyMode) {\n modalLabel = { className: 'field-required' };\n }\n return this.renderTemplate('modalPreview', {\n previewText: this.getValueAsString(dataValue, { modalPreview: true }) || this.t('Click to set value'),\n messages: '',\n labelInfo: modalLabel,\n });\n }\n /**\n * Performs a complete build of a component, which empties, renders, sets the content in the DOM, and then finally attaches events.\n * @param {HTMLElement} element - The element to attach this component to.\n * @returns {Promise<void>} - A promise that resolves when the component has been built.\n */\n build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n /**\n * Renders a component as an HTML string.\n * @param {string} children - The contents of all the children HTML as a string.\n * @param {boolean} topLevel - If this is the topmost component that is being rendered.\n * @returns {string} - The rendered HTML string of a component.\n */\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n /**\n * Attaches all the tooltips provided the refs object.\n * @param {object} toolTipsRefs - The refs for the tooltips within your template.\n * @returns {void}\n */\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n /**\n * Create a new component modal for this component.\n * @param {HTMLElement} element - The element to attach the modal to.\n * @param {boolean} modalShouldBeOpened - TRUE if the modal should open immediately.\n * @param {any} currentValue - The current value of the component.\n * @returns {ComponentModal} - The created component modal.\n */\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\n }\n /**\n * Attaches all event listensers for this component to the DOM elements that were rendered.\n * @param {HTMLElement} element - The element to attach the listeners to.\n * @returns {Promise<void>} - Resolves when the component is done attaching to the DOM.\n */\n attach(element) {\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n const openModalTemplate = this.componentModal && modalShouldBeOpened\n ? this.componentModal.openModalTemplate\n : null;\n this.componentModal = this.createComponentModal(element, modalShouldBeOpened, currentValue);\n this.setOpenModalElement(openModalTemplate);\n }\n this.attached = true;\n this.setElement(element);\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n /**\n * Restors the \"focus\" on a component after a redraw event has occured.\n */\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n /**\n * Adds a keyboard shortcut to this component.\n * @param {HTMLElement} element - The element to attach the keyboard shortcut to.\n * @param {string} shortcut - The keyboard shortcut to add.\n * @returns {void}\n */\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n /**\n * Removes a keyboard shortcut from this component.\n * @param {HTMLElement} element - The element to remove the keyboard shortcut from.\n * @param {string} shortcut - The keyboard shortcut to remove.\n * @returns {void}\n */\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n // First iterate through each ref and delete the component so there are no dangling component references.\n lodash_1.default.each(this.refs, (ref) => {\n if (typeof ref === NodeList) {\n ref.forEach((elem) => {\n delete elem.component;\n });\n }\n else if (ref) {\n delete ref.component;\n }\n });\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n /**\n * Determines if the component should be refreshed based on the path of another component that changed.\n * @param {string} refreshData - The path of the data that needs to trigger a refresh.\n * @param {boolean} changed - Flag that is true if the data has been changed.\n * @param {any} flags - The flags for the checkData procedure.\n * @returns {void}\n */\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n /**\n * Iterates over a list of changes, and determines if the component should be refreshed if it is configured to refresh on any of those components.\n * @param {Array<any>} changes - The list of components that have changed.\n * @param {any} flags - The checkData flags.\n * @returns {void}\n */\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n * @param {any} value - The latest value of the component to check if it needs to be refreshed.\n * @returns {void}\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n * @param {any} component - The component to check if it is in the same context as this component.\n * @returns {boolean} - TRUE if the component is in the same context as this component.\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n /**\n * Determines if we are in \"view\" only mode.\n * @returns {boolean} - TRUE if we are in \"view\" only mode.\n */\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n /**\n * Sets the HTMLElement for this component.\n * @param {HTMLElement} element - The element that is attached to this component.\n * @returns {void}\n */\n setElement(element) {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n this.element = element;\n }\n /**\n * Creates an element to hold the \"view only\" version of this component.\n * @returns {HTMLElement} - The element for this component.\n */\n createViewOnlyElement() {\n this.setElement(this.ce('dl', {\n id: this.id\n }));\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n /**\n * The default value for the \"view only\" mode of a component if the value is not provided.\n * @returns {string} - The default value for this component.\n */\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n * @param {any} value - The current value of the component.\n * @param {any} options - The options for getValueAsString.\n * @returns {any|Array<any>} - The value as a string.\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n /**\n * Returns the value of the component as a string.\n * @param {any} value - The value for this component.\n * @param {any} options - The options for this component.\n * @returns {string} - The string representation of the value of this component.\n */\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n /**\n * Returns the string representation \"view\" of the component value.\n * @param {any} value - The value of the component.\n * @param {any} options - The options for this component.\n * @returns {string} - The string representation of the value of this component.\n */\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n /**\n * Updates the items list for this component. Useful for Select and other List component types.\n * @param {...any} args - The arguments to pass to the onChange event.\n * @returns {void}\n */\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * Returns the value for a specific item in a List type component.\n * @param {any} data - The data for this component.\n * @param {boolean} [forceUseValue] - if true, return 'value' property of the data\n * @returns {any} - The value of the item.\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n /**\n * Returns the item value for html mode.\n * @param {any} value - The value for this component.\n * @returns {any} - The value of the item for html mode.\n */\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n /**\n * Creates a modal to input the value of this component.\n * @param {HTMLElement} element - The element to attach the modal to.\n * @param {any} attr - A list of attributes to add to the modal.\n * @param {boolean} confirm - If we should add a confirmation to the modal that keeps it from closing unless confirmed.\n * @returns {HTMLElement} - The created modal element.\n */\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n /**\n * Uses CSS classes to show or hide an element.\n * @returns {boolean} - TRUE if the element has been css removed.\n */\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @returns {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n /**\n * Returns the component condition operator settings if available.\n * @returns {object} - The component condition operator settings.\n */\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n /**\n * Returns if the application is on a mobile device.\n * @returns {boolean} - TRUE if the application is on a mobile device.\n */\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement} - The wrapping element of this component.\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n * @param {any} additional - Additional context to provide.\n * @returns {any} - The evaluation context.\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n * @param {boolean} pristine - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n /**\n * Returns if the component is pristine.\n * @returns {boolean} - TRUE if the component is pristine.\n */\n get isPristine() {\n return this.pristine;\n }\n /**\n * Sets the dirty flag for this component.\n * @param {boolean} dirty - TRUE to make dirty, FALSE not dirty.\n */\n setDirty(dirty) {\n this.dirty = dirty;\n }\n /**\n * Returns if the component is dirty.\n * @returns {boolean} - TRUE if the component is dirty.\n */\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n /**\n * Returns the icon class for a given icon name.\n * @param {string} name - The name of the icon you wish to fetch provided the icon class. This is the \"font awesome\" version of the name of the icon.\n * @param {boolean} spinning - If the component should be spinning.\n * @returns {string} - The icon class for the equivalent icon in the iconset we are using.\n */\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n /**\n * Returns the size css class names for our current template.\n * @param {string} size - The size class name for the default iconset.\n * @returns {string} - The size class for our component.\n */\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n /**\n * Returns the visible errors for this component.\n * @returns {Array<object>} - The visible errors for this component.\n */\n get visibleErrors() {\n return this._visibleErrors;\n }\n /**\n * Returns all the errors for this component, visible or not.\n * @returns {Array<object>} - All the errors for this component.\n */\n get errors() {\n return this._errors;\n }\n /**\n * Returns the error label for this component.\n * @returns {string} - The error label for this component.\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param {string} type - The type of error to fetch the message for.\n * @returns {string} - The error message configured for this component.\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n /**\n * Sets the content, innerHTML, of an element to the sanitized content.\n * @param {HTMLElement} element - The element to set the innerHTML to.\n * @param {string} content - The HTML string content that we wish to set.\n * @param {boolean} forceSanitize - If we should force the content to be sanitized.\n * @param {any} sanitizeOptions - The options for the sanitize function.\n * @returns {boolean} - TRUE if the content was sanitized and set.\n */\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n /**\n * Restores the caret position in the input element after a refresh occurs.\n */\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n /**\n * Redraw the component.\n * @returns {Promise<void>} - A promise that resolves when the component is done redrawing.\n */\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.setElement(parent.children[index]);\n return this.attach(this.element);\n }\n /**\n * Rebuild and redraw a component.\n * @returns {Promise<void>} - A promise that resolves when the component is done rebuilding and redrawing.\n */\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n /**\n * Removes all event listeners attached to this component.\n */\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n /**\n * Returns if the dom node has the classes provided.\n * @param {HTMLElement} element - The element to check for the class.\n * @param {string} className - The name of the class to check.\n * @returns {boolean|void} - TRUE if the element has the class.\n */\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n /**\n * Adds a class to an HTML element.\n * @param {HTMLElement} element - The dom element to add the class to.\n * @param {string} className - The class name you wish to add.\n * @returns {this|void} - The component instance.\n */\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n /**\n * Removes a class from an element.\n * @param {HTMLElement} element - The element to remove the class from.\n * @param {string} className - The class name to remove.\n * @returns {this|void} - The component instance.\n */\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n * @returns {boolean} - TRUE if the component has a condition defined.\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n * @param {any} data - The data to check against.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is conditionally visible.\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n * @param {any} row - The row contextual data.\n * @param {any} data - The global data object.\n * @returns {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n * @param {any} data - The data to check against.\n * @param {any} flags - The flags passed to checkData function.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is visible.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param {any} data - The data to check against.\n * @param {any} flags - The flags passed to checkData function.\n * @param {any} row - The row data to check against.\n * @returns {boolean} - TRUE if the component is visible.\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n /**\n * Returns the component logic if applicable.\n * @returns {Array<object>} - The component logic.\n */\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n * @param {any} data - The data to check against.\n * @param {any} row - The row data to check against.\n * @returns {boolean|void} - TRUE if the component was altered.\n */\n fieldLogic(data = this.rootValue, row = this.data) {\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n /**\n * Retuns if the browser is Internet Explorer.\n * @returns {boolean} - TRUE if the browser is IE.\n */\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n /**\n * Defines the logic action value through evaluation.\n * @param {object} action - The action within the Logic system to perform.\n * @param {object} argsObject - The arguments to pass to the evaluation.\n * @returns {any} - The result of the evaluation.\n */\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n /**\n * Apply the actions of Logic for a component once the conditions have been met.\n * @param {object} newComponent - The new component to apply the actions to.\n * @param {Array<object>} actions - An array of actions\n * @param {any} result - The result of the conditional check in order to evaluate the actions.\n * @param {any} row - The contextual row data for this component.\n * @param {any} data - The global data object for the submission.\n * @returns {boolean} - TRUE if the component was altered.\n */\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n * @param {Array<object>|string} messages - An array of messages to add to the element.\n * @returns {void}\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n return this.renderTemplate('message', Object.assign({}, message));\n }).join(''));\n }\n }\n /**\n * Sets the form input widget error classes.\n * @param {Array<HTMLElement>} elements - An array of DOM elements to set the error classes on.\n * @param {boolean} dirty - If the input is dirty.\n * @param {boolean} hasErrors - If the input has errors.\n * @param {boolean} hasMessages - If the input has messages.\n * @param {HTMLElement} element - The wrapper element for all the other elements passed in first argument.\n * @returns {void}\n */\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n // do not set error classes for hidden components\n if (!this.visible) {\n return;\n }\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n /**\n * Adds the classes necessary to mark an element as invalid.\n * @param {HTMLElement} element - The element you wish to add the invalid classes to.\n * @param {boolean} invalid - TRUE if the component is invalid, FALSE otherwise.\n * @returns {void}\n */\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n /**\n * Clears the components data if it is conditionally hidden AND clearOnHide is set to true for this component.\n */\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n /**\n * Triggers a debounced onChange event for the root component (usually Webform).\n * @param {...any} args - The arguments to pass to the onChange event.\n */\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root && this.root.triggerChange) {\n this.root.triggerChange(...args);\n }\n }\n /**\n * Called when the component value has been changed. This will then trigger the root level onChange handler which\n * propagates the checkData methods for the full component tree.\n * @param {any} flags - The flags for the change event propagation.\n * @param {boolean} fromRoot - If the change event is from the root component.\n * @returns {boolean} - TRUE if the component has changed.\n */\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur' || this.component.validateOn === 'submit') {\n flags.noValidate = true;\n }\n if (this.component.onChange) {\n this.evaluate(this.component.onChange, {\n flags\n });\n }\n // Set the changed variable.\n const changed = {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: flags\n };\n // Emit the change.\n this.emit('componentChange', changed);\n // Do not propogate the modified flag.\n let modified = false;\n if (flags.modified) {\n modified = true;\n delete flags.modified;\n }\n // Bubble this change up to the top.\n if (!fromRoot) {\n this.triggerRootChange(flags, changed, modified);\n }\n return changed;\n }\n get wysiwygDefault() {\n return {\n quill: {\n theme: 'snow',\n placeholder: this.t(this.component.placeholder, { _userInput: true }),\n modules: {\n toolbar: [\n [{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown\n [{ 'header': [1, 2, 3, 4, 5, 6, false] }],\n [{ 'font': [] }],\n ['bold', 'italic', 'underline', 'strike', { 'script': 'sub' }, { 'script': 'super' }, 'clean'],\n [{ 'color': [] }, { 'background': [] }],\n [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }, { 'align': [] }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video', 'formula', 'source']\n ]\n }\n },\n ace: {\n theme: 'ace/theme/xcode',\n maxLines: 12,\n minLines: 12,\n tabSize: 2,\n mode: 'ace/mode/javascript',\n placeholder: this.t(this.component.placeholder, { _userInput: true })\n },\n ckeditor: {\n image: {\n toolbar: [\n 'imageTextAlternative',\n '|',\n 'imageStyle:full',\n 'imageStyle:alignLeft',\n 'imageStyle:alignCenter',\n 'imageStyle:alignRight'\n ],\n styles: [\n 'full',\n 'alignLeft',\n 'alignCenter',\n 'alignRight'\n ]\n },\n extraPlugins: []\n },\n default: {}\n };\n }\n addCKE(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? {} : settings;\n settings.base64Upload = this.component.isUploadEnabled ? false : true;\n settings.mediaEmbed = { previewsInData: true };\n settings = lodash_1.default.merge(this.wysiwygDefault.ckeditor, lodash_1.default.get(this.options, 'editors.ckeditor.settings', {}), settings);\n if (this.component.isUploadEnabled) {\n settings.extraPlugins.push((0, uploadAdapter_1.getFormioUploadAdapterPlugin)(this.fileService, this));\n }\n return Formio_1.Formio.requireLibrary('ckeditor', isIEBrowser ? 'CKEDITOR' : 'ClassicEditor', lodash_1.default.get(this.options, 'editors.ckeditor.src', `${Formio_1.Formio.cdn.ckeditor}/ckeditor.js`), true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n if (isIEBrowser) {\n const editor = CKEDITOR.replace(element);\n editor.on('change', () => onChange(editor.getData()));\n return Promise.resolve(editor);\n }\n else {\n return ClassicEditor.create(element, settings).then(editor => {\n editor.model.document.on('change', () => onChange(editor.data.get()));\n return editor;\n });\n }\n });\n }\n addQuill(element, settings, onChange) {\n settings = lodash_1.default.isEmpty(settings) ? this.wysiwygDefault.quill : settings;\n settings = lodash_1.default.merge(this.wysiwygDefault.quill, lodash_1.default.get(this.options, 'editors.quill.settings', {}), settings);\n settings = Object.assign(Object.assign({}, settings), { modules: Object.assign({ table: true }, settings.modules) });\n // Lazy load the quill css.\n Formio_1.Formio.requireLibrary(`quill-css-${settings.theme}`, 'Quill', [\n { type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` }\n ], true);\n // Lazy load the quill library.\n return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.min.js`), true)\n .then(() => {\n return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true)\n .then(() => {\n if (!element.parentNode) {\n return Promise.reject();\n }\n this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);\n /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */\n const txtArea = document.createElement('textarea');\n txtArea.setAttribute('class', 'quill-source-code');\n this.quill.addContainer('ql-custom').appendChild(txtArea);\n const qlSource = element.parentNode.querySelector('.ql-source');\n if (qlSource) {\n this.addEventListener(qlSource, 'click', (event) => {\n event.preventDefault();\n if (txtArea.style.display === 'inherit') {\n this.quill.setContents(this.quill.clipboard.convert({ html: txtArea.value }));\n }\n txtArea.style.display = (txtArea.style.display === 'none') ? 'inherit' : 'none';\n });\n }\n /** END CODEBLOCK */\n // Make sure to select cursor when they click on the element.\n this.addEventListener(element, 'click', () => this.quill.focus());\n // Allows users to skip toolbar items when tabbing though form\n const elm = document.querySelectorAll('.ql-formats > button');\n for (let i = 0; i < elm.length; i++) {\n elm[i].setAttribute('tabindex', '-1');\n }\n this.quill.on('text-change', () => {\n txtArea.value = this.quill.root.innerHTML;\n onChange(txtArea);\n });\n return this.quill;\n });\n });\n }\n get shouldSanitizeValue() {\n var _a;\n // Sanitize value if sanitizing for thw whole content is turned off\n return (((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitize) !== false);\n }\n addAce(element, settings, onChange) {\n if (!settings || (settings.theme === 'snow')) {\n const mode = settings ? settings.mode : '';\n settings = {};\n if (mode) {\n settings.mode = mode;\n }\n }\n settings = lodash_1.default.merge(this.wysiwygDefault.ace, lodash_1.default.get(this.options, 'editors.ace.settings', {}), settings || {});\n return Formio_1.Formio.requireLibrary('ace', 'ace', lodash_1.default.get(this.options, 'editors.ace.src', `${Formio_1.Formio.cdn.ace}/ace.js`), true)\n .then((editor) => {\n editor = editor.edit(element);\n editor.removeAllListeners('change');\n editor.setOptions(settings);\n editor.getSession().setMode(settings.mode);\n editor.on('change', () => onChange(editor.getValue()));\n if (settings.isUseWorkerDisabled) {\n editor.session.setUseWorker(false);\n }\n return editor;\n });\n }\n get tree() {\n return this.component.tree || false;\n }\n /**\n * The empty value for this component.\n * @returns {null} - The empty value for this component.\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n * @param {any} data - The global data object.\n * @returns {boolean} - TRUE if a value is set.\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n * @returns {*} - The root value for the component, typically the Webform data object.\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @returns {*} - The value for this component.\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n * @param {*} value - The value to set for this component.\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n * @param {number} index - The index to splice for an array component values.\n * @param {*} flags - The flags to use when splicing the value.\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n * @returns {*} - The value for the component.\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - For an array component or multiple values, this returns the value at a specific index.\n * @returns {*} - The value at the specified index.\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n * @param {*} value - The value to set for this component.\n * @param {*} flags - The flags to use when setting the value.\n * @returns {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n * @param {number} index - The index to set the value at.\n * @param {*} value - The value to set at the specified index.\n * @param {*} flags - The flags to use when setting the value.\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n * @param {*} value - The value to normalize before setting.\n * @returns {*} - The normalized value.\n */\n normalizeValue(value) {\n return value;\n }\n /**\n * Update a value of this component.\n * @param {*} value - The value to update.\n * @param {*} flags - The flags to use when updating the value.\n * @returns {boolean} - If the value changed.\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n * @param {...any} args - The arguments to pass to updateValue.\n * @returns {boolean} - If the value changed.\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.defaultValue || this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n * @param {*} newValue - The new value to check.\n * @param {*} oldValue - The existing value of the component.\n * @returns {boolean} - TRUE if the value has changed.\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n * @param {*} flags - The flags to use when triggering the on change event.\n * @param {boolean} changed - If the value has changed.\n * @returns {boolean} - If the value changed.\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n if (flags.fromSubmission) {\n // Reset the errors when a submission has been made and allow it to revalidate.\n this._errors = [];\n }\n this.triggerChange(flags);\n return true;\n }\n return false;\n }\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set or in builder mode\n if (this.builderMode || lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n this.calculatedValue = null;\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified && this.root.initialized) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n * @param {*} data - The data to perform the calculation with.\n * @param {*} flags - The flags to use when calculating the value.\n * @param {*} row - The contextual row data to use when performing the calculation.\n * @returns {boolean} - TRUE if the value changed.\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n * @returns {string} - The label text for this component.\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n * @param {string} value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n * @returns {*} root - The root component to search from.\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {boolean} ignoreCondition - If conditions for the component should be ignored when checking validity.\n * @param {*} row - Contextual row data for this component.\n * @returns {string} - The message to show when the component is invalid.\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n const validationScope = { errors: [] };\n (0, process_1.processOneSync)({\n component: this.component,\n data,\n row,\n path: this.path || this.component.key,\n scope: validationScope,\n instance: this,\n processors: [\n process_1.validateProcessInfo\n ]\n });\n const errors = validationScope.errors;\n const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this));\n return lodash_1.default.map(interpolatedErrors, 'message').join('\\n\\n');\n }\n /**\n * Returns if the component is valid or not.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @returns {boolean} - TRUE if the component is valid.\n */\n isValid(data, dirty) {\n return !this.invalidMessage(data, dirty);\n }\n setComponentValidity(errors, dirty, silentCheck) {\n if (silentCheck) {\n return [];\n }\n const messages = errors.filter(message => !message.fromServer);\n if (errors.length && !!messages.length && (!this.isEmpty(this.defaultValue) || dirty || !this.pristine)) {\n return this.setCustomValidity(messages, dirty);\n }\n else {\n return this.setCustomValidity('');\n }\n }\n /**\n * Interpolate errors from the validation methods.\n * @param {Array<any>} errors - An array of errors to interpolate.\n * @returns {Array<any>} - The interpolated errors.\n */\n interpolateErrors(errors) {\n var _a;\n const interpolatedErrors = FormioUtils.interpolateErrors(this.component, errors, this.t.bind(this));\n return ((_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.length) ? [...interpolatedErrors, ...this.serverErrors] : interpolatedErrors;\n }\n /**\n * Show component validation errors.\n * @param {*} errors - An array of errors that have occured.\n * @param {*} data - The root submission data.\n * @param {*} row - The contextual row data.\n * @param {*} flags - The flags to perform validation.\n * @returns {boolean} - TRUE if the component is valid.\n */\n showValidationErrors(errors, data, row, flags) {\n if (flags.silentCheck) {\n return [];\n }\n if (this.options.alwaysDirty) {\n flags.dirty = true;\n }\n if (flags.fromSubmission && this.hasValue(data)) {\n flags.dirty = true;\n }\n this.setDirty(flags.dirty);\n return this.setComponentValidity(errors, flags.dirty, flags.silentCheck, flags.fromSubmission);\n }\n /**\n * Perform a component validation.\n * @param {*} data - The root data you wish to use for this component.\n * @param {*} row - The contextual row data you wish to use for this component.\n * @param {*} flags - The flags to control the behavior of the validation.\n * @returns {Array<any>} - An array of errors if the component is invalid.\n */\n validateComponent(data = null, row = null, flags = {}) {\n data = data || this.rootValue;\n row = row || this.data;\n const { async = false } = flags;\n if (this.shouldSkipValidation(data, row, flags)) {\n return async ? Promise.resolve([]) : [];\n }\n const processContext = {\n component: this.component,\n data,\n row,\n value: this.validationValue,\n path: this.path || this.component.key,\n instance: this,\n scope: { errors: [] },\n processors: [\n process_1.validateProcessInfo\n ]\n };\n if (async) {\n return (0, process_1.processOne)(processContext).then(() => {\n this._errors = this.interpolateErrors(processContext.scope.errors);\n return this._errors;\n });\n }\n (0, process_1.processOneSync)(processContext);\n this._errors = this.interpolateErrors(processContext.scope.errors);\n return this._errors;\n }\n /**\n * Checks the validity of this component and sets the error message if it is invalid.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {*} row - The contextual row data for this component.\n * @param {*} flags - The flags to use when checking the validity.\n * @param {Array<any>} allErrors - An array of all errors that have occured so that it can be appended when another one occurs here.\n * @returns {boolean} - TRUE if the component is valid.\n */\n checkComponentValidity(data = null, dirty = false, row = null, flags = {}, allErrors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n flags.dirty = dirty || false;\n if (flags.async) {\n return this.validateComponent(data, row, flags).then((errors) => {\n allErrors.push(...errors);\n if (this.parent && this.parent.childErrors) {\n if (errors.length) {\n this.parent.childErrors.push(...errors);\n }\n else {\n lodash_1.default.remove(this.parent.childErrors, (err) => { var _a, _b; return (((_a = err === null || err === void 0 ? void 0 : err.component) === null || _a === void 0 ? void 0 : _a.key) || ((_b = err === null || err === void 0 ? void 0 : err.context) === null || _b === void 0 ? void 0 : _b.key)) === this.component.key; });\n }\n }\n this.showValidationErrors(errors, data, row, flags);\n return errors.length === 0;\n });\n }\n else {\n const errors = this.validateComponent(data, row, flags);\n this.showValidationErrors(errors, data, row, flags);\n allErrors.push(...errors);\n if (this.parent && this.parent.childErrors) {\n if (errors.length) {\n this.parent.childErrors.push(...errors);\n }\n else {\n lodash_1.default.remove(this.parent.childErrors, (err) => { var _a, _b; return (((_a = err === null || err === void 0 ? void 0 : err.component) === null || _a === void 0 ? void 0 : _a.key) || ((_b = err === null || err === void 0 ? void 0 : err.context) === null || _b === void 0 ? void 0 : _b.key)) === this.component.key; });\n }\n }\n return errors.length === 0;\n }\n }\n /**\n * Checks the validity of the component.\n * @param {*} data - The data to check if the component is valid.\n * @param {boolean} dirty - If the component is dirty.\n * @param {*} row - The contextual row data for this component.\n * @param {boolean} silentCheck - If the check should be silent and not set the error messages.\n * @param {Array<any>} errors - An array of all errors that have occured so that it can be appended when another one occurs here.\n * @returns {boolean} - TRUE if the component is valid.\n */\n checkValidity(data = null, dirty = false, row = null, silentCheck = false, errors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n return this.checkComponentValidity(data, dirty, row, { silentCheck }, errors);\n }\n checkAsyncValidity(data = null, dirty = false, row = null, silentCheck = false, errors = []) {\n return this.checkComponentValidity(data, dirty, row, { async: true, silentCheck }, errors);\n }\n /**\n * Check the conditions, calculations, and validity of a single component and triggers an update if\n * something changed.\n * @param {*} data - The root data of the change event.\n * @param {*} flags - The flags from this change event.\n * @param {*} row - The contextual row data for this component.\n * @returns {void|boolean} - TRUE if no check should be performed on the component.\n */\n checkData(data = null, flags = null, row = null) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n }\n checkModal(errors = [], dirty = false) {\n const messages = errors.filter(error => !error.fromServer);\n const isValid = errors.length === 0;\n if (!this.component.modalEdit || !this.componentModal) {\n return;\n }\n if (dirty && !isValid) {\n this.setErrorClasses([this.refs.openModal], dirty, !isValid, !!messages.length, this.refs.openModalWrapper);\n }\n else {\n this.clearErrorClasses(this.refs.openModalWrapper);\n }\n }\n get validationValue() {\n return this.dataValue;\n }\n isEmpty(value = this.dataValue) {\n const isEmptyArray = (lodash_1.default.isArray(value) && value.length === 1) ? lodash_1.default.isEqual(value[0], this.emptyValue) : false;\n return value == null || value.length === 0 || lodash_1.default.isEqual(value, this.emptyValue) || isEmptyArray;\n }\n isEqual(valueA, valueB = this.dataValue) {\n return (this.isEmpty(valueA) && this.isEmpty(valueB)) || lodash_1.default.isEqual(valueA, valueB);\n }\n /**\n * Check if a component is eligible for multiple validation\n * @returns {boolean} - TRUE if the component is eligible for multiple validation.\n */\n validateMultiple() {\n return true;\n }\n clearErrorClasses(element = this.element) {\n this.removeClass(element, this.options.componentErrorClass);\n this.removeClass(element, 'alert alert-danger');\n this.removeClass(element, 'has-error');\n this.removeClass(element, 'has-message');\n }\n setInputWidgetErrorClasses(inputRefs, hasErrors) {\n if (!this.isInputComponent || !this.component.widget || !(inputRefs === null || inputRefs === void 0 ? void 0 : inputRefs.length)) {\n return;\n }\n inputRefs.forEach((input) => {\n if ((input === null || input === void 0 ? void 0 : input.widget) && input.widget.setErrorClasses) {\n input.widget.setErrorClasses(hasErrors);\n }\n });\n }\n addFocusBlurEvents(element) {\n this.addEventListener(element, 'focus', () => {\n if (this.root.focusedComponent !== this) {\n if (this.root.pendingBlur) {\n this.root.pendingBlur();\n }\n this.root.focusedComponent = this;\n this.emit('focus', this);\n }\n else if (this.root.focusedComponent === this && this.root.pendingBlur) {\n this.root.pendingBlur.cancel();\n this.root.pendingBlur = null;\n }\n });\n this.addEventListener(element, 'blur', () => {\n this.root.pendingBlur = FormioUtils.delay(() => {\n this.emit('blur', this);\n if (this.component.validateOn === 'blur') {\n this.root.triggerChange({ fromBlur: true }, {\n instance: this,\n component: this.component,\n value: this.dataValue,\n flags: { fromBlur: true }\n });\n }\n this.root.focusedComponent = null;\n this.root.pendingBlur = null;\n });\n });\n }\n // eslint-disable-next-line max-statements\n setCustomValidity(messages, dirty, external) {\n const inputRefs = this.isInputComponent ? this.refs.input || [] : null;\n if (typeof messages === 'string' && messages) {\n messages = {\n level: 'error',\n message: messages,\n component: this.component,\n };\n }\n if (!Array.isArray(messages)) {\n if (messages) {\n messages = [messages];\n }\n else {\n messages = [];\n }\n }\n const errors = messages.filter(message => message.level === 'error');\n let invalidInputRefs = inputRefs;\n // Filter the invalid input refs in multiple components\n if (this.component.multiple) {\n const refsArray = Array.from(inputRefs);\n refsArray.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), false);\n });\n this.setInputWidgetErrorClasses(refsArray, false);\n invalidInputRefs = refsArray.filter((ref, index) => {\n var _a;\n return (_a = messages.some) === null || _a === void 0 ? void 0 : _a.call(messages, (msg) => {\n var _a;\n return ((_a = msg === null || msg === void 0 ? void 0 : msg.context) === null || _a === void 0 ? void 0 : _a.index) === index;\n });\n });\n }\n if (messages.length) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n this.emit('componentError', {\n instance: this,\n component: this.component,\n message: messages[0].message,\n messages,\n external: !!external,\n });\n this.addMessages(messages, dirty, invalidInputRefs);\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, !!errors.length, !!messages.length);\n }\n }\n else if (!errors.length || (errors[0].external === !!external)) {\n if (this.refs.messageContainer) {\n this.empty(this.refs.messageContainer);\n }\n if (this.refs.modalMessageContainer) {\n this.empty(this.refs.modalMessageContainer);\n }\n if (invalidInputRefs) {\n this.setErrorClasses(invalidInputRefs, dirty, !!errors.length, !!messages.length);\n }\n this.clearErrorClasses();\n }\n this._visibleErrors = messages;\n return messages;\n }\n /**\n * Determines if the value of this component is hidden from the user as if it is coming from the server, but is\n * protected.\n * @returns {boolean|*} - TRUE if the value is hidden.\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, row, flags = {}) {\n const { validateWhenHidden = false } = this.component || {};\n const forceValidOnHidden = (!this.visible || !this.checkCondition(row, data)) && !validateWhenHidden;\n if (forceValidOnHidden) {\n // If this component is forced valid when it is hidden, then we also need to reset the errors for this component.\n this._errors = [];\n }\n const rules = [\n // Do not validate if the flags say not too.\n () => flags.noValidate,\n // Force valid if component is read-only\n () => this.options.readOnly,\n // Do not check validations if component is not an input component.\n () => !this.hasInput,\n // Check to see if we are editing and if so, check component persistence.\n () => this.isValueHidden(),\n // Force valid if component is hidden.\n () => forceValidOnHidden\n ];\n return rules.some(pred => pred());\n }\n // Maintain reverse compatibility.\n whenReady() {\n console.warn('The whenReady() method has been deprecated. Please use the dataReady property instead.');\n return this.dataReady;\n }\n get dataReady() {\n return Promise.resolve();\n }\n /**\n * Prints out the value of this component as a string value.\n * @param {*} value - The value to print out.\n * @returns {string} - The string representation of the value.\n */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @returns {boolean} - TRUE if the component is disabled.\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n * @param {boolean} disabled - TRUE to disable the component.\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n * @returns {*} - The components \"input\" DOM element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index = (this.refs.input.length - 1)) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = this.refs.input[index];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n * @returns {import('@formio/core').Formio} - The Formio instance file service.\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = (0, utils_1.getScriptPlugin)(property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n src = Array.isArray(src) ? src : [src];\n src.forEach((lib) => {\n let attrs = {};\n let elementType = '';\n if (typeof lib === 'string') {\n lib = {\n type: 'script',\n src: lib\n };\n }\n switch (lib.type) {\n case 'script':\n elementType = 'script';\n attrs = {\n src: lib.src,\n type: 'text/javascript',\n defer: true,\n async: true\n };\n break;\n case 'styles':\n elementType = 'link';\n attrs = {\n href: lib.src,\n rel: 'stylesheet'\n };\n break;\n }\n // Add the script to the top page.\n const script = document.createElement(elementType);\n for (const attr in attrs) {\n script.setAttribute(attr, attrs[attr]);\n }\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n setTimeout(function checkLibrary() {\n const plugin = (0, utils_1.getScriptPlugin)(property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n // check again after 200 ms.\n setTimeout(checkLibrary, 200);\n }\n }, 200);\n }\n }\n }\n return Component.externalLibraries[name].ready;\n};\nComponent.libraryReady = function (name) {\n if (Component.externalLibraries.hasOwnProperty(name) &&\n Component.externalLibraries[name].ready) {\n return Component.externalLibraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/Component.js?");
5472
5472
 
5473
5473
  /***/ }),
5474
5474
 
@@ -5633,7 +5633,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
5633
5633
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5634
5634
 
5635
5635
  "use strict";
5636
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nclass Multivalue extends Field_1.default {\n /**\n * Normalize values coming into updateValue.\n * @param {*} value - The value to normalize before setting.\n * @param {object} flags - Flags to use when normalizing the value.\n * @param {*} emptyValue - The empty value for the field.\n * @returns {*} - The normalized value.\n */\n normalizeValue(value, flags = {}, emptyValue = this.emptyValue) {\n const underlyingValueShouldBeArray = core_1.Utils.getModelType(this.component) === 'array' || this.component.storeas === 'array' || Array.isArray(emptyValue);\n if (this.component.multiple) {\n if (Array.isArray(value)) {\n if (underlyingValueShouldBeArray) {\n if (value.length === 0 || !Array.isArray(value[0])) {\n return [value];\n }\n }\n if (value.length === 0) {\n return [emptyValue];\n }\n return super.normalizeValue(value, flags);\n }\n else {\n return super.normalizeValue(value == null ? [emptyValue] : [value], flags);\n }\n }\n else {\n if (Array.isArray(value) && !underlyingValueShouldBeArray) {\n if (this.component.storeas === 'string') {\n return super.normalizeValue(value.join(this.delimiter || ''), flags);\n }\n if (this.component.type === 'hidden' && value.length > 1) {\n return super.normalizeValue(value, flags);\n }\n return super.normalizeValue(value[0] || emptyValue, flags);\n }\n else {\n return super.normalizeValue(value, flags);\n }\n }\n }\n get dataValue() {\n return this.normalizeValue(super.dataValue);\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get defaultValue() {\n let value = super.defaultValue;\n if (this.component.multiple) {\n if (lodash_1.default.isArray(value)) {\n value = !value.length ? [super.emptyValue] : value;\n }\n else {\n value = [value];\n }\n }\n return value;\n }\n get addAnother() {\n return this.t(this.component.addAnother || 'Add Another');\n }\n /**\n * @returns {Field} - The created field.\n */\n render() {\n let dataValue = this.normalizeValue(this.dataValue);\n return this.component.hasOwnProperty('multiple') && this.component.multiple\n ? super.render(this.renderTemplate('multiValueTable', {\n rows: dataValue.map(this.renderRow.bind(this)).join(''),\n disabled: this.disabled,\n addAnother: this.addAnother,\n }))\n : super.render(`<div ${this._referenceAttributeName}=\"element\">\n ${this.renderElement(this.component.type !== 'hidden' ? dataValue : '')}\n </div>`);\n }\n renderElement() {\n return '';\n }\n /**\n * Renders a single row for multi-value components.\n * @param {any} value - The value associated with the row to render.\n * @param {number} index - The index of the row in the multi-value list.\n * @returns {any} Returns the HTML string representation of the row.\n */\n renderRow(value, index) {\n return this.renderTemplate('multiValueRow', {\n index,\n disabled: this.disabled,\n element: `${this.renderElement(value, index)}`,\n });\n }\n /**\n * @param {HTMLElement} dom - The DOM element to which the component will attach.\n * @returns {Promise} - Promise that resolves when all asynchronous tasks that have finished.\n */\n attach(dom) {\n const superAttach = super.attach(dom);\n this.loadRefs(dom, {\n addButton: 'multiple',\n input: 'multiple',\n removeRow: 'multiple',\n mask: 'multiple',\n select: 'multiple',\n });\n const promises = [];\n this.refs.input.forEach((element, index) => {\n promises.push(this.attachElement.call(this, element, index));\n });\n if (!this.component.multiple) {\n return Promise.all(promises);\n }\n this.refs.removeRow.forEach((removeButton, index) => {\n this.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n this.removeValue(index);\n });\n });\n // If single value field.\n this.refs.addButton.forEach((addButton) => {\n this.addEventListener(addButton, 'click', (event) => {\n event.preventDefault();\n this.addValue();\n });\n });\n return superAttach.then(() => {\n return Promise.all(promises);\n });\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n if (this.refs.input && this.refs.input.length) {\n this.refs.input.forEach((input) => {\n if (input.mask) {\n input.mask.destroy ? input.mask.destroy() : input.mask.remove();\n }\n if (input.widget) {\n input.widget.destroy();\n }\n });\n }\n if (this.refs.mask && this.refs.mask.length) {\n this.refs.mask.forEach((input) => {\n if (input.mask) {\n input.mask.destroy ? input.mask.destroy() : input.mask.remove();\n }\n });\n }\n super.detach();\n }\n /**\n * Attach inputs to the element.\n * @param {HTMLElement} element - The element to attach.\n * @param {number} index - The index of the element to attach.\n */\n attachElement(element, index) {\n this.addEventListener(element, this.inputInfo.changeEvent, () => {\n // Delay update slightly to give input mask a chance to run.\n const textCase = lodash_1.default.get(this.component, 'case', 'mixed');\n if (textCase !== 'mixed') {\n const { selectionStart, selectionEnd, } = element;\n if (textCase === 'uppercase' && element.value) {\n element.value = element.value.toUpperCase();\n }\n if (textCase === 'lowercase' && element.value) {\n element.value = element.value.toLowerCase();\n }\n if (element.selectionStart && element.selectionEnd) {\n element.selectionStart = selectionStart;\n element.selectionEnd = selectionEnd;\n }\n }\n try {\n this.saveCaretPosition(element, index);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n // If a mask is present, delay the update to allow mask to update first.\n if (element.mask) {\n setTimeout(() => {\n return this.updateValue(null, {\n modified: (this.component.type !== 'hidden')\n }, index);\n }, 1);\n }\n else {\n return this.updateValue(null, {\n modified: (this.component.type !== 'hidden')\n }, index);\n }\n });\n if (!this.attachMultiMask(index)) {\n const applyMask = () => {\n this.setInputMask(element);\n const valueMask = this.component.inputMask;\n const displayMask = this.component.displayMask;\n if (valueMask && displayMask && displayMask !== valueMask && this.refs.valueMaskInput) {\n this.setInputMask(this.refs.valueMaskInput, valueMask);\n }\n };\n if (this.inputInfo.changeEvent === 'blur') {\n this.addEventListener(element, this.inputInfo.changeEvent, () => {\n applyMask();\n this.dataValue = this.refs.input[0].value;\n if (this.checkComponentValidity()) {\n this.updateComponentValue(this.refs.input[0].value);\n }\n });\n }\n else {\n applyMask();\n }\n }\n }\n /**\n * Event handler for selecting a mask from a dropdown.\n * @param {Event} event - Event triggered by changing the selected option in mask.\n */\n onSelectMaskHandler(event) {\n this.updateMask(event.target.maskInput, this.getMaskPattern(event.target.value));\n }\n /**\n * Retrieves the mask pattern for a given mask name\n * @param {string} maskName - The name of the mask to retrieve.\n * @returns {any} The mask pattern associated with the given mask name.\n */\n getMaskPattern(maskName) {\n if (!this.multiMasks) {\n this.multiMasks = {};\n }\n if (this.multiMasks[maskName]) {\n return this.multiMasks[maskName];\n }\n const mask = this.component.inputMasks.find(inputMask => inputMask.label === maskName);\n this.multiMasks[maskName] = mask ? mask.mask : this.component.inputMasks[0].mask;\n return this.multiMasks[maskName];\n }\n /**\n * Attaches a selectable mask to an input field based on its configuration.\n * @param {number} index - The index of the select or input in component array.\n * @returns {boolean} - Returns true if the mask was successfully attached\n */\n attachMultiMask(index) {\n if (!(this.isMultipleMasksField && this.component.inputMasks.length && this.refs.input.length)) {\n return false;\n }\n const maskSelect = this.refs.select[index];\n maskSelect.onchange = this.onSelectMaskHandler.bind(this);\n maskSelect.maskInput = this.refs.mask[index];\n this.setInputMask(maskSelect.maskInput, this.component.inputMasks[0].mask);\n return true;\n }\n /**\n * @param {any} input - The input element on which the mask is to be applied.\n * @param {string} mask - The mask pattern to apply to the input element. Exit early if no mask.\n */\n updateMask(input, mask) {\n if (!mask) {\n return;\n }\n this.setInputMask(input, mask, !this.component.placeholder);\n this.updateValue();\n }\n /**\n * Adds a new empty value to the data array.\n * @param {any} value -A value to be added to the data array.\n */\n addNewValue(value) {\n if (value === undefined) {\n value = this.component.defaultValue ?\n this.component.defaultValue : this.emptyValue;\n // If default is an empty aray, default back to empty value.\n if (Array.isArray(value) && value.length === 0) {\n value = this.emptyValue;\n }\n }\n let dataValue = this.dataValue || [];\n if (!Array.isArray(dataValue)) {\n dataValue = [dataValue];\n }\n if (Array.isArray(value)) {\n dataValue = dataValue.concat(value);\n }\n else {\n dataValue.push(value);\n }\n this.dataValue = dataValue;\n }\n /**\n * Adds a new empty value to the data array, and add a new row to contain it.\n */\n addValue() {\n this.addNewValue();\n this.redraw();\n this.checkConditions();\n if (!this.isEmpty(this.dataValue)) {\n this.restoreValue();\n }\n if (this.root) {\n this.root.onChange();\n }\n }\n}\nexports[\"default\"] = Multivalue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/multivalue/Multivalue.js?");
5636
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nclass Multivalue extends Field_1.default {\n /**\n * Normalize values coming into updateValue.\n * @param {*} value - The value to normalize before setting.\n * @param {object} flags - Flags to use when normalizing the value.\n * @param {*} emptyValue - The empty value for the field.\n * @returns {*} - The normalized value.\n */\n normalizeValue(value, flags = {}, emptyValue = this.emptyValue) {\n const underlyingValueShouldBeArray = core_1.Utils.getModelType(this.component) === 'array' || this.component.storeas === 'array' || Array.isArray(emptyValue);\n if (this.component.multiple) {\n if (Array.isArray(value)) {\n if (underlyingValueShouldBeArray) {\n if (value.length === 0 || !Array.isArray(value[0])) {\n return [value];\n }\n }\n if (value.length === 0) {\n return [emptyValue];\n }\n return super.normalizeValue(value, flags);\n }\n else {\n return super.normalizeValue(value == null ? [emptyValue] : [value], flags);\n }\n }\n else {\n if (Array.isArray(value) && !underlyingValueShouldBeArray) {\n if (core_1.Utils.getModelType(this.component) === 'any') {\n return super.normalizeValue(value, flags);\n }\n if (this.component.storeas === 'string') {\n return super.normalizeValue(value.join(this.delimiter || ''), flags);\n }\n return super.normalizeValue(value[0] || emptyValue, flags);\n }\n else {\n return super.normalizeValue(value, flags);\n }\n }\n }\n get dataValue() {\n return this.normalizeValue(super.dataValue);\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get defaultValue() {\n let value = super.defaultValue;\n if (this.component.multiple) {\n if (lodash_1.default.isArray(value)) {\n value = !value.length ? [super.emptyValue] : value;\n }\n else {\n value = [value];\n }\n }\n return value;\n }\n get addAnother() {\n return this.t(this.component.addAnother || 'Add Another');\n }\n /**\n * @returns {Field} - The created field.\n */\n render() {\n let dataValue = this.normalizeValue(this.dataValue);\n return this.component.hasOwnProperty('multiple') && this.component.multiple\n ? super.render(this.renderTemplate('multiValueTable', {\n rows: dataValue.map(this.renderRow.bind(this)).join(''),\n disabled: this.disabled,\n addAnother: this.addAnother,\n }))\n : super.render(`<div ${this._referenceAttributeName}=\"element\">\n ${this.renderElement(this.component.type !== 'hidden' ? dataValue : '')}\n </div>`);\n }\n renderElement() {\n return '';\n }\n /**\n * Renders a single row for multi-value components.\n * @param {any} value - The value associated with the row to render.\n * @param {number} index - The index of the row in the multi-value list.\n * @returns {any} Returns the HTML string representation of the row.\n */\n renderRow(value, index) {\n return this.renderTemplate('multiValueRow', {\n index,\n disabled: this.disabled,\n element: `${this.renderElement(value, index)}`,\n });\n }\n /**\n * @param {HTMLElement} dom - The DOM element to which the component will attach.\n * @returns {Promise} - Promise that resolves when all asynchronous tasks that have finished.\n */\n attach(dom) {\n const superAttach = super.attach(dom);\n this.loadRefs(dom, {\n addButton: 'multiple',\n input: 'multiple',\n removeRow: 'multiple',\n mask: 'multiple',\n select: 'multiple',\n });\n const promises = [];\n this.refs.input.forEach((element, index) => {\n promises.push(this.attachElement.call(this, element, index));\n });\n if (!this.component.multiple) {\n return Promise.all(promises);\n }\n this.refs.removeRow.forEach((removeButton, index) => {\n this.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n this.removeValue(index);\n });\n });\n // If single value field.\n this.refs.addButton.forEach((addButton) => {\n this.addEventListener(addButton, 'click', (event) => {\n event.preventDefault();\n this.addValue();\n });\n });\n return superAttach.then(() => {\n return Promise.all(promises);\n });\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n if (this.refs.input && this.refs.input.length) {\n this.refs.input.forEach((input) => {\n if (input.mask) {\n input.mask.destroy ? input.mask.destroy() : input.mask.remove();\n }\n if (input.widget) {\n input.widget.destroy();\n }\n });\n }\n if (this.refs.mask && this.refs.mask.length) {\n this.refs.mask.forEach((input) => {\n if (input.mask) {\n input.mask.destroy ? input.mask.destroy() : input.mask.remove();\n }\n });\n }\n super.detach();\n }\n /**\n * Attach inputs to the element.\n * @param {HTMLElement} element - The element to attach.\n * @param {number} index - The index of the element to attach.\n */\n attachElement(element, index) {\n this.addEventListener(element, this.inputInfo.changeEvent, () => {\n // Delay update slightly to give input mask a chance to run.\n const textCase = lodash_1.default.get(this.component, 'case', 'mixed');\n if (textCase !== 'mixed') {\n const { selectionStart, selectionEnd, } = element;\n if (textCase === 'uppercase' && element.value) {\n element.value = element.value.toUpperCase();\n }\n if (textCase === 'lowercase' && element.value) {\n element.value = element.value.toLowerCase();\n }\n if (element.selectionStart && element.selectionEnd) {\n element.selectionStart = selectionStart;\n element.selectionEnd = selectionEnd;\n }\n }\n try {\n this.saveCaretPosition(element, index);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n // If a mask is present, delay the update to allow mask to update first.\n if (element.mask) {\n setTimeout(() => {\n return this.updateValue(null, {\n modified: (this.component.type !== 'hidden')\n }, index);\n }, 1);\n }\n else {\n return this.updateValue(null, {\n modified: (this.component.type !== 'hidden')\n }, index);\n }\n });\n if (!this.attachMultiMask(index)) {\n const applyMask = () => {\n this.setInputMask(element);\n const valueMask = this.component.inputMask;\n const displayMask = this.component.displayMask;\n if (valueMask && displayMask && displayMask !== valueMask && this.refs.valueMaskInput) {\n this.setInputMask(this.refs.valueMaskInput, valueMask);\n }\n };\n if (this.inputInfo.changeEvent === 'blur') {\n this.addEventListener(element, this.inputInfo.changeEvent, () => {\n applyMask();\n this.dataValue = this.refs.input[0].value;\n if (this.checkComponentValidity()) {\n this.updateComponentValue(this.refs.input[0].value);\n }\n });\n }\n else {\n applyMask();\n }\n }\n }\n /**\n * Event handler for selecting a mask from a dropdown.\n * @param {Event} event - Event triggered by changing the selected option in mask.\n */\n onSelectMaskHandler(event) {\n this.updateMask(event.target.maskInput, this.getMaskPattern(event.target.value));\n }\n /**\n * Retrieves the mask pattern for a given mask name\n * @param {string} maskName - The name of the mask to retrieve.\n * @returns {any} The mask pattern associated with the given mask name.\n */\n getMaskPattern(maskName) {\n if (!this.multiMasks) {\n this.multiMasks = {};\n }\n if (this.multiMasks[maskName]) {\n return this.multiMasks[maskName];\n }\n const mask = this.component.inputMasks.find(inputMask => inputMask.label === maskName);\n this.multiMasks[maskName] = mask ? mask.mask : this.component.inputMasks[0].mask;\n return this.multiMasks[maskName];\n }\n /**\n * Attaches a selectable mask to an input field based on its configuration.\n * @param {number} index - The index of the select or input in component array.\n * @returns {boolean} - Returns true if the mask was successfully attached\n */\n attachMultiMask(index) {\n if (!(this.isMultipleMasksField && this.component.inputMasks.length && this.refs.input.length)) {\n return false;\n }\n const maskSelect = this.refs.select[index];\n maskSelect.onchange = this.onSelectMaskHandler.bind(this);\n maskSelect.maskInput = this.refs.mask[index];\n this.setInputMask(maskSelect.maskInput, this.component.inputMasks[0].mask);\n return true;\n }\n /**\n * @param {any} input - The input element on which the mask is to be applied.\n * @param {string} mask - The mask pattern to apply to the input element. Exit early if no mask.\n */\n updateMask(input, mask) {\n if (!mask) {\n return;\n }\n this.setInputMask(input, mask, !this.component.placeholder);\n this.updateValue();\n }\n /**\n * Adds a new empty value to the data array.\n * @param {any} value -A value to be added to the data array.\n */\n addNewValue(value) {\n if (value === undefined) {\n value = this.component.defaultValue ?\n this.component.defaultValue : this.emptyValue;\n // If default is an empty aray, default back to empty value.\n if (Array.isArray(value) && value.length === 0) {\n value = this.emptyValue;\n }\n }\n let dataValue = this.dataValue || [];\n if (!Array.isArray(dataValue)) {\n dataValue = [dataValue];\n }\n if (Array.isArray(value)) {\n dataValue = dataValue.concat(value);\n }\n else {\n dataValue.push(value);\n }\n this.dataValue = dataValue;\n }\n /**\n * Adds a new empty value to the data array, and add a new row to contain it.\n */\n addValue() {\n this.addNewValue();\n this.redraw();\n this.checkConditions();\n if (!this.isEmpty(this.dataValue)) {\n this.restoreValue();\n }\n if (this.root) {\n this.root.onChange();\n }\n }\n}\nexports[\"default\"] = Multivalue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/multivalue/Multivalue.js?");
5637
5637
 
5638
5638
  /***/ }),
5639
5639
 
@@ -6205,7 +6205,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
6205
6205
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6206
6206
 
6207
6207
  "use strict";
6208
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DayComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'day',\n label: 'Day',\n key: 'day',\n fields: {\n day: {\n type: 'number',\n placeholder: '',\n required: false\n },\n month: {\n type: 'select',\n placeholder: '',\n required: false\n },\n year: {\n type: 'number',\n placeholder: '',\n required: false\n }\n },\n dayFirst: false,\n defaultValue: ''\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Day',\n group: 'advanced',\n icon: 'calendar',\n documentation: '/userguide/form-building/advanced-components#day',\n weight: 50,\n schema: DayComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isDateEqual', 'isNotDateEqual', 'isEmpty', 'isNotEmpty', 'dateLessThan', 'dateGreaterThan', 'dateLessThanOrEqual', 'dateGreaterThanOrEqual'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.string];\n }\n constructor(component, options, data) {\n if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {\n component.maxDate = (0, moment_1.default)(component.maxDate, 'YYYY-MM-DD').toISOString();\n }\n if (component.minDate && component.minDate.indexOf('moment(') === -1) {\n component.minDate = (0, moment_1.default)(component.minDate, 'YYYY-MM-DD').toISOString();\n }\n super(component, options, data);\n }\n static get serverConditionSettings() {\n return DayComponent.conditionOperatorsSettings;\n }\n /**\n * The empty value for day component.\n * @returns {''} - The empty value of the day component.\n */\n get emptyValue() {\n return '';\n }\n get valueMask() {\n return /^\\d{2}\\/\\d{2}\\/\\d{4}$/;\n }\n get dayRequired() {\n return this.showDay && lodash_1.default.get(this.component, 'fields.day.required', false);\n }\n get showDay() {\n return !lodash_1.default.get(this.component, 'fields.day.hide', false);\n }\n get monthRequired() {\n return this.showMonth && lodash_1.default.get(this.component, 'fields.month.required', false);\n }\n get showMonth() {\n return !lodash_1.default.get(this.component, 'fields.month.hide', false);\n }\n get yearRequired() {\n return this.showYear && lodash_1.default.get(this.component, 'fields.year.required', false);\n }\n get showYear() {\n return !lodash_1.default.get(this.component, 'fields.year.hide', false);\n }\n get defaultSchema() {\n return DayComponent.schema();\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'input';\n info.attr.type = 'hidden';\n info.changeEvent = 'input';\n return info;\n }\n inputDefinition(name) {\n let min, max;\n if (name === 'day') {\n min = 1;\n max = 31;\n }\n if (name === 'month') {\n min = 1;\n max = 12;\n }\n if (name === 'year') {\n min = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n max = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 1900;\n }\n return {\n type: 'input',\n ref: name,\n attr: {\n id: `${this.component.key}-${name}`,\n class: `form-control ${this.transform('class', `formio-day-component-${name}`)}`,\n type: this.component.fields[name].type === 'select' ? 'select' : 'number',\n placeholder: this.t(this.component.fields[name].placeholder),\n step: 1,\n min,\n max,\n }\n };\n }\n selectDefinition(name) {\n return {\n multiple: false,\n ref: name,\n widget: 'html5',\n attr: {\n id: `${this.component.key}-${name}`,\n class: 'form-control',\n name,\n lang: this.options.language\n }\n };\n }\n get days() {\n if (this._days) {\n return this._days;\n }\n this._days = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.day.placeholder', '') }\n ];\n for (let x = 1; x <= 31; x++) {\n this._days.push({\n value: x,\n label: x.toString()\n });\n }\n return this._days;\n }\n get months() {\n if (this._months) {\n return this._months;\n }\n this._months = [\n {\n value: '',\n label: lodash_1.default.get(this.component, 'fields.month.placeholder') || (this.hideInputLabels ? this.t('Month') : '')\n },\n { value: 1, label: 'January' },\n { value: 2, label: 'February' },\n { value: 3, label: 'March' },\n { value: 4, label: 'April' },\n { value: 5, label: 'May' },\n { value: 6, label: 'June' },\n { value: 7, label: 'July' },\n { value: 8, label: 'August' },\n { value: 9, label: 'September' },\n { value: 10, label: 'October' },\n { value: 11, label: 'November' },\n { value: 12, label: 'December' }\n ];\n return this._months;\n }\n get years() {\n if (this._years) {\n return this._years;\n }\n this._years = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.year.placeholder', '') }\n ];\n const minYears = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n const maxYears = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 2030;\n for (let x = minYears; x <= maxYears; x++) {\n this._years.push({\n value: x,\n label: x.toString()\n });\n }\n return this._years;\n }\n setErrorClasses(elements, dirty, hasError) {\n super.setErrorClasses(elements, dirty, hasError);\n super.setErrorClasses([this.refs.day, this.refs.month, this.refs.year], dirty, hasError);\n }\n removeInputError(elements) {\n super.removeInputError([this.refs.day, this.refs.month, this.refs.year]);\n super.removeInputError(elements);\n }\n init() {\n super.init();\n const minYear = this.component.fields.year.minYear;\n const maxYear = this.component.fields.year.maxYear;\n this.component.maxYear = maxYear;\n this.component.minYear = minYear;\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.options.language);\n this.dayFirst = this.component.useLocaleSettings\n ? dateFormatInfo.dayFirst\n : this.component.dayFirst;\n }\n render() {\n if (this.isHtmlRenderMode()) {\n return super.render(this.renderTemplate('input'));\n }\n return super.render(this.renderTemplate('day', {\n dayFirst: this.dayFirst,\n showDay: this.showDay,\n showMonth: this.showMonth,\n showYear: this.showYear,\n day: this.renderField('day'),\n month: this.renderField('month'),\n year: this.renderField('year'),\n }));\n }\n renderField(name) {\n if (this.component.fields[name].type === 'select') {\n return this.renderTemplate('select', {\n input: this.selectDefinition(name),\n selectOptions: this[`${name}s`].reduce((html, option) => html + this.renderTemplate('selectOption', {\n option,\n selected: false,\n attrs: {}\n }), ''),\n });\n }\n else {\n return this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: this.inputDefinition(name)\n });\n }\n }\n attach(element) {\n this.loadRefs(element, { day: 'single', month: 'single', year: 'single', input: 'multiple' });\n const superAttach = super.attach(element);\n const updateValueAndSaveFocus = (element, name) => () => {\n try {\n this.saveCaretPosition(element, name);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n this.updateValue(null, {\n modified: true,\n });\n };\n if (this.shouldDisabled) {\n this.setDisabled(this.refs.day, true);\n this.setDisabled(this.refs.month, true);\n this.setDisabled(this.refs.year, true);\n if (this.refs.input) {\n this.refs.input.forEach((input) => this.setDisabled(input, true));\n }\n }\n else {\n this.addEventListener(this.refs.day, 'input', updateValueAndSaveFocus(this.refs.day, 'day'));\n // TODO: Need to rework this to work with day select as well.\n // Change day max input when month changes.\n this.addEventListener(this.refs.month, 'input', () => {\n const maxDay = this.refs.year ? parseInt(new Date(this.refs.year.value, this.refs.month.value, 0).getDate(), 10)\n : '';\n const day = this.getFieldValue('day');\n if (!this.component.fields.day.hide && maxDay) {\n this.refs.day.max = maxDay;\n }\n if (maxDay && day > maxDay) {\n this.refs.day.value = this.refs.day.max;\n }\n updateValueAndSaveFocus(this.refs.month, 'month')();\n });\n this.addEventListener(this.refs.year, 'input', updateValueAndSaveFocus(this.refs.year, 'year'));\n this.addEventListener(this.refs.input, this.info.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n [this.refs.day, this.refs.month, this.refs.year].filter((element) => !!element).forEach((element) => {\n super.addFocusBlurEvents(element);\n });\n }\n this.setValue(this.dataValue);\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n return superAttach;\n }\n validateRequired(setting, value) {\n const { day, month, year } = this.parts;\n if (this.dayRequired && !day) {\n return false;\n }\n if (this.monthRequired && !month) {\n return false;\n }\n if (this.yearRequired && !year) {\n return false;\n }\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n return !this.isEmpty(value);\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.refs.year || !this.refs.month || !this.refs.day) {\n return;\n }\n if (disabled) {\n this.refs.year.setAttribute('disabled', 'disabled');\n this.refs.month.setAttribute('disabled', 'disabled');\n this.refs.day.setAttribute('disabled', 'disabled');\n }\n else {\n this.refs.year.removeAttribute('disabled');\n this.refs.month.removeAttribute('disabled');\n this.refs.day.removeAttribute('disabled');\n }\n }\n normalizeValue(value) {\n if (!value || this.valueMask.test(value)) {\n return value;\n }\n const dateParts = [];\n const valueParts = value.split('/');\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = this.component.defaultValue ? this.component.defaultValue.split('/') : '';\n let defaultDay = '';\n let defaultMonth = '';\n let defaultYear = '';\n if (defaultValue) {\n const hasHiddenFields = defaultValue.length !== 3;\n defaultDay = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).day : defaultValue[DAY];\n defaultMonth = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).month : defaultValue[MONTH];\n defaultYear = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).year : defaultValue[YEAR];\n }\n if (this.options.building && defaultValue.length === 3) {\n return this.component.defaultValue;\n }\n const getNextPart = (shouldTake, defaultValue) => {\n // Only push the part if it's not an empty string\n const part = shouldTake ? valueParts.shift() : defaultValue;\n if (part !== '') {\n dateParts.push(part);\n }\n };\n if (this.dayFirst) {\n getNextPart(this.showDay, defaultDay);\n }\n getNextPart(this.showMonth, defaultMonth);\n if (!this.dayFirst) {\n getNextPart(this.showDay, defaultDay);\n }\n getNextPart(this.showYear, defaultYear);\n return dateParts.join('/');\n }\n /**\n * Set the value at a specific index and updates the component's refs.\n * @param {number} index - The index to set.\n * @param {any} value - The value to set.\n * @returns {null|void} - Returns null if the value is invalid, otherwise void.\n */\n setValueAt(index, value) {\n // temporary solution to avoid input reset\n // on invalid date.\n if (value === 'Invalid date') {\n return null;\n }\n let day, month, year;\n const parts = value.split('/');\n if (parts.length !== 3) {\n day = this.getDayWithHiddenFields(parts).day;\n month = this.getDayWithHiddenFields(parts).month;\n year = this.getDayWithHiddenFields(parts).year;\n }\n else {\n if (this.component.dayFirst) {\n day = parts.shift();\n }\n month = parts.shift();\n if (!this.component.dayFirst) {\n day = parts.shift();\n }\n year = parts.shift();\n }\n if (this.refs.day && this.showDay) {\n this.refs.day.value = day === '00' ? '' : parseInt(day, 10);\n }\n if (this.refs.month && this.showMonth) {\n this.refs.month.value = month === '00' ? '' : parseInt(month, 10);\n }\n if (this.refs.year && this.showYear) {\n this.refs.year.value = year === '0000' ? '' : parseInt(year, 10);\n }\n }\n getDayWithHiddenFields(parts) {\n let [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n if (!this.showDay) {\n MONTH = MONTH === 0 ? 0 : MONTH - 1;\n YEAR = YEAR - 1;\n DAY = null;\n }\n if (!this.showMonth) {\n DAY = DAY === 0 ? 0 : DAY - 1;\n YEAR = YEAR - 1;\n MONTH = null;\n }\n if (!this.showYear) {\n YEAR = null;\n }\n return {\n month: lodash_1.default.isNull(MONTH) ? '' : parts[MONTH],\n day: lodash_1.default.isNull(DAY) ? '' : parts[DAY],\n year: lodash_1.default.isNull(YEAR) ? '' : parts[YEAR],\n };\n }\n getFieldValue(name) {\n const parts = this.dataValue ? this.dataValue.split('/') : [];\n let val = 0;\n switch (name) {\n case 'month':\n val = parts[this.dayFirst ? 1 : 0];\n break;\n case 'day':\n val = parts[this.dayFirst ? 0 : 1];\n break;\n case 'year':\n val = parts[2];\n break;\n }\n val = parseInt(val, 10);\n return (!lodash_1.default.isNaN(val) && lodash_1.default.isNumber(val)) ? val : 0;\n }\n get parts() {\n return {\n day: this.getFieldValue('day'),\n month: this.getFieldValue('month'),\n year: this.getFieldValue('year'),\n };\n }\n /**\n * Get the format for the value string.\n * @returns {string} - the format for the value string.\n */\n get format() {\n let format = '';\n if (this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showMonth) {\n format += 'M/';\n }\n if (!this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showYear) {\n format += 'YYYY';\n return format;\n }\n else {\n // Trim off the \"/\" from the end of the format string.\n return format.length ? format.substring(0, format.length - 1) : format;\n }\n }\n /**\n * Return the date for this component.\n * @param {any} value - The value to convert to a date.\n * @returns {null|string} - The date string.\n */\n getDate(value) {\n let defaults = [], day, month, year;\n // Map positions to identifiers to get default values for each part of day\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = value || this.component.defaultValue;\n if (defaultValue) {\n defaults = defaultValue.split('/').map(x => parseInt(x, 10));\n }\n if (this.showDay && this.refs.day) {\n day = parseInt(this.refs.day.value, 10);\n }\n if (day === undefined || lodash_1.default.isNaN(day)) {\n day = defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0;\n }\n if (this.showMonth && this.refs.month) {\n // Months are 0 indexed.\n month = parseInt(this.refs.month.value, 10);\n }\n if (month === undefined || lodash_1.default.isNaN(month)) {\n month = defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;\n }\n if (this.showYear && this.refs.year) {\n year = parseInt(this.refs.year.value);\n }\n if (year === undefined || lodash_1.default.isNaN(year)) {\n year = defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;\n }\n let result;\n if (!day && !month && !year) {\n return null;\n }\n // add trailing zeros if the data is showed\n day = this.showDay ? day.toString().padStart(2, 0) : '';\n month = this.showMonth ? month.toString().padStart(2, 0) : '';\n year = this.showYear ? year.toString().padStart(4, 0) : '';\n if (this.component.dayFirst) {\n result = `${day}${this.showDay && this.showMonth || this.showDay && this.showYear ? '/' : ''}${month}${this.showMonth && this.showYear ? '/' : ''}${year}`;\n }\n else {\n result = `${month}${this.showDay && this.showMonth || this.showMonth && this.showYear ? '/' : ''}${day}${this.showDay && this.showYear ? '/' : ''}${year}`;\n }\n return result;\n }\n /**\n * Return the date string for this component.\n * @returns {string|null} - The date string for this component.\n */\n get date() {\n return this.getDate();\n }\n /**\n * Return the raw value.\n * @returns {string} - The raw value of the component.\n */\n get validationValue() {\n return this.dataValue;\n }\n getValue() {\n const result = super.getValue();\n return (!result) ? this.dataValue : result;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - The index to get the value from.\n * @returns {*} - The value at index.\n */\n getValueAt(index) {\n const date = this.date || this.emptyValue;\n if (date) {\n this.refs.input[index].value = date;\n return this.refs.input[index].value;\n }\n else {\n this.refs.input[index].value = '';\n return null;\n }\n }\n /**\n * Get the input value of the date.\n * @param {any} value - The value to convert to a string.\n * @returns {string|null} - The string value of the date.\n */\n getValueAsString(value) {\n return this.getDate(value) || '';\n }\n focus(field) {\n var _a, _b, _c;\n if (field && typeof field === 'string' && this.refs[field]) {\n this.refs[field].focus();\n }\n else if (this.dayFirst && this.showDay || !this.dayFirst && !this.showMonth && this.showDay) {\n (_a = this.refs.day) === null || _a === void 0 ? void 0 : _a.focus();\n }\n else if (this.dayFirst && !this.showDay && this.showMonth || !this.dayFirst && this.showMonth) {\n (_b = this.refs.month) === null || _b === void 0 ? void 0 : _b.focus();\n }\n else if (!this.showDay && !this.showDay && this.showYear) {\n (_c = this.refs.year) === null || _c === void 0 ? void 0 : _c.focus();\n }\n }\n restoreCaretPosition() {\n var _a;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n const { selection, index } = this.root.currentSelection;\n if (this.refs[index]) {\n const input = this.refs[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n }\n }\n isPartialDay(value) {\n if (!value) {\n return true;\n }\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/');\n if (values.length < 3) {\n return true;\n }\n return (values[DAY] === '00' || values[MONTH] === '00' || values[YEAR] === '0000');\n }\n getValidationFormat() {\n var _a, _b, _c, _d, _e, _f;\n let validationFormat = this.dayFirst ? 'DD-MM-YYYY' : 'MM-DD-YYYY';\n if ((_b = (_a = this.fields) === null || _a === void 0 ? void 0 : _a.day) === null || _b === void 0 ? void 0 : _b.hide) {\n validationFormat = validationFormat.replace('DD-', '');\n }\n if ((_d = (_c = this.fields) === null || _c === void 0 ? void 0 : _c.month) === null || _d === void 0 ? void 0 : _d.hide) {\n validationFormat = validationFormat.replace('MM-', '');\n }\n if ((_f = (_e = this.fields) === null || _e === void 0 ? void 0 : _e.year) === null || _f === void 0 ? void 0 : _f.hide) {\n validationFormat = validationFormat.replace('-YYYY', '');\n }\n return validationFormat;\n }\n}\nexports[\"default\"] = DayComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/day/Day.js?");
6208
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../_classes/field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass DayComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'day',\n label: 'Day',\n key: 'day',\n fields: {\n day: {\n type: 'number',\n placeholder: '',\n required: false\n },\n month: {\n type: 'select',\n placeholder: '',\n required: false\n },\n year: {\n type: 'number',\n placeholder: '',\n required: false\n }\n },\n dayFirst: false,\n defaultValue: ''\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Day',\n group: 'advanced',\n icon: 'calendar',\n documentation: '/userguide/form-building/advanced-components#day',\n weight: 50,\n schema: DayComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isDateEqual', 'isNotDateEqual', 'isEmpty', 'isNotEmpty', 'dateLessThan', 'dateGreaterThan', 'dateLessThanOrEqual', 'dateGreaterThanOrEqual'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.string];\n }\n constructor(component, options, data) {\n if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {\n component.maxDate = (0, moment_1.default)(component.maxDate, 'YYYY-MM-DD').toISOString();\n }\n if (component.minDate && component.minDate.indexOf('moment(') === -1) {\n component.minDate = (0, moment_1.default)(component.minDate, 'YYYY-MM-DD').toISOString();\n }\n super(component, options, data);\n }\n static get serverConditionSettings() {\n return DayComponent.conditionOperatorsSettings;\n }\n /**\n * The empty value for day component.\n * @returns {''} - The empty value of the day component.\n */\n get emptyValue() {\n return '';\n }\n get valueMask() {\n return /^\\d{2}\\/\\d{2}\\/\\d{4}$/;\n }\n get dayRequired() {\n return this.showDay && lodash_1.default.get(this.component, 'fields.day.required', false);\n }\n get showDay() {\n return !lodash_1.default.get(this.component, 'fields.day.hide', false);\n }\n get monthRequired() {\n return this.showMonth && lodash_1.default.get(this.component, 'fields.month.required', false);\n }\n get showMonth() {\n return !lodash_1.default.get(this.component, 'fields.month.hide', false);\n }\n get yearRequired() {\n return this.showYear && lodash_1.default.get(this.component, 'fields.year.required', false);\n }\n get showYear() {\n return !lodash_1.default.get(this.component, 'fields.year.hide', false);\n }\n get defaultSchema() {\n return DayComponent.schema();\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'input';\n info.attr.type = 'hidden';\n info.changeEvent = 'input';\n return info;\n }\n inputDefinition(name) {\n let min, max;\n if (name === 'day') {\n min = 1;\n max = 31;\n }\n if (name === 'month') {\n min = 1;\n max = 12;\n }\n if (name === 'year') {\n min = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n max = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 1900;\n }\n return {\n type: 'input',\n ref: name,\n attr: {\n id: `${this.component.key}-${name}`,\n class: `form-control ${this.transform('class', `formio-day-component-${name}`)}`,\n type: this.component.fields[name].type === 'select' ? 'select' : 'number',\n placeholder: this.t(this.component.fields[name].placeholder),\n step: 1,\n min,\n max,\n }\n };\n }\n selectDefinition(name) {\n return {\n multiple: false,\n ref: name,\n widget: 'html5',\n attr: {\n id: `${this.component.key}-${name}`,\n class: 'form-control',\n name,\n lang: this.options.language\n }\n };\n }\n get days() {\n if (this._days) {\n return this._days;\n }\n this._days = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.day.placeholder', '') }\n ];\n for (let x = 1; x <= 31; x++) {\n this._days.push({\n value: x,\n label: x.toString()\n });\n }\n return this._days;\n }\n get months() {\n if (this._months) {\n return this._months;\n }\n this._months = [\n {\n value: '',\n label: lodash_1.default.get(this.component, 'fields.month.placeholder') || (this.hideInputLabels ? this.t('Month') : '')\n },\n { value: 1, label: 'January' },\n { value: 2, label: 'February' },\n { value: 3, label: 'March' },\n { value: 4, label: 'April' },\n { value: 5, label: 'May' },\n { value: 6, label: 'June' },\n { value: 7, label: 'July' },\n { value: 8, label: 'August' },\n { value: 9, label: 'September' },\n { value: 10, label: 'October' },\n { value: 11, label: 'November' },\n { value: 12, label: 'December' }\n ];\n return this._months;\n }\n get years() {\n if (this._years) {\n return this._years;\n }\n this._years = [\n { value: '', label: lodash_1.default.get(this.component, 'fields.year.placeholder', '') }\n ];\n const minYears = lodash_1.default.get(this.component, 'fields.year.minYear', 1900) || 1900;\n const maxYears = lodash_1.default.get(this.component, 'fields.year.maxYear', 2030) || 2030;\n for (let x = minYears; x <= maxYears; x++) {\n this._years.push({\n value: x,\n label: x.toString()\n });\n }\n return this._years;\n }\n setErrorClasses(elements, dirty, hasError) {\n super.setErrorClasses(elements, dirty, hasError);\n super.setErrorClasses([this.refs.day, this.refs.month, this.refs.year], dirty, hasError);\n }\n removeInputError(elements) {\n super.removeInputError([this.refs.day, this.refs.month, this.refs.year]);\n super.removeInputError(elements);\n }\n init() {\n super.init();\n const minYear = this.component.fields.year.minYear;\n const maxYear = this.component.fields.year.maxYear;\n this.component.maxYear = maxYear;\n this.component.minYear = minYear;\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.options.language);\n this.dayFirst = this.component.useLocaleSettings\n ? dateFormatInfo.dayFirst\n : this.component.dayFirst;\n }\n render() {\n if (this.isHtmlRenderMode()) {\n return super.render(this.renderTemplate('input'));\n }\n return super.render(this.renderTemplate('day', {\n dayFirst: this.dayFirst,\n showDay: this.showDay,\n showMonth: this.showMonth,\n showYear: this.showYear,\n day: this.renderField('day'),\n month: this.renderField('month'),\n year: this.renderField('year'),\n }));\n }\n renderField(name) {\n if (this.component.fields[name].type === 'select') {\n return this.renderTemplate('select', {\n input: this.selectDefinition(name),\n selectOptions: this[`${name}s`].reduce((html, option) => html + this.renderTemplate('selectOption', {\n option,\n selected: false,\n attrs: {}\n }), ''),\n });\n }\n else {\n return this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: this.inputDefinition(name)\n });\n }\n }\n attach(element) {\n this.loadRefs(element, { day: 'single', month: 'single', year: 'single', input: 'multiple' });\n const superAttach = super.attach(element);\n const updateValueAndSaveFocus = (element, name) => () => {\n try {\n this.saveCaretPosition(element, name);\n }\n catch (err) {\n console.warn('An error occurred while trying to save caret position', err);\n }\n this.updateValue(null, {\n modified: true,\n });\n };\n if (this.shouldDisabled) {\n this.setDisabled(this.refs.day, true);\n this.setDisabled(this.refs.month, true);\n this.setDisabled(this.refs.year, true);\n if (this.refs.input) {\n this.refs.input.forEach((input) => this.setDisabled(input, true));\n }\n }\n else {\n this.addEventListener(this.refs.day, 'input', updateValueAndSaveFocus(this.refs.day, 'day'));\n // TODO: Need to rework this to work with day select as well.\n // Change day max input when month changes.\n this.addEventListener(this.refs.month, 'input', () => {\n const maxDay = this.refs.year ? parseInt(new Date(this.refs.year.value, this.refs.month.value, 0).getDate(), 10)\n : '';\n const day = this.getFieldValue('day');\n if (!this.component.fields.day.hide && maxDay) {\n this.refs.day.max = maxDay;\n }\n if (maxDay && day > maxDay) {\n this.refs.day.value = this.refs.day.max;\n }\n updateValueAndSaveFocus(this.refs.month, 'month')();\n });\n this.addEventListener(this.refs.year, 'input', updateValueAndSaveFocus(this.refs.year, 'year'));\n this.addEventListener(this.refs.input, this.info.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n [this.refs.day, this.refs.month, this.refs.year].filter((element) => !!element).forEach((element) => {\n super.addFocusBlurEvents(element);\n });\n }\n this.setValue(this.dataValue);\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n return superAttach;\n }\n validateRequired(setting, value) {\n const { day, month, year } = this.parts;\n if (this.dayRequired && !day) {\n return false;\n }\n if (this.monthRequired && !month) {\n return false;\n }\n if (this.yearRequired && !year) {\n return false;\n }\n if (!(0, utils_1.boolValue)(setting)) {\n return true;\n }\n return !this.isEmpty(value);\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.refs.year || !this.refs.month || !this.refs.day) {\n return;\n }\n if (disabled) {\n this.refs.year.setAttribute('disabled', 'disabled');\n this.refs.month.setAttribute('disabled', 'disabled');\n this.refs.day.setAttribute('disabled', 'disabled');\n }\n else {\n this.refs.year.removeAttribute('disabled');\n this.refs.month.removeAttribute('disabled');\n this.refs.day.removeAttribute('disabled');\n }\n }\n normalizeValue(value) {\n if (!value || this.valueMask.test(value)) {\n return value;\n }\n const dateParts = [];\n const valueParts = value.split('/');\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = this.component.defaultValue ? this.component.defaultValue.split('/') : '';\n let defaultDay = '';\n let defaultMonth = '';\n let defaultYear = '';\n if (defaultValue) {\n const hasHiddenFields = defaultValue.length !== 3;\n defaultDay = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).day : defaultValue[DAY];\n defaultMonth = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).month : defaultValue[MONTH];\n defaultYear = hasHiddenFields ? this.getDayWithHiddenFields(defaultValue).year : defaultValue[YEAR];\n }\n if (this.options.building && defaultValue.length === 3) {\n return this.component.defaultValue;\n }\n const getNextPart = (shouldTake, defaultValue) => {\n // Only push the part if it's not an empty string\n const part = shouldTake ? valueParts.shift() : defaultValue;\n if (part !== '') {\n dateParts.push(part);\n }\n };\n if (this.dayFirst) {\n getNextPart(this.showDay, defaultDay);\n }\n getNextPart(this.showMonth, defaultMonth);\n if (!this.dayFirst) {\n getNextPart(this.showDay, defaultDay);\n }\n getNextPart(this.showYear, defaultYear);\n return dateParts.join('/');\n }\n /**\n * Set the value at a specific index and updates the component's refs.\n * @param {number} index - The index to set.\n * @param {any} value - The value to set.\n * @returns {null|void} - Returns null if the value is invalid, otherwise void.\n */\n setValueAt(index, value) {\n // temporary solution to avoid input reset\n // on invalid date.\n if (value === 'Invalid date') {\n return null;\n }\n let day, month, year;\n const parts = value.split('/');\n if (parts.length !== 3) {\n day = this.getDayWithHiddenFields(parts).day;\n month = this.getDayWithHiddenFields(parts).month;\n year = this.getDayWithHiddenFields(parts).year;\n }\n else {\n if (this.component.dayFirst) {\n day = parts.shift();\n }\n month = parts.shift();\n if (!this.component.dayFirst) {\n day = parts.shift();\n }\n year = parts.shift();\n }\n if (this.refs.day && this.showDay) {\n this.refs.day.value = day === '00' ? '' : parseInt(day, 10);\n }\n if (this.refs.month && this.showMonth) {\n this.refs.month.value = month === '00' ? '' : parseInt(month, 10);\n }\n if (this.refs.year && this.showYear) {\n this.refs.year.value = year === '0000' ? '' : parseInt(year, 10);\n }\n }\n getDayWithHiddenFields(parts) {\n let [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n if (!this.showDay) {\n MONTH = MONTH === 0 ? 0 : MONTH - 1;\n YEAR = YEAR - 1;\n DAY = null;\n }\n if (!this.showMonth) {\n if (!lodash_1.default.isNull(DAY)) {\n DAY = DAY === 0 ? 0 : DAY - 1;\n }\n YEAR = YEAR - 1;\n MONTH = null;\n }\n if (!this.showYear) {\n YEAR = null;\n }\n return {\n month: lodash_1.default.isNull(MONTH) ? '' : parts[MONTH],\n day: lodash_1.default.isNull(DAY) ? '' : parts[DAY],\n year: lodash_1.default.isNull(YEAR) ? '' : parts[YEAR],\n };\n }\n getFieldValue(name) {\n const parts = this.dataValue ? this.dataValue.split('/') : [];\n let val = 0;\n switch (name) {\n case 'month':\n val = parts[this.dayFirst ? 1 : 0];\n break;\n case 'day':\n val = parts[this.dayFirst ? 0 : 1];\n break;\n case 'year':\n val = parts[2];\n break;\n }\n val = parseInt(val, 10);\n return (!lodash_1.default.isNaN(val) && lodash_1.default.isNumber(val)) ? val : 0;\n }\n get parts() {\n return {\n day: this.getFieldValue('day'),\n month: this.getFieldValue('month'),\n year: this.getFieldValue('year'),\n };\n }\n /**\n * Get the format for the value string.\n * @returns {string} - the format for the value string.\n */\n get format() {\n let format = '';\n if (this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showMonth) {\n format += 'M/';\n }\n if (!this.component.dayFirst && this.showDay) {\n format += 'D/';\n }\n if (this.showYear) {\n format += 'YYYY';\n return format;\n }\n else {\n // Trim off the \"/\" from the end of the format string.\n return format.length ? format.substring(0, format.length - 1) : format;\n }\n }\n /**\n * Return the date for this component.\n * @param {any} value - The value to convert to a date.\n * @returns {null|string} - The date string.\n */\n getDate(value) {\n let defaults = [], day, month, year;\n // Map positions to identifiers to get default values for each part of day\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const defaultValue = value || this.component.defaultValue;\n if (defaultValue) {\n defaults = defaultValue.split('/').map(x => parseInt(x, 10));\n }\n if (this.showDay && this.refs.day) {\n day = parseInt(this.refs.day.value, 10);\n }\n if (day === undefined || lodash_1.default.isNaN(day)) {\n day = defaults[DAY] && !lodash_1.default.isNaN(defaults[DAY]) ? defaults[DAY] : 0;\n }\n if (this.showMonth && this.refs.month) {\n // Months are 0 indexed.\n month = parseInt(this.refs.month.value, 10);\n }\n if (month === undefined || lodash_1.default.isNaN(month)) {\n month = defaults[MONTH] && !lodash_1.default.isNaN(defaults[MONTH]) ? defaults[MONTH] : 0;\n }\n if (this.showYear && this.refs.year) {\n year = parseInt(this.refs.year.value);\n }\n if (year === undefined || lodash_1.default.isNaN(year)) {\n year = defaults[YEAR] && !lodash_1.default.isNaN(defaults[YEAR]) ? defaults[YEAR] : 0;\n }\n let result;\n if (!day && !month && !year) {\n return null;\n }\n // add trailing zeros if the data is showed\n day = this.showDay ? day.toString().padStart(2, 0) : '';\n month = this.showMonth ? month.toString().padStart(2, 0) : '';\n year = this.showYear ? year.toString().padStart(4, 0) : '';\n if (this.component.dayFirst) {\n result = `${day}${this.showDay && this.showMonth || this.showDay && this.showYear ? '/' : ''}${month}${this.showMonth && this.showYear ? '/' : ''}${year}`;\n }\n else {\n result = `${month}${this.showDay && this.showMonth || this.showMonth && this.showYear ? '/' : ''}${day}${this.showDay && this.showYear ? '/' : ''}${year}`;\n }\n return result;\n }\n /**\n * Return the date string for this component.\n * @returns {string|null} - The date string for this component.\n */\n get date() {\n return this.getDate();\n }\n /**\n * Return the raw value.\n * @returns {string} - The raw value of the component.\n */\n get validationValue() {\n return this.dataValue;\n }\n getValue() {\n const result = super.getValue();\n return (!result) ? this.dataValue : result;\n }\n /**\n * Get the value at a specific index.\n * @param {number} index - The index to get the value from.\n * @returns {*} - The value at index.\n */\n getValueAt(index) {\n const date = this.date || this.emptyValue;\n if (date) {\n this.refs.input[index].value = date;\n return this.refs.input[index].value;\n }\n else {\n this.refs.input[index].value = '';\n return null;\n }\n }\n /**\n * Get the input value of the date.\n * @param {any} value - The value to convert to a string.\n * @returns {string|null} - The string value of the date.\n */\n getValueAsString(value) {\n return this.getDate(value) || '';\n }\n focus(field) {\n var _a, _b, _c;\n if (field && typeof field === 'string' && this.refs[field]) {\n this.refs[field].focus();\n }\n else if (this.dayFirst && this.showDay || !this.dayFirst && !this.showMonth && this.showDay) {\n (_a = this.refs.day) === null || _a === void 0 ? void 0 : _a.focus();\n }\n else if (this.dayFirst && !this.showDay && this.showMonth || !this.dayFirst && this.showMonth) {\n (_b = this.refs.month) === null || _b === void 0 ? void 0 : _b.focus();\n }\n else if (!this.showDay && !this.showDay && this.showYear) {\n (_c = this.refs.year) === null || _c === void 0 ? void 0 : _c.focus();\n }\n }\n restoreCaretPosition() {\n var _a;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n const { selection, index } = this.root.currentSelection;\n if (this.refs[index]) {\n const input = this.refs[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n }\n }\n isPartialDay(value) {\n if (!value) {\n return true;\n }\n const [DAY, MONTH, YEAR] = this.component.dayFirst ? [0, 1, 2] : [1, 0, 2];\n const values = value.split('/');\n if (values.length < 3) {\n return true;\n }\n return (values[DAY] === '00' || values[MONTH] === '00' || values[YEAR] === '0000');\n }\n getValidationFormat() {\n var _a, _b, _c, _d, _e, _f;\n let validationFormat = this.dayFirst ? 'DD-MM-YYYY' : 'MM-DD-YYYY';\n if ((_b = (_a = this.fields) === null || _a === void 0 ? void 0 : _a.day) === null || _b === void 0 ? void 0 : _b.hide) {\n validationFormat = validationFormat.replace('DD-', '');\n }\n if ((_d = (_c = this.fields) === null || _c === void 0 ? void 0 : _c.month) === null || _d === void 0 ? void 0 : _d.hide) {\n validationFormat = validationFormat.replace('MM-', '');\n }\n if ((_f = (_e = this.fields) === null || _e === void 0 ? void 0 : _e.year) === null || _f === void 0 ? void 0 : _f.hide) {\n validationFormat = validationFormat.replace('-YYYY', '');\n }\n return validationFormat;\n }\n}\nexports[\"default\"] = DayComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/day/Day.js?");
6209
6209
 
6210
6210
  /***/ }),
6211
6211
 
@@ -10843,7 +10843,7 @@ eval("\nvar parent = __webpack_require__(/*! ../../es/object/from-entries */ \".
10843
10843
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
10844
10844
 
10845
10845
  "use strict";
10846
- eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nvar _a;\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.FormBuilder = exports.Form = exports.Formio = void 0;\nconst CDN_js_1 = __importDefault(__webpack_require__(/*! ./CDN.js */ \"./lib/cjs/CDN.js\"));\nclass Formio {\n static setLicense(license, norecurse = false) {\n _a.license = license;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setLicense(license);\n }\n }\n static setBaseUrl(url, norecurse = false) {\n _a.baseUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setBaseUrl(url);\n }\n }\n static setApiUrl(url, norecurse = false) {\n _a.baseUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setApiUrl(url);\n }\n }\n static setProjectUrl(url, norecurse = false) {\n _a.projectUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setProjectUrl(url);\n }\n }\n static setAppUrl(url, norecurse = false) {\n _a.projectUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setAppUrl(url);\n }\n }\n static setPathType(type, norecurse = false) {\n _a.pathType = type;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setPathType(type);\n }\n }\n static debug(...args) {\n if (_a.config.debug) {\n console.log(...args);\n }\n }\n static clearCache() {\n if (_a.FormioClass) {\n _a.FormioClass.clearCache();\n }\n }\n static global(prop, flag = '') {\n const globalValue = window[prop];\n if (flag && globalValue && !globalValue[flag]) {\n return null;\n }\n _a.debug(`Getting global ${prop}`, globalValue);\n return globalValue;\n }\n static use(module) {\n if (_a.FormioClass && _a.FormioClass.isRenderer) {\n _a.FormioClass.use(module);\n }\n else {\n _a.modules.push(module);\n }\n }\n static createElement(type, attrs, children) {\n const element = document.createElement(type);\n if (!attrs) {\n return element;\n }\n Object.keys(attrs).forEach(key => {\n element.setAttribute(key, attrs[key]);\n });\n (children || []).forEach(child => {\n element.appendChild(_a.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n static addScript(wrapper, src, name, flag = '') {\n return __awaiter(this, void 0, void 0, function* () {\n if (!src) {\n return Promise.resolve();\n }\n if (typeof src !== 'string' && src.length) {\n return Promise.all(src.map(ref => _a.addScript(wrapper, ref)));\n }\n if (name && _a.global(name, flag)) {\n _a.debug(`${name} already loaded.`);\n return Promise.resolve(_a.global(name));\n }\n _a.debug('Adding Script', src);\n try {\n wrapper.appendChild(_a.createElement('script', {\n src\n }));\n }\n catch (err) {\n _a.debug(err);\n return Promise.resolve();\n }\n if (!name) {\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n _a.debug(`Waiting to load ${name}`);\n const wait = setInterval(() => {\n if (_a.global(name, flag)) {\n clearInterval(wait);\n _a.debug(`${name} loaded.`);\n resolve(_a.global(name));\n }\n }, 100);\n });\n });\n }\n static addStyles(wrapper, href) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!href) {\n return;\n }\n if (typeof href !== 'string' && href.length) {\n href.forEach(ref => _a.addStyles(wrapper, ref));\n return;\n }\n _a.debug('Adding Styles', href);\n wrapper.appendChild(_a.createElement('link', {\n rel: 'stylesheet',\n href\n }));\n });\n }\n static submitDone(instance, submission) {\n return __awaiter(this, void 0, void 0, function* () {\n _a.debug('Submision Complete', submission);\n if (_a.config.submitDone) {\n _a.config.submitDone(submission, instance);\n }\n const successMessage = (_a.config.success || '').toString();\n if (successMessage && successMessage.toLowerCase() !== 'false' && instance.element) {\n instance.element.innerHTML = `<div class=\"alert-success\" role=\"alert\">${successMessage}</div>`;\n }\n let returnUrl = _a.config.redirect;\n // Allow form based configuration for return url.\n if (!returnUrl &&\n (instance._form &&\n instance._form.settings &&\n (instance._form.settings.returnUrl ||\n instance._form.settings.redirect))) {\n _a.debug('Return url found in form configuration');\n returnUrl = instance._form.settings.returnUrl || instance._form.settings.redirect;\n }\n if (returnUrl) {\n const formSrc = instance.formio ? instance.formio.formUrl : '';\n const hasQuery = !!returnUrl.match(/\\?/);\n const isOrigin = returnUrl.indexOf(location.origin) === 0;\n returnUrl += hasQuery ? '&' : '?';\n returnUrl += `sub=${submission._id}`;\n if (!isOrigin && formSrc) {\n returnUrl += `&form=${encodeURIComponent(formSrc)}`;\n }\n _a.debug('Return URL', returnUrl);\n window.location.href = returnUrl;\n if (isOrigin) {\n window.location.reload();\n }\n }\n });\n }\n // Return the full script if the builder is being used.\n static formioScript(script, builder) {\n builder = builder || _a.config.includeBuilder;\n if (_a.fullAdded || builder) {\n _a.fullAdded = true;\n return script.replace('formio.form', 'formio.full');\n }\n return script;\n }\n static addLibrary(libWrapper, lib, name) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!lib) {\n return;\n }\n if (lib.dependencies) {\n for (let i = 0; i < lib.dependencies.length; i++) {\n const libName = lib.dependencies[i];\n yield _a.addLibrary(libWrapper, _a.config.libs[libName], libName);\n }\n }\n if (lib.css) {\n yield _a.addStyles((lib.global ? document.body : libWrapper), lib.css);\n }\n if (lib.js) {\n const module = yield _a.addScript((lib.global ? document.body : libWrapper), lib.js, lib.use ? name : false);\n if (lib.use) {\n _a.debug(`Using ${name}`);\n const options = lib.options || {};\n if (!options.license && _a.license) {\n options.license = _a.license;\n }\n _a.use((typeof lib.use === 'function' ? lib.use(module) : module), options);\n }\n }\n if (lib.globalStyle) {\n const style = _a.createElement('style');\n style.type = 'text/css';\n style.innerHTML = lib.globalStyle;\n document.body.appendChild(style);\n }\n });\n }\n static addLoader(wrapper) {\n return __awaiter(this, void 0, void 0, function* () {\n wrapper.appendChild(_a.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 });\n }\n // eslint-disable-next-line max-statements\n static init(element, options = {}, builder = false) {\n return __awaiter(this, void 0, void 0, function* () {\n _a.cdn = new CDN_js_1.default(_a.config.cdn, _a.config.cdnUrls || {});\n _a.config.libs = _a.config.libs || {\n uswds: {\n dependencies: ['fontawesome'],\n js: `${_a.cdn.uswds}/uswds.min.js`,\n css: `${_a.cdn.uswds}/uswds.min.css`,\n use: true\n },\n fontawesome: {\n // Due to an issue with font-face not loading in the shadowdom (https://issues.chromium.org/issues/41085401), we need\n // to do 2 things. 1.) Load the fonts from the global cdn, and 2.) add the font-face to the global styles on the page.\n css: `https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css`,\n globalStyle: `@font-face {\n font-family: 'FontAwesome';\n src: url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.eot?v=4.7.0');\n src: url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');\n font-weight: normal;\n font-style: normal;\n }`\n },\n bootstrap4: {\n dependencies: ['fontawesome'],\n css: `${_a.cdn.bootstrap4}/css/bootstrap.min.css`\n },\n bootstrap: {\n dependencies: ['bootstrap-icons'],\n css: `${_a.cdn.bootstrap}/css/bootstrap.min.css`\n },\n 'bootstrap-icons': {\n // Due to an issue with font-face not loading in the shadowdom (https://issues.chromium.org/issues/41085401), we need\n // to do 2 things. 1.) Load the fonts from the global cdn, and 2.) add the font-face to the global styles on the page.\n css: 'https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.min.css',\n globalStyle: `@font-face {\n font-display: block;\n font-family: \"bootstrap-icons\";\n src: url(\"https://cdn.jsdelivr.net/npm/bootstrap-icons/font/fonts/bootstrap-icons.woff2?dd67030699838ea613ee6dbda90effa6\") format(\"woff2\"),\n url(\"https://cdn.jsdelivr.net/npm/bootstrap-icons/font/fonts/bootstrap-icons.woff?dd67030699838ea613ee6dbda90effa6\") format(\"woff\");\n }`\n }\n };\n // Add all bootswatch templates.\n ['cerulean', 'cosmo', 'cyborg', 'darkly', 'flatly', 'journal', 'litera', 'lumen', 'lux', 'materia', 'minty', 'pulse', 'sandstone', 'simplex', 'sketchy', 'slate', 'solar', 'spacelab', 'superhero', 'united', 'yeti'].forEach((template) => {\n _a.config.libs[template] = {\n dependencies: ['bootstrap-icons'],\n css: `${_a.cdn.bootswatch}/dist/${template}/bootstrap.min.css`\n };\n });\n const id = _a.config.id || `formio-${Math.random().toString(36).substring(7)}`;\n // Create a new wrapper and add the element inside of a new wrapper.\n let wrapper = _a.createElement('div', {\n 'id': `${id}-wrapper`\n });\n element.parentNode.insertBefore(wrapper, element);\n // If we include the libraries, then we will attempt to run this in shadow dom.\n const useShadowDom = _a.config.includeLibs && !_a.config.noshadow && (typeof wrapper.attachShadow === 'function');\n if (useShadowDom) {\n wrapper = wrapper.attachShadow({\n mode: 'open'\n });\n options.shadowRoot = wrapper;\n }\n element.parentNode.removeChild(element);\n wrapper.appendChild(element);\n // If this is inside of shadow dom, then we need to add the styles and scripts to the shadow dom.\n const libWrapper = useShadowDom ? wrapper : document.body;\n // Load the renderer styles.\n yield _a.addStyles(libWrapper, _a.config.embedCSS || `${_a.cdn.js}/formio.embed.css`);\n // Add a loader.\n _a.addLoader(wrapper);\n const formioSrc = _a.config.full ? 'formio.full' : 'formio.form';\n const renderer = _a.config.debug ? formioSrc : `${formioSrc}.min`;\n _a.FormioClass = yield _a.addScript(libWrapper, _a.formioScript(_a.config.script || `${_a.cdn.js}/${renderer}.js`, builder), 'Formio', builder ? 'isBuilder' : 'isRenderer');\n _a.FormioClass.cdn = _a.cdn;\n _a.FormioClass.setBaseUrl(options.baseUrl || _a.baseUrl || _a.config.base);\n _a.FormioClass.setProjectUrl(options.projectUrl || _a.projectUrl || _a.config.project);\n _a.FormioClass.language = _a.language;\n _a.setLicense(_a.license || _a.config.license || false);\n _a.modules.forEach((module) => {\n _a.FormioClass.use(module);\n });\n if (_a.icons) {\n _a.FormioClass.icons = _a.icons;\n }\n if (_a.pathType) {\n _a.FormioClass.setPathType(_a.pathType);\n }\n // Add libraries if they wish to include the libs.\n if (_a.config.template && _a.config.includeLibs) {\n yield _a.addLibrary(libWrapper, _a.config.libs[_a.config.template], _a.config.template);\n }\n if (!_a.config.libraries) {\n _a.config.libraries = _a.config.modules || {};\n }\n // Adding premium if it is provided via the config.\n if (_a.config.premium) {\n _a.config.libraries.premium = _a.config.premium;\n }\n // Allow adding dynamic modules.\n if (_a.config.libraries) {\n for (const name in _a.config.libraries) {\n const lib = _a.config.libraries[name];\n lib.use = lib.use || true;\n yield _a.addLibrary(libWrapper, lib, name);\n }\n }\n yield _a.addStyles(libWrapper, _a.formioScript(_a.config.style || `${_a.cdn.js}/${renderer}.css`, builder));\n if (_a.config.before) {\n yield _a.config.before(_a.FormioClass, element, _a.config);\n }\n _a.FormioClass.license = true;\n _a._formioReady(_a.FormioClass);\n return wrapper;\n });\n }\n // Called after an instance has been created.\n static afterCreate(instance, wrapper, readyEvent) {\n return __awaiter(this, void 0, void 0, function* () {\n const loader = wrapper.querySelector('.formio-loader');\n if (loader) {\n wrapper.removeChild(loader);\n }\n _a.FormioClass.events.emit(readyEvent, instance);\n if (_a.config.after) {\n _a.debug('Calling ready callback');\n _a.config.after(instance, _a.config);\n }\n return instance;\n });\n }\n // Create a new form.\n static createForm(element, form, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n if (_a.FormioClass) {\n return _a.FormioClass.createForm(element, form, Object.assign(Object.assign({}, options), { noLoader: true }));\n }\n const wrapper = yield _a.init(element, options);\n return _a.FormioClass.createForm(element, form, Object.assign(Object.assign({}, options), { noLoader: true })).then((instance) => {\n // Set the default submission data.\n if (_a.config.submission) {\n _a.debug('Setting submission', _a.config.submission);\n instance.submission = _a.config.submission;\n }\n // Call the after create method.\n _a.afterCreate(instance, wrapper, 'formEmbedded');\n return instance;\n });\n });\n }\n // Create a form builder.\n static builder(element, form, options = {}) {\n var _b;\n return __awaiter(this, void 0, void 0, function* () {\n if ((_b = _a.FormioClass) === null || _b === void 0 ? void 0 : _b.builder) {\n return _a.FormioClass.builder(element, form, options);\n }\n const wrapper = yield _a.init(element, options, true);\n return _a.FormioClass.builder(element, form, options).then((instance) => {\n _a.afterCreate(instance, wrapper, 'builderEmbedded');\n return instance;\n });\n });\n }\n}\nexports.Formio = Formio;\n_a = Formio;\nFormio.FormioClass = null;\nFormio.config = {};\nFormio.modules = [];\nFormio.icons = '';\nFormio.license = '';\nFormio.formioReady = new Promise((ready, reject) => {\n _a._formioReady = ready;\n _a._formioReadyReject = reject;\n});\nFormio.version = '5.0.0-rc.82';\n// Create a report.\nFormio.Report = {\n create: (element, submission, options = {}) => __awaiter(void 0, void 0, void 0, function* () {\n var _b;\n if ((_b = _a.FormioClass) === null || _b === void 0 ? void 0 : _b.Report) {\n return _a.FormioClass.Report.create(element, submission, options);\n }\n const wrapper = yield _a.init(element, options, true);\n return _a.FormioClass.Report.create(element, submission, options).then((instance) => {\n _a.afterCreate(instance, wrapper, 'reportEmbedded');\n return instance;\n });\n })\n};\nCDN_js_1.default.defaultCDN = Formio.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';\nclass Form {\n constructor(element, form, options) {\n this.form = form;\n this.element = element;\n this.options = options || {};\n this.init();\n this.instance = {\n proxy: true,\n ready: this.ready,\n destroy: () => { }\n };\n }\n init() {\n if (this.instance && !this.instance.proxy) {\n this.instance.destroy();\n }\n this.element.innerHTML = '';\n this.ready = this.create().then((instance) => {\n this.instance = instance;\n this.form = instance.form;\n return instance;\n });\n }\n create() {\n return Formio.createForm(this.element, this.form, this.options);\n }\n setForm(form) {\n this.form = form;\n if (this.instance) {\n this.instance.setForm(form);\n }\n }\n setDisplay(display) {\n if (this.instance.proxy) {\n return this.ready;\n }\n this.form.display = display;\n this.instance.destroy();\n this.ready = this.create().then((instance) => {\n this.instance = instance;\n this.setForm(this.form);\n });\n return this.ready;\n }\n}\nexports.Form = Form;\nclass FormBuilder extends Form {\n create() {\n return Formio.builder(this.element, this.form, this.options);\n }\n}\nexports.FormBuilder = FormBuilder;\nFormio.Form = Form;\nFormio.FormBuilder = FormBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Embed.js?");
10846
+ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nvar _a;\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.FormBuilder = exports.Form = exports.Formio = void 0;\nconst CDN_js_1 = __importDefault(__webpack_require__(/*! ./CDN.js */ \"./lib/cjs/CDN.js\"));\nclass Formio {\n static setLicense(license, norecurse = false) {\n _a.license = license;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setLicense(license);\n }\n }\n static setBaseUrl(url, norecurse = false) {\n _a.baseUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setBaseUrl(url);\n }\n }\n static setApiUrl(url, norecurse = false) {\n _a.baseUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setApiUrl(url);\n }\n }\n static setProjectUrl(url, norecurse = false) {\n _a.projectUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setProjectUrl(url);\n }\n }\n static setAppUrl(url, norecurse = false) {\n _a.projectUrl = url;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setAppUrl(url);\n }\n }\n static setPathType(type, norecurse = false) {\n _a.pathType = type;\n if (!norecurse && _a.FormioClass) {\n _a.FormioClass.setPathType(type);\n }\n }\n static debug(...args) {\n if (_a.config.debug) {\n console.log(...args);\n }\n }\n static clearCache() {\n if (_a.FormioClass) {\n _a.FormioClass.clearCache();\n }\n }\n static global(prop, flag = '') {\n const globalValue = window[prop];\n if (flag && globalValue && !globalValue[flag]) {\n return null;\n }\n _a.debug(`Getting global ${prop}`, globalValue);\n return globalValue;\n }\n static use(module) {\n if (_a.FormioClass && _a.FormioClass.isRenderer) {\n _a.FormioClass.use(module);\n }\n else {\n _a.modules.push(module);\n }\n }\n static createElement(type, attrs, children) {\n const element = document.createElement(type);\n if (!attrs) {\n return element;\n }\n Object.keys(attrs).forEach(key => {\n element.setAttribute(key, attrs[key]);\n });\n (children || []).forEach(child => {\n element.appendChild(_a.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n static addScript(wrapper, src, name, flag = '') {\n return __awaiter(this, void 0, void 0, function* () {\n if (!src) {\n return Promise.resolve();\n }\n if (typeof src !== 'string' && src.length) {\n return Promise.all(src.map(ref => _a.addScript(wrapper, ref)));\n }\n if (name && _a.global(name, flag)) {\n _a.debug(`${name} already loaded.`);\n return Promise.resolve(_a.global(name));\n }\n _a.debug('Adding Script', src);\n try {\n wrapper.appendChild(_a.createElement('script', {\n src\n }));\n }\n catch (err) {\n _a.debug(err);\n return Promise.resolve();\n }\n if (!name) {\n return Promise.resolve();\n }\n return new Promise((resolve) => {\n _a.debug(`Waiting to load ${name}`);\n const wait = setInterval(() => {\n if (_a.global(name, flag)) {\n clearInterval(wait);\n _a.debug(`${name} loaded.`);\n resolve(_a.global(name));\n }\n }, 100);\n });\n });\n }\n static addStyles(wrapper, href) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!href) {\n return;\n }\n if (typeof href !== 'string' && href.length) {\n href.forEach(ref => _a.addStyles(wrapper, ref));\n return;\n }\n _a.debug('Adding Styles', href);\n wrapper.appendChild(_a.createElement('link', {\n rel: 'stylesheet',\n href\n }));\n });\n }\n static submitDone(instance, submission) {\n return __awaiter(this, void 0, void 0, function* () {\n _a.debug('Submision Complete', submission);\n if (_a.config.submitDone) {\n _a.config.submitDone(submission, instance);\n }\n const successMessage = (_a.config.success || '').toString();\n if (successMessage && successMessage.toLowerCase() !== 'false' && instance.element) {\n instance.element.innerHTML = `<div class=\"alert-success\" role=\"alert\">${successMessage}</div>`;\n }\n let returnUrl = _a.config.redirect;\n // Allow form based configuration for return url.\n if (!returnUrl &&\n (instance._form &&\n instance._form.settings &&\n (instance._form.settings.returnUrl ||\n instance._form.settings.redirect))) {\n _a.debug('Return url found in form configuration');\n returnUrl = instance._form.settings.returnUrl || instance._form.settings.redirect;\n }\n if (returnUrl) {\n const formSrc = instance.formio ? instance.formio.formUrl : '';\n const hasQuery = !!returnUrl.match(/\\?/);\n const isOrigin = returnUrl.indexOf(location.origin) === 0;\n returnUrl += hasQuery ? '&' : '?';\n returnUrl += `sub=${submission._id}`;\n if (!isOrigin && formSrc) {\n returnUrl += `&form=${encodeURIComponent(formSrc)}`;\n }\n _a.debug('Return URL', returnUrl);\n window.location.href = returnUrl;\n if (isOrigin) {\n window.location.reload();\n }\n }\n });\n }\n // Return the full script if the builder is being used.\n static formioScript(script, builder) {\n builder = builder || _a.config.includeBuilder;\n if (_a.fullAdded || builder) {\n _a.fullAdded = true;\n return script.replace('formio.form', 'formio.full');\n }\n return script;\n }\n static addLibrary(libWrapper, lib, name) {\n return __awaiter(this, void 0, void 0, function* () {\n if (!lib) {\n return;\n }\n if (lib.dependencies) {\n for (let i = 0; i < lib.dependencies.length; i++) {\n const libName = lib.dependencies[i];\n yield _a.addLibrary(libWrapper, _a.config.libs[libName], libName);\n }\n }\n if (lib.css) {\n yield _a.addStyles((lib.global ? document.body : libWrapper), lib.css);\n }\n if (lib.js) {\n const module = yield _a.addScript((lib.global ? document.body : libWrapper), lib.js, lib.use ? name : false);\n if (lib.use) {\n _a.debug(`Using ${name}`);\n const options = lib.options || {};\n if (!options.license && _a.license) {\n options.license = _a.license;\n }\n _a.use((typeof lib.use === 'function' ? lib.use(module) : module), options);\n }\n }\n if (lib.globalStyle) {\n const style = _a.createElement('style');\n style.type = 'text/css';\n style.innerHTML = lib.globalStyle;\n document.body.appendChild(style);\n }\n });\n }\n static addLoader(wrapper) {\n return __awaiter(this, void 0, void 0, function* () {\n wrapper.appendChild(_a.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 });\n }\n // eslint-disable-next-line max-statements\n static init(element, options = {}, builder = false) {\n return __awaiter(this, void 0, void 0, function* () {\n _a.cdn = new CDN_js_1.default(_a.config.cdn, _a.config.cdnUrls || {});\n _a.config.libs = _a.config.libs || {\n uswds: {\n dependencies: ['fontawesome'],\n js: `${_a.cdn.uswds}/uswds.min.js`,\n css: `${_a.cdn.uswds}/uswds.min.css`,\n use: true\n },\n fontawesome: {\n // Due to an issue with font-face not loading in the shadowdom (https://issues.chromium.org/issues/41085401), we need\n // to do 2 things. 1.) Load the fonts from the global cdn, and 2.) add the font-face to the global styles on the page.\n css: `https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css`,\n globalStyle: `@font-face {\n font-family: 'FontAwesome';\n src: url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.eot?v=4.7.0');\n src: url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');\n font-weight: normal;\n font-style: normal;\n }`\n },\n bootstrap4: {\n dependencies: ['fontawesome'],\n css: `${_a.cdn.bootstrap4}/css/bootstrap.min.css`\n },\n bootstrap: {\n dependencies: ['bootstrap-icons'],\n css: `${_a.cdn.bootstrap}/css/bootstrap.min.css`\n },\n 'bootstrap-icons': {\n // Due to an issue with font-face not loading in the shadowdom (https://issues.chromium.org/issues/41085401), we need\n // to do 2 things. 1.) Load the fonts from the global cdn, and 2.) add the font-face to the global styles on the page.\n css: 'https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.min.css',\n globalStyle: `@font-face {\n font-display: block;\n font-family: \"bootstrap-icons\";\n src: url(\"https://cdn.jsdelivr.net/npm/bootstrap-icons/font/fonts/bootstrap-icons.woff2?dd67030699838ea613ee6dbda90effa6\") format(\"woff2\"),\n url(\"https://cdn.jsdelivr.net/npm/bootstrap-icons/font/fonts/bootstrap-icons.woff?dd67030699838ea613ee6dbda90effa6\") format(\"woff\");\n }`\n }\n };\n // Add all bootswatch templates.\n ['cerulean', 'cosmo', 'cyborg', 'darkly', 'flatly', 'journal', 'litera', 'lumen', 'lux', 'materia', 'minty', 'pulse', 'sandstone', 'simplex', 'sketchy', 'slate', 'solar', 'spacelab', 'superhero', 'united', 'yeti'].forEach((template) => {\n _a.config.libs[template] = {\n dependencies: ['bootstrap-icons'],\n css: `${_a.cdn.bootswatch}/dist/${template}/bootstrap.min.css`\n };\n });\n const id = _a.config.id || `formio-${Math.random().toString(36).substring(7)}`;\n // Create a new wrapper and add the element inside of a new wrapper.\n let wrapper = _a.createElement('div', {\n 'id': `${id}-wrapper`\n });\n element.parentNode.insertBefore(wrapper, element);\n // If we include the libraries, then we will attempt to run this in shadow dom.\n const useShadowDom = _a.config.includeLibs && !_a.config.noshadow && (typeof wrapper.attachShadow === 'function');\n if (useShadowDom) {\n wrapper = wrapper.attachShadow({\n mode: 'open'\n });\n options.shadowRoot = wrapper;\n }\n element.parentNode.removeChild(element);\n wrapper.appendChild(element);\n // If this is inside of shadow dom, then we need to add the styles and scripts to the shadow dom.\n const libWrapper = useShadowDom ? wrapper : document.body;\n // Load the renderer styles.\n yield _a.addStyles(libWrapper, _a.config.embedCSS || `${_a.cdn.js}/formio.embed.css`);\n // Add a loader.\n _a.addLoader(wrapper);\n const formioSrc = _a.config.full ? 'formio.full' : 'formio.form';\n const renderer = _a.config.debug ? formioSrc : `${formioSrc}.min`;\n _a.FormioClass = yield _a.addScript(libWrapper, _a.formioScript(_a.config.script || `${_a.cdn.js}/${renderer}.js`, builder), 'Formio', builder ? 'isBuilder' : 'isRenderer');\n _a.FormioClass.cdn = _a.cdn;\n _a.FormioClass.setBaseUrl(options.baseUrl || _a.baseUrl || _a.config.base);\n _a.FormioClass.setProjectUrl(options.projectUrl || _a.projectUrl || _a.config.project);\n _a.FormioClass.language = _a.language;\n _a.setLicense(_a.license || _a.config.license || false);\n _a.modules.forEach((module) => {\n _a.FormioClass.use(module);\n });\n if (_a.icons) {\n _a.FormioClass.icons = _a.icons;\n }\n if (_a.pathType) {\n _a.FormioClass.setPathType(_a.pathType);\n }\n // Add libraries if they wish to include the libs.\n if (_a.config.template && _a.config.includeLibs) {\n yield _a.addLibrary(libWrapper, _a.config.libs[_a.config.template], _a.config.template);\n }\n if (!_a.config.libraries) {\n _a.config.libraries = _a.config.modules || {};\n }\n // Adding premium if it is provided via the config.\n if (_a.config.premium) {\n _a.config.libraries.premium = _a.config.premium;\n }\n // Allow adding dynamic modules.\n if (_a.config.libraries) {\n for (const name in _a.config.libraries) {\n const lib = _a.config.libraries[name];\n lib.use = lib.use || true;\n yield _a.addLibrary(libWrapper, lib, name);\n }\n }\n yield _a.addStyles(libWrapper, _a.formioScript(_a.config.style || `${_a.cdn.js}/${renderer}.css`, builder));\n if (_a.config.before) {\n yield _a.config.before(_a.FormioClass, element, _a.config);\n }\n _a.FormioClass.license = true;\n _a._formioReady(_a.FormioClass);\n return wrapper;\n });\n }\n // Called after an instance has been created.\n static afterCreate(instance, wrapper, readyEvent) {\n return __awaiter(this, void 0, void 0, function* () {\n const loader = wrapper.querySelector('.formio-loader');\n if (loader) {\n wrapper.removeChild(loader);\n }\n _a.FormioClass.events.emit(readyEvent, instance);\n if (_a.config.after) {\n _a.debug('Calling ready callback');\n _a.config.after(instance, _a.config);\n }\n return instance;\n });\n }\n // Create a new form.\n static createForm(element, form, options = {}) {\n return __awaiter(this, void 0, void 0, function* () {\n if (_a.FormioClass) {\n return _a.FormioClass.createForm(element, form, Object.assign(Object.assign({}, options), { noLoader: true }));\n }\n const wrapper = yield _a.init(element, options);\n return _a.FormioClass.createForm(element, form, Object.assign(Object.assign({}, options), { noLoader: true })).then((instance) => {\n // Set the default submission data.\n if (_a.config.submission) {\n _a.debug('Setting submission', _a.config.submission);\n instance.submission = _a.config.submission;\n }\n // Call the after create method.\n _a.afterCreate(instance, wrapper, 'formEmbedded');\n return instance;\n });\n });\n }\n // Create a form builder.\n static builder(element, form, options = {}) {\n var _b;\n return __awaiter(this, void 0, void 0, function* () {\n if ((_b = _a.FormioClass) === null || _b === void 0 ? void 0 : _b.builder) {\n return _a.FormioClass.builder(element, form, options);\n }\n const wrapper = yield _a.init(element, options, true);\n return _a.FormioClass.builder(element, form, options).then((instance) => {\n _a.afterCreate(instance, wrapper, 'builderEmbedded');\n return instance;\n });\n });\n }\n}\nexports.Formio = Formio;\n_a = Formio;\nFormio.FormioClass = null;\nFormio.config = {};\nFormio.modules = [];\nFormio.icons = '';\nFormio.license = '';\nFormio.formioReady = new Promise((ready, reject) => {\n _a._formioReady = ready;\n _a._formioReadyReject = reject;\n});\nFormio.version = '5.0.0-rc.83';\n// Create a report.\nFormio.Report = {\n create: (element, submission, options = {}) => __awaiter(void 0, void 0, void 0, function* () {\n var _b;\n if ((_b = _a.FormioClass) === null || _b === void 0 ? void 0 : _b.Report) {\n return _a.FormioClass.Report.create(element, submission, options);\n }\n const wrapper = yield _a.init(element, options, true);\n return _a.FormioClass.Report.create(element, submission, options).then((instance) => {\n _a.afterCreate(instance, wrapper, 'reportEmbedded');\n return instance;\n });\n })\n};\nCDN_js_1.default.defaultCDN = Formio.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';\nclass Form {\n constructor(element, form, options) {\n this.form = form;\n this.element = element;\n this.options = options || {};\n this.init();\n this.instance = {\n proxy: true,\n ready: this.ready,\n destroy: () => { }\n };\n }\n init() {\n if (this.instance && !this.instance.proxy) {\n this.instance.destroy();\n }\n this.element.innerHTML = '';\n this.ready = this.create().then((instance) => {\n this.instance = instance;\n this.form = instance.form;\n return instance;\n });\n }\n create() {\n return Formio.createForm(this.element, this.form, this.options);\n }\n setForm(form) {\n this.form = form;\n if (this.instance) {\n this.instance.setForm(form);\n }\n }\n setDisplay(display) {\n if (this.instance.proxy) {\n return this.ready;\n }\n this.form.display = display;\n this.instance.destroy();\n this.ready = this.create().then((instance) => {\n this.instance = instance;\n this.setForm(this.form);\n });\n return this.ready;\n }\n}\nexports.Form = Form;\nclass FormBuilder extends Form {\n create() {\n return Formio.builder(this.element, this.form, this.options);\n }\n}\nexports.FormBuilder = FormBuilder;\nFormio.Form = Form;\nFormio.FormBuilder = FormBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Embed.js?");
10847
10847
 
10848
10848
  /***/ }),
10849
10849
 
@@ -10854,7 +10854,7 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
10854
10854
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
10855
10855
 
10856
10856
  "use strict";
10857
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.Formio = void 0;\nconst sdk_1 = __webpack_require__(/*! @formio/core/sdk */ \"./node_modules/@formio/core/lib/sdk/index.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return sdk_1.Formio; } }));\nconst Embed_1 = __webpack_require__(/*! ./Embed */ \"./lib/cjs/Embed.js\");\nconst CDN_1 = __importDefault(__webpack_require__(/*! ./CDN */ \"./lib/cjs/CDN.js\"));\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\nsdk_1.Formio.cdn = new CDN_1.default();\nsdk_1.Formio.Providers = providers_1.default;\nsdk_1.Formio.version = '5.0.0-rc.82';\nCDN_1.default.defaultCDN = sdk_1.Formio.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';\nconst isNil = (val) => val === null || val === undefined;\nsdk_1.Formio.prototype.uploadFile = function (storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) {\n const requestArgs = {\n provider: storage,\n method: 'upload',\n file: file,\n fileName: fileName,\n dir: dir\n };\n fileKey = fileKey || 'file';\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', storage);\n if (Provider) {\n const provider = new Provider(this);\n if (uploadStartCallback) {\n uploadStartCallback();\n }\n return provider.uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback, multipartOptions);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\nsdk_1.Formio.prototype.downloadFile = function (file, options) {\n const requestArgs = {\n method: 'download',\n file: file\n };\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.downloadFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\nsdk_1.Formio.prototype.deleteFile = function (file, options) {\n const requestArgs = {\n method: 'delete',\n file: file\n };\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.deleteFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\n// Esnure we proxy the following methods to the FormioEmbed class.\n['setBaseUrl', 'setApiUrl', 'setAppUrl', 'setProjectUrl', 'setPathType', 'setLicense'].forEach((fn) => {\n const baseFn = sdk_1.Formio[fn];\n sdk_1.Formio[fn] = function (arg) {\n const retVal = Embed_1.Formio[fn](arg, true);\n return baseFn ? baseFn.call(this, arg) : retVal;\n };\n});\n// For reverse compatability.\nsdk_1.Formio.Promise = Promise;\nsdk_1.Formio.formioReady = Embed_1.Formio.formioReady;\nsdk_1.Formio.config = Embed_1.Formio.config;\nsdk_1.Formio.builder = Embed_1.Formio.builder;\nsdk_1.Formio.Report = Embed_1.Formio.Report;\nsdk_1.Formio.Form = Embed_1.Formio.Form;\nsdk_1.Formio.FormBuilder = Embed_1.Formio.FormBuilder;\nsdk_1.Formio.use = Embed_1.Formio.use;\nsdk_1.Formio.createForm = Embed_1.Formio.createForm;\nsdk_1.Formio.submitDone = Embed_1.Formio.submitDone;\nsdk_1.Formio.addLibrary = Embed_1.Formio.addLibrary;\nsdk_1.Formio.addLoader = Embed_1.Formio.addLoader;\nsdk_1.Formio.addToGlobal = (global) => {\n if (typeof global === 'object' && !global.Formio) {\n global.Formio = sdk_1.Formio;\n }\n};\nif (typeof __webpack_require__.g !== 'undefined') {\n sdk_1.Formio.addToGlobal(__webpack_require__.g);\n}\nif (typeof window !== 'undefined') {\n sdk_1.Formio.addToGlobal(window);\n}\nEmbed_1.Formio._formioReady(sdk_1.Formio);\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Formio.js?");
10857
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.Formio = void 0;\nconst sdk_1 = __webpack_require__(/*! @formio/core/sdk */ \"./node_modules/@formio/core/lib/sdk/index.js\");\nObject.defineProperty(exports, \"Formio\", ({ enumerable: true, get: function () { return sdk_1.Formio; } }));\nconst Embed_1 = __webpack_require__(/*! ./Embed */ \"./lib/cjs/Embed.js\");\nconst CDN_1 = __importDefault(__webpack_require__(/*! ./CDN */ \"./lib/cjs/CDN.js\"));\nconst providers_1 = __importDefault(__webpack_require__(/*! ./providers */ \"./lib/cjs/providers/index.js\"));\nsdk_1.Formio.cdn = new CDN_1.default();\nsdk_1.Formio.Providers = providers_1.default;\nsdk_1.Formio.version = '5.0.0-rc.83';\nCDN_1.default.defaultCDN = sdk_1.Formio.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';\nconst isNil = (val) => val === null || val === undefined;\nsdk_1.Formio.prototype.uploadFile = function (storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) {\n const requestArgs = {\n provider: storage,\n method: 'upload',\n file: file,\n fileName: fileName,\n dir: dir\n };\n fileKey = fileKey || 'file';\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', storage);\n if (Provider) {\n const provider = new Provider(this);\n if (uploadStartCallback) {\n uploadStartCallback();\n }\n return provider.uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback, multipartOptions);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\nsdk_1.Formio.prototype.downloadFile = function (file, options) {\n const requestArgs = {\n method: 'download',\n file: file\n };\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.downloadFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\nsdk_1.Formio.prototype.deleteFile = function (file, options) {\n const requestArgs = {\n method: 'delete',\n file: file\n };\n const request = sdk_1.Formio.pluginWait('preRequest', requestArgs)\n .then(() => {\n return sdk_1.Formio.pluginGet('fileRequest', requestArgs)\n .then((result) => {\n if (file.storage && isNil(result)) {\n const Provider = providers_1.default.getProvider('storage', file.storage);\n if (Provider) {\n const provider = new Provider(this);\n return provider.deleteFile(file, options);\n }\n else {\n throw ('Storage provider not found');\n }\n }\n return result || { url: '' };\n });\n });\n return sdk_1.Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs);\n};\n// Esnure we proxy the following methods to the FormioEmbed class.\n['setBaseUrl', 'setApiUrl', 'setAppUrl', 'setProjectUrl', 'setPathType', 'setLicense'].forEach((fn) => {\n const baseFn = sdk_1.Formio[fn];\n sdk_1.Formio[fn] = function (arg) {\n const retVal = Embed_1.Formio[fn](arg, true);\n return baseFn ? baseFn.call(this, arg) : retVal;\n };\n});\n// For reverse compatability.\nsdk_1.Formio.Promise = Promise;\nsdk_1.Formio.formioReady = Embed_1.Formio.formioReady;\nsdk_1.Formio.config = Embed_1.Formio.config;\nsdk_1.Formio.builder = Embed_1.Formio.builder;\nsdk_1.Formio.Report = Embed_1.Formio.Report;\nsdk_1.Formio.Form = Embed_1.Formio.Form;\nsdk_1.Formio.FormBuilder = Embed_1.Formio.FormBuilder;\nsdk_1.Formio.use = Embed_1.Formio.use;\nsdk_1.Formio.createForm = Embed_1.Formio.createForm;\nsdk_1.Formio.submitDone = Embed_1.Formio.submitDone;\nsdk_1.Formio.addLibrary = Embed_1.Formio.addLibrary;\nsdk_1.Formio.addLoader = Embed_1.Formio.addLoader;\nsdk_1.Formio.addToGlobal = (global) => {\n if (typeof global === 'object' && !global.Formio) {\n global.Formio = sdk_1.Formio;\n }\n};\nif (typeof __webpack_require__.g !== 'undefined') {\n sdk_1.Formio.addToGlobal(__webpack_require__.g);\n}\nif (typeof window !== 'undefined') {\n sdk_1.Formio.addToGlobal(window);\n}\nEmbed_1.Formio._formioReady(sdk_1.Formio);\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Formio.js?");
10858
10858
 
10859
10859
  /***/ }),
10860
10860