@formio/js 5.0.0-dev.5614.ea3660d → 5.0.0-dev.5620.dedc19b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/Changelog.md +4 -2
  2. package/dist/formio.form.js +31 -21
  3. package/dist/formio.form.min.js +1 -1
  4. package/dist/formio.form.min.js.LICENSE.txt +2 -0
  5. package/dist/formio.full.js +34 -24
  6. package/dist/formio.full.min.js +1 -1
  7. package/dist/formio.full.min.js.LICENSE.txt +2 -0
  8. package/dist/formio.utils.js +13 -3
  9. package/dist/formio.utils.min.js +1 -1
  10. package/dist/formio.utils.min.js.LICENSE.txt +2 -0
  11. package/lib/cjs/Element.d.ts +2 -1
  12. package/lib/cjs/Element.js +17 -8
  13. package/lib/cjs/Form.js +15 -1
  14. package/lib/cjs/PDF.js +8 -1
  15. package/lib/cjs/PDFBuilder.js +3 -3
  16. package/lib/cjs/Webform.d.ts +0 -1
  17. package/lib/cjs/Webform.js +17 -12
  18. package/lib/cjs/WebformBuilder.d.ts +0 -1
  19. package/lib/cjs/WebformBuilder.js +4 -4
  20. package/lib/cjs/Wizard.js +1 -1
  21. package/lib/cjs/addons/FormioAddon.d.ts +1 -0
  22. package/lib/cjs/components/_classes/component/Component.d.ts +2 -1
  23. package/lib/cjs/components/_classes/component/Component.js +46 -8
  24. package/lib/cjs/components/_classes/input/Input.js +16 -1
  25. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +2 -2
  26. package/lib/cjs/components/_classes/nested/NestedComponent.js +8 -7
  27. package/lib/cjs/components/columns/Columns.js +2 -2
  28. package/lib/cjs/components/editgrid/EditGrid.d.ts +1 -1
  29. package/lib/cjs/components/editgrid/EditGrid.js +21 -7
  30. package/lib/cjs/components/file/File.d.ts +1 -0
  31. package/lib/cjs/components/file/File.js +2 -2
  32. package/lib/cjs/components/form/Form.js +3 -3
  33. package/lib/cjs/components/radio/Radio.d.ts +1 -1
  34. package/lib/cjs/components/radio/Radio.js +5 -3
  35. package/lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.d.ts +5 -0
  36. package/lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +3 -0
  37. package/lib/cjs/components/select/Select.js +10 -3
  38. package/lib/cjs/components/select/fixtures/comp23.d.ts +47 -0
  39. package/lib/cjs/components/select/fixtures/comp23.js +40 -0
  40. package/lib/cjs/components/select/fixtures/index.d.ts +2 -1
  41. package/lib/cjs/components/select/fixtures/index.js +3 -1
  42. package/lib/cjs/components/selectboxes/SelectBoxes.js +4 -1
  43. package/lib/cjs/components/table/Table.d.ts +0 -1
  44. package/lib/cjs/components/table/Table.js +1 -1
  45. package/lib/cjs/components/tags/Tags.js +4 -2
  46. package/lib/cjs/utils/utils.d.ts +7 -1
  47. package/lib/cjs/utils/utils.js +29 -3
  48. package/lib/cjs/widgets/CalendarWidget.js +2 -2
  49. package/lib/mjs/Element.d.ts +2 -1
  50. package/lib/mjs/Element.js +17 -8
  51. package/lib/mjs/Form.js +15 -1
  52. package/lib/mjs/PDF.js +8 -1
  53. package/lib/mjs/PDFBuilder.js +3 -3
  54. package/lib/mjs/Webform.d.ts +0 -1
  55. package/lib/mjs/Webform.js +17 -12
  56. package/lib/mjs/WebformBuilder.d.ts +0 -1
  57. package/lib/mjs/WebformBuilder.js +4 -4
  58. package/lib/mjs/Wizard.js +1 -1
  59. package/lib/mjs/addons/FormioAddon.d.ts +1 -0
  60. package/lib/mjs/components/_classes/component/Component.d.ts +2 -1
  61. package/lib/mjs/components/_classes/component/Component.js +47 -9
  62. package/lib/mjs/components/_classes/input/Input.js +16 -1
  63. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +2 -2
  64. package/lib/mjs/components/_classes/nested/NestedComponent.js +8 -7
  65. package/lib/mjs/components/columns/Columns.js +2 -2
  66. package/lib/mjs/components/editgrid/EditGrid.d.ts +1 -1
  67. package/lib/mjs/components/editgrid/EditGrid.js +20 -7
  68. package/lib/mjs/components/file/File.d.ts +1 -0
  69. package/lib/mjs/components/file/File.js +2 -2
  70. package/lib/mjs/components/form/Form.js +3 -3
  71. package/lib/mjs/components/radio/Radio.d.ts +1 -1
  72. package/lib/mjs/components/radio/Radio.js +5 -3
  73. package/lib/mjs/components/recaptcha/editForm/ReCaptcha.edit.display.d.ts +5 -0
  74. package/lib/mjs/components/recaptcha/editForm/ReCaptcha.edit.display.js +3 -0
  75. package/lib/mjs/components/select/Select.js +10 -3
  76. package/lib/mjs/components/select/fixtures/comp23.d.ts +47 -0
  77. package/lib/mjs/components/select/fixtures/comp23.js +38 -0
  78. package/lib/mjs/components/select/fixtures/index.d.ts +2 -1
  79. package/lib/mjs/components/select/fixtures/index.js +2 -1
  80. package/lib/mjs/components/selectboxes/SelectBoxes.js +4 -1
  81. package/lib/mjs/components/table/Table.d.ts +0 -1
  82. package/lib/mjs/components/table/Table.js +1 -1
  83. package/lib/mjs/components/tags/Tags.js +4 -2
  84. package/lib/mjs/utils/utils.d.ts +7 -1
  85. package/lib/mjs/utils/utils.js +15 -1
  86. package/lib/mjs/widgets/CalendarWidget.js +2 -2
  87. package/package.json +2 -2
@@ -1894,7 +1894,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
1894
1894
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
1895
1895
 
1896
1896
  "use strict";
1897
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.sanitize = void 0;\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.js\"));\nlet DOMPurify = null;\nconst getDOMPurify = () => {\n if (DOMPurify) {\n return DOMPurify;\n }\n if (window) {\n DOMPurify = (0, dompurify_1.default)(window);\n return DOMPurify;\n }\n return null;\n};\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n const dompurify = getDOMPurify();\n if (!dompurify) {\n console.log('DOMPurify unable to sanitize the contents.');\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target', 'within'],\n USE_PROFILES: { html: true }\n };\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n sanitizeOptions.ALLOWED_URI_REGEXP = options.sanitizeConfig.allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/utils/sanitize.js?");
1897
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.sanitize = void 0;\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/@formio/core/node_modules/dompurify/dist/purify.js\"));\nlet DOMPurify = null;\nconst getDOMPurify = () => {\n if (DOMPurify) {\n return DOMPurify;\n }\n if (window) {\n DOMPurify = (0, dompurify_1.default)(window);\n return DOMPurify;\n }\n return null;\n};\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n const dompurify = getDOMPurify();\n if (!dompurify) {\n console.log('DOMPurify unable to sanitize the contents.');\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target', 'within'],\n USE_PROFILES: { html: true }\n };\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n sanitizeOptions.ALLOWED_URI_REGEXP = options.sanitizeConfig.allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/lib/utils/sanitize.js?");
1898
1898
 
1899
1899
  /***/ }),
1900
1900
 
@@ -1920,6 +1920,16 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
1920
1920
 
1921
1921
  /***/ }),
1922
1922
 
1923
+ /***/ "./node_modules/@formio/core/node_modules/dompurify/dist/purify.js":
1924
+ /*!*************************************************************************!*\
1925
+ !*** ./node_modules/@formio/core/node_modules/dompurify/dist/purify.js ***!
1926
+ \*************************************************************************/
1927
+ /***/ (function(module) {
1928
+
1929
+ eval("/*! @license DOMPurify 3.1.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.0/LICENSE */\n\n(function (global, factory) {\n true ? module.exports = factory() :\n 0;\n})(this, (function () { 'use strict';\n\n const {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n } = Object;\n let {\n freeze,\n seal,\n create\n } = Object; // eslint-disable-line import/no-mutable-exports\n let {\n apply,\n construct\n } = typeof Reflect !== 'undefined' && Reflect;\n if (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n }\n if (!seal) {\n seal = function seal(x) {\n return x;\n };\n }\n if (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n }\n if (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n }\n const arrayForEach = unapply(Array.prototype.forEach);\n const arrayPop = unapply(Array.prototype.pop);\n const arrayPush = unapply(Array.prototype.push);\n const stringToLowerCase = unapply(String.prototype.toLowerCase);\n const stringToString = unapply(String.prototype.toString);\n const stringMatch = unapply(String.prototype.match);\n const stringReplace = unapply(String.prototype.replace);\n const stringIndexOf = unapply(String.prototype.indexOf);\n const stringTrim = unapply(String.prototype.trim);\n const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\n const regExpTest = unapply(RegExp.prototype.test);\n const typeErrorCreate = unconstruct(TypeError);\n\n /**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param {Function} func - The function to be wrapped and called.\n * @returns {Function} A new function that calls the given function with a specified thisArg and arguments.\n */\n function unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n }\n\n /**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param {Function} func - The constructor function to be wrapped and called.\n * @returns {Function} A new function that constructs an instance of the given constructor function with the provided arguments.\n */\n function unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n }\n\n /**\n * Add properties to a lookup table\n *\n * @param {Object} set - The set to which elements will be added.\n * @param {Array} array - The array containing elements to be added to the set.\n * @param {Function} transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns {Object} The modified set with added elements.\n */\n function addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n }\n\n /**\n * Clean up an array to harden against CSPP\n *\n * @param {Array} array - The array to be cleaned.\n * @returns {Array} The cleaned version of the array\n */\n function cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n }\n\n /**\n * Shallow clone an object\n *\n * @param {Object} object - The object to be cloned.\n * @returns {Object} A new object that copies the original.\n */\n function clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n }\n\n /**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param {Object} object - The object to look up the getter function in its prototype chain.\n * @param {String} prop - The property name for which to find the getter function.\n * @returns {Function} The getter function found in the prototype chain or a fallback function.\n */\n function lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n }\n\n const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n\n // SVG\n const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n\n // List of SVG elements that are disallowed by default.\n // We still need to know them so that we can do namespace\n // checks properly in case one wants to add them to\n // allow-list.\n const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n\n // Similarly to SVG, we want to know all MathML elements,\n // even those that we disallow by default.\n const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n const text = freeze(['#text']);\n\n const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\n const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n // eslint-disable-next-line unicorn/better-regex\n const MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\n const ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\n const TMPLIT_EXPR = seal(/\\${[\\w\\W]*}/gm);\n const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\n const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\n const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n );\n\n const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\n const ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n );\n\n const DOCTYPE_NAME = seal(/^html$/i);\n const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\n var EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n ERB_EXPR: ERB_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR,\n DATA_ATTR: DATA_ATTR,\n ARIA_ATTR: ARIA_ATTR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n DOCTYPE_NAME: DOCTYPE_NAME,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT\n });\n\n const getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n };\n\n /**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param {TrustedTypePolicyFactory} trustedTypes The policy factory.\n * @param {HTMLScriptElement} purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return {TrustedTypePolicy} The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\n const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n };\n function createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n\n /**\n * Version label, exposed for easier checks\n * if DOMPurify is up to date or not\n */\n DOMPurify.version = '3.1.0';\n\n /**\n * Array of elements that DOMPurify removed during sanitation.\n * Empty if nothing was removed.\n */\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== 9) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = {};\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n\n /*\n * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n\n /**\n * _parseConfig\n *\n * @param {Object} cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),\n // eslint-disable-line indent\n cfg.ADD_URI_SAFE_ATTR,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS),\n // eslint-disable-line indent\n cfg.ADD_DATA_URI_TAGS,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);\n\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n\n /**\n * @param {Element} element a DOM element whose namespace is being checked\n * @returns {boolean} Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either <annotation-xml> or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n\n /**\n * _forceRemove\n *\n * @param {Node} node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n node.parentNode.removeChild(node);\n } catch (_) {\n node.remove();\n }\n };\n\n /**\n * _removeAttribute\n *\n * @param {String} name an Attribute name\n * @param {Node} node a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, node) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: node.getAttributeNode(name),\n from: node\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: node\n });\n }\n node.removeAttribute(name);\n\n // We void attribute values for unremovable \"is\"\" attributes\n if (name === 'is' && !ALLOWED_ATTR[name]) {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(node);\n } catch (_) {}\n } else {\n try {\n node.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n\n /**\n * _initDocument\n *\n * @param {String} dirty a string of dirty markup\n * @return {Document} a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param {Node} root The root element or node to start traversing on.\n * @return {NodeIterator} The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n\n /**\n * _isClobbered\n *\n * @param {Node} elm element to check for clobbering attacks\n * @return {Boolean} true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(elm) {\n return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');\n };\n\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param {Node} object object to check whether it's a DOM node\n * @return {Boolean} true is object is a DOM node\n */\n const _isNode = function _isNode(object) {\n return typeof Node === 'function' && object instanceof Node;\n };\n\n /**\n * _executeHook\n * Execute user configurable hooks\n *\n * @param {String} entryPoint Name of the hook's entry point\n * @param {Node} currentNode node to work on with the hook\n * @param {Object} data additional hook parameters\n */\n const _executeHook = function _executeHook(entryPoint, currentNode, data) {\n if (!hooks[entryPoint]) {\n return;\n }\n arrayForEach(hooks[entryPoint], hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n };\n\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n *\n * @param {Node} currentNode to check for permission to exist\n * @return {Boolean} true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeElements', currentNode, null);\n\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n\n /* Execute a hook if present */\n _executeHook('uponSanitizeElement', currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n\n /* Detect mXSS attempts abusing namespace confusion */\n if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any ocurrence of processing instructions */\n if (currentNode.nodeType === 7) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeElements', currentNode, null);\n return false;\n };\n\n /**\n * _isValidAttribute\n *\n * @param {string} lcTag Lowercase tag name of containing element.\n * @param {string} lcName Lowercase attribute name.\n * @param {string} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param {string} tagName name of the tag of the node to sanitize\n * @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param {Node} currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHook('beforeSanitizeAttributes', currentNode, null);\n const {\n attributes\n } = currentNode;\n\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR\n };\n let l = attributes.length;\n\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n let value = name === 'value' ? attrValue : stringTrim(attrValue);\n\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHook('uponSanitizeAttribute', currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n\n /* Remove attribute */\n _removeAttribute(name, currentNode);\n\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n continue;\n }\n\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n arrayPop(DOMPurify.removed);\n } catch (_) {}\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeAttributes', currentNode, null);\n };\n\n /**\n * _sanitizeShadowDOM\n *\n * @param {DocumentFragment} fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeShadowDOM', fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHook('uponSanitizeShadowNode', shadowNode, null);\n\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeShadowDOM', fragment, null);\n };\n\n /**\n * Sanitize\n * Public method providing core sanitation functionality\n *\n * @param {String|Node} dirty string or DOM node\n * @param {Object} cfg object\n */\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n\n /* Clean up removed elements */\n DOMPurify.removed = [];\n\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n }\n\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n\n /**\n * Public method to set the configuration once\n * setConfig\n *\n * @param {Object} cfg configuration object\n */\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n\n /**\n * Public method to remove the configuration\n * clearConfig\n *\n */\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n\n /**\n * Public method to check if an attribute value is valid.\n * Uses last set config, if any. Otherwise, uses config defaults.\n * isValidAttribute\n *\n * @param {String} tag Tag name of containing element.\n * @param {String} attr Attribute name.\n * @param {String} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.\n */\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n\n /**\n * AddHook\n * Public method to add DOMPurify hooks\n *\n * @param {String} entryPoint entry point for the hook to add\n * @param {Function} hookFunction function to execute\n */\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n hooks[entryPoint] = hooks[entryPoint] || [];\n arrayPush(hooks[entryPoint], hookFunction);\n };\n\n /**\n * RemoveHook\n * Public method to remove a DOMPurify hook at a given entryPoint\n * (pops it from the stack of hooks if more are present)\n *\n * @param {String} entryPoint entry point for the hook to remove\n * @return {Function} removed(popped) hook\n */\n DOMPurify.removeHook = function (entryPoint) {\n if (hooks[entryPoint]) {\n return arrayPop(hooks[entryPoint]);\n }\n };\n\n /**\n * RemoveHooks\n * Public method to remove all DOMPurify hooks at a given entryPoint\n *\n * @param {String} entryPoint entry point for the hooks to remove\n */\n DOMPurify.removeHooks = function (entryPoint) {\n if (hooks[entryPoint]) {\n hooks[entryPoint] = [];\n }\n };\n\n /**\n * RemoveAllHooks\n * Public method to remove all DOMPurify hooks\n */\n DOMPurify.removeAllHooks = function () {\n hooks = {};\n };\n return DOMPurify;\n }\n var purify = createDOMPurify();\n\n return purify;\n\n}));\n//# sourceMappingURL=purify.js.map\n\n\n//# sourceURL=webpack://Formio/./node_modules/@formio/core/node_modules/dompurify/dist/purify.js?");
1930
+
1931
+ /***/ }),
1932
+
1923
1933
  /***/ "./node_modules/@formio/core/node_modules/inputmask/dist/inputmask.js":
1924
1934
  /*!****************************************************************************!*\
1925
1935
  !*** ./node_modules/@formio/core/node_modules/inputmask/dist/inputmask.js ***!
@@ -2868,7 +2878,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n\n
2868
2878
  \***********************************************/
2869
2879
  /***/ (function(module) {
2870
2880
 
2871
- eval("/*! @license DOMPurify 3.1.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.0/LICENSE */\n\n(function (global, factory) {\n true ? module.exports = factory() :\n 0;\n})(this, (function () { 'use strict';\n\n const {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n } = Object;\n let {\n freeze,\n seal,\n create\n } = Object; // eslint-disable-line import/no-mutable-exports\n let {\n apply,\n construct\n } = typeof Reflect !== 'undefined' && Reflect;\n if (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n }\n if (!seal) {\n seal = function seal(x) {\n return x;\n };\n }\n if (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n }\n if (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n }\n const arrayForEach = unapply(Array.prototype.forEach);\n const arrayPop = unapply(Array.prototype.pop);\n const arrayPush = unapply(Array.prototype.push);\n const stringToLowerCase = unapply(String.prototype.toLowerCase);\n const stringToString = unapply(String.prototype.toString);\n const stringMatch = unapply(String.prototype.match);\n const stringReplace = unapply(String.prototype.replace);\n const stringIndexOf = unapply(String.prototype.indexOf);\n const stringTrim = unapply(String.prototype.trim);\n const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\n const regExpTest = unapply(RegExp.prototype.test);\n const typeErrorCreate = unconstruct(TypeError);\n\n /**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param {Function} func - The function to be wrapped and called.\n * @returns {Function} A new function that calls the given function with a specified thisArg and arguments.\n */\n function unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n }\n\n /**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param {Function} func - The constructor function to be wrapped and called.\n * @returns {Function} A new function that constructs an instance of the given constructor function with the provided arguments.\n */\n function unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n }\n\n /**\n * Add properties to a lookup table\n *\n * @param {Object} set - The set to which elements will be added.\n * @param {Array} array - The array containing elements to be added to the set.\n * @param {Function} transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns {Object} The modified set with added elements.\n */\n function addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n }\n\n /**\n * Clean up an array to harden against CSPP\n *\n * @param {Array} array - The array to be cleaned.\n * @returns {Array} The cleaned version of the array\n */\n function cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n }\n\n /**\n * Shallow clone an object\n *\n * @param {Object} object - The object to be cloned.\n * @returns {Object} A new object that copies the original.\n */\n function clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n }\n\n /**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param {Object} object - The object to look up the getter function in its prototype chain.\n * @param {String} prop - The property name for which to find the getter function.\n * @returns {Function} The getter function found in the prototype chain or a fallback function.\n */\n function lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n }\n\n const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n\n // SVG\n const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n\n // List of SVG elements that are disallowed by default.\n // We still need to know them so that we can do namespace\n // checks properly in case one wants to add them to\n // allow-list.\n const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n\n // Similarly to SVG, we want to know all MathML elements,\n // even those that we disallow by default.\n const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n const text = freeze(['#text']);\n\n const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\n const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n // eslint-disable-next-line unicorn/better-regex\n const MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\n const ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\n const TMPLIT_EXPR = seal(/\\${[\\w\\W]*}/gm);\n const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\n const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\n const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n );\n\n const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\n const ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n );\n\n const DOCTYPE_NAME = seal(/^html$/i);\n const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\n var EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n ERB_EXPR: ERB_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR,\n DATA_ATTR: DATA_ATTR,\n ARIA_ATTR: ARIA_ATTR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n DOCTYPE_NAME: DOCTYPE_NAME,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT\n });\n\n const getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n };\n\n /**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param {TrustedTypePolicyFactory} trustedTypes The policy factory.\n * @param {HTMLScriptElement} purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return {TrustedTypePolicy} The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\n const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n };\n function createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n\n /**\n * Version label, exposed for easier checks\n * if DOMPurify is up to date or not\n */\n DOMPurify.version = '3.1.0';\n\n /**\n * Array of elements that DOMPurify removed during sanitation.\n * Empty if nothing was removed.\n */\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== 9) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = {};\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n\n /*\n * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n\n /**\n * _parseConfig\n *\n * @param {Object} cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),\n // eslint-disable-line indent\n cfg.ADD_URI_SAFE_ATTR,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS),\n // eslint-disable-line indent\n cfg.ADD_DATA_URI_TAGS,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'desc', 'title', 'annotation-xml']);\n\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n\n /**\n * @param {Element} element a DOM element whose namespace is being checked\n * @returns {boolean} Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either <annotation-xml> or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n\n /**\n * _forceRemove\n *\n * @param {Node} node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n node.parentNode.removeChild(node);\n } catch (_) {\n node.remove();\n }\n };\n\n /**\n * _removeAttribute\n *\n * @param {String} name an Attribute name\n * @param {Node} node a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, node) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: node.getAttributeNode(name),\n from: node\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: node\n });\n }\n node.removeAttribute(name);\n\n // We void attribute values for unremovable \"is\"\" attributes\n if (name === 'is' && !ALLOWED_ATTR[name]) {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(node);\n } catch (_) {}\n } else {\n try {\n node.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n\n /**\n * _initDocument\n *\n * @param {String} dirty a string of dirty markup\n * @return {Document} a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param {Node} root The root element or node to start traversing on.\n * @return {NodeIterator} The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n\n /**\n * _isClobbered\n *\n * @param {Node} elm element to check for clobbering attacks\n * @return {Boolean} true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(elm) {\n return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');\n };\n\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param {Node} object object to check whether it's a DOM node\n * @return {Boolean} true is object is a DOM node\n */\n const _isNode = function _isNode(object) {\n return typeof Node === 'function' && object instanceof Node;\n };\n\n /**\n * _executeHook\n * Execute user configurable hooks\n *\n * @param {String} entryPoint Name of the hook's entry point\n * @param {Node} currentNode node to work on with the hook\n * @param {Object} data additional hook parameters\n */\n const _executeHook = function _executeHook(entryPoint, currentNode, data) {\n if (!hooks[entryPoint]) {\n return;\n }\n arrayForEach(hooks[entryPoint], hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n };\n\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n *\n * @param {Node} currentNode to check for permission to exist\n * @return {Boolean} true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeElements', currentNode, null);\n\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n\n /* Execute a hook if present */\n _executeHook('uponSanitizeElement', currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n\n /* Detect mXSS attempts abusing namespace confusion */\n if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any ocurrence of processing instructions */\n if (currentNode.nodeType === 7) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n parentNode.insertBefore(cloneNode(childNodes[i], true), getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeElements', currentNode, null);\n return false;\n };\n\n /**\n * _isValidAttribute\n *\n * @param {string} lcTag Lowercase tag name of containing element.\n * @param {string} lcName Lowercase attribute name.\n * @param {string} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param {string} tagName name of the tag of the node to sanitize\n * @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param {Node} currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHook('beforeSanitizeAttributes', currentNode, null);\n const {\n attributes\n } = currentNode;\n\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR\n };\n let l = attributes.length;\n\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n let value = name === 'value' ? attrValue : stringTrim(attrValue);\n\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHook('uponSanitizeAttribute', currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n\n /* Remove attribute */\n _removeAttribute(name, currentNode);\n\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n continue;\n }\n\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n arrayPop(DOMPurify.removed);\n } catch (_) {}\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeAttributes', currentNode, null);\n };\n\n /**\n * _sanitizeShadowDOM\n *\n * @param {DocumentFragment} fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeShadowDOM', fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHook('uponSanitizeShadowNode', shadowNode, null);\n\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeShadowDOM', fragment, null);\n };\n\n /**\n * Sanitize\n * Public method providing core sanitation functionality\n *\n * @param {String|Node} dirty string or DOM node\n * @param {Object} cfg object\n */\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n\n /* Clean up removed elements */\n DOMPurify.removed = [];\n\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n }\n\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n\n /**\n * Public method to set the configuration once\n * setConfig\n *\n * @param {Object} cfg configuration object\n */\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n\n /**\n * Public method to remove the configuration\n * clearConfig\n *\n */\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n\n /**\n * Public method to check if an attribute value is valid.\n * Uses last set config, if any. Otherwise, uses config defaults.\n * isValidAttribute\n *\n * @param {String} tag Tag name of containing element.\n * @param {String} attr Attribute name.\n * @param {String} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.\n */\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n\n /**\n * AddHook\n * Public method to add DOMPurify hooks\n *\n * @param {String} entryPoint entry point for the hook to add\n * @param {Function} hookFunction function to execute\n */\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n hooks[entryPoint] = hooks[entryPoint] || [];\n arrayPush(hooks[entryPoint], hookFunction);\n };\n\n /**\n * RemoveHook\n * Public method to remove a DOMPurify hook at a given entryPoint\n * (pops it from the stack of hooks if more are present)\n *\n * @param {String} entryPoint entry point for the hook to remove\n * @return {Function} removed(popped) hook\n */\n DOMPurify.removeHook = function (entryPoint) {\n if (hooks[entryPoint]) {\n return arrayPop(hooks[entryPoint]);\n }\n };\n\n /**\n * RemoveHooks\n * Public method to remove all DOMPurify hooks at a given entryPoint\n *\n * @param {String} entryPoint entry point for the hooks to remove\n */\n DOMPurify.removeHooks = function (entryPoint) {\n if (hooks[entryPoint]) {\n hooks[entryPoint] = [];\n }\n };\n\n /**\n * RemoveAllHooks\n * Public method to remove all DOMPurify hooks\n */\n DOMPurify.removeAllHooks = function () {\n hooks = {};\n };\n return DOMPurify;\n }\n var purify = createDOMPurify();\n\n return purify;\n\n}));\n//# sourceMappingURL=purify.js.map\n\n\n//# sourceURL=webpack://Formio/./node_modules/dompurify/dist/purify.js?");
2881
+ eval("/*! @license DOMPurify 3.1.4 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.4/LICENSE */\n\n(function (global, factory) {\n true ? module.exports = factory() :\n 0;\n})(this, (function () { 'use strict';\n\n const {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n } = Object;\n let {\n freeze,\n seal,\n create\n } = Object; // eslint-disable-line import/no-mutable-exports\n let {\n apply,\n construct\n } = typeof Reflect !== 'undefined' && Reflect;\n if (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n }\n if (!seal) {\n seal = function seal(x) {\n return x;\n };\n }\n if (!apply) {\n apply = function apply(fun, thisValue, args) {\n return fun.apply(thisValue, args);\n };\n }\n if (!construct) {\n construct = function construct(Func, args) {\n return new Func(...args);\n };\n }\n const arrayForEach = unapply(Array.prototype.forEach);\n const arrayPop = unapply(Array.prototype.pop);\n const arrayPush = unapply(Array.prototype.push);\n const stringToLowerCase = unapply(String.prototype.toLowerCase);\n const stringToString = unapply(String.prototype.toString);\n const stringMatch = unapply(String.prototype.match);\n const stringReplace = unapply(String.prototype.replace);\n const stringIndexOf = unapply(String.prototype.indexOf);\n const stringTrim = unapply(String.prototype.trim);\n const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\n const regExpTest = unapply(RegExp.prototype.test);\n const typeErrorCreate = unconstruct(TypeError);\n function numberIsNaN(x) {\n // eslint-disable-next-line unicorn/prefer-number-properties\n return typeof x === 'number' && isNaN(x);\n }\n\n /**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param {Function} func - The function to be wrapped and called.\n * @returns {Function} A new function that calls the given function with a specified thisArg and arguments.\n */\n function unapply(func) {\n return function (thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n return apply(func, thisArg, args);\n };\n }\n\n /**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param {Function} func - The constructor function to be wrapped and called.\n * @returns {Function} A new function that constructs an instance of the given constructor function with the provided arguments.\n */\n function unconstruct(func) {\n return function () {\n for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n return construct(func, args);\n };\n }\n\n /**\n * Add properties to a lookup table\n *\n * @param {Object} set - The set to which elements will be added.\n * @param {Array} array - The array containing elements to be added to the set.\n * @param {Function} transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns {Object} The modified set with added elements.\n */\n function addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n }\n\n /**\n * Clean up an array to harden against CSPP\n *\n * @param {Array} array - The array to be cleaned.\n * @returns {Array} The cleaned version of the array\n */\n function cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n }\n\n /**\n * Shallow clone an object\n *\n * @param {Object} object - The object to be cloned.\n * @returns {Object} A new object that copies the original.\n */\n function clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n }\n\n /**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param {Object} object - The object to look up the getter function in its prototype chain.\n * @param {String} prop - The property name for which to find the getter function.\n * @returns {Function} The getter function found in the prototype chain or a fallback function.\n */\n function lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n }\n\n const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n\n // SVG\n const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n\n // List of SVG elements that are disallowed by default.\n // We still need to know them so that we can do namespace\n // checks properly in case one wants to add them to\n // allow-list.\n const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n\n // Similarly to SVG, we want to know all MathML elements,\n // even those that we disallow by default.\n const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n const text = freeze(['#text']);\n\n const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\n const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n // eslint-disable-next-line unicorn/better-regex\n const MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\n const ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\n const TMPLIT_EXPR = seal(/\\${[\\w\\W]*}/gm);\n const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\n const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\n const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n );\n\n const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\n const ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n );\n\n const DOCTYPE_NAME = seal(/^html$/i);\n const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\n var EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n ERB_EXPR: ERB_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR,\n DATA_ATTR: DATA_ATTR,\n ARIA_ATTR: ARIA_ATTR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n DOCTYPE_NAME: DOCTYPE_NAME,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT\n });\n\n // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n const NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n };\n\n const getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n };\n\n /**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param {TrustedTypePolicyFactory} trustedTypes The policy factory.\n * @param {HTMLScriptElement} purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return {TrustedTypePolicy} The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\n const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n };\n function createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n\n /**\n * Version label, exposed for easier checks\n * if DOMPurify is up to date or not\n */\n DOMPurify.version = '3.1.4';\n\n /**\n * Array of elements that DOMPurify removed during sanitation.\n * Empty if nothing was removed.\n */\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = {};\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n\n /*\n * Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n\n /* Specify the maximum element nesting depth to prevent mXSS */\n const MAX_NESTING_DEPTH = 255;\n\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n\n /**\n * _parseConfig\n *\n * @param {Object} cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES),\n // eslint-disable-line indent\n cfg.ADD_URI_SAFE_ATTR,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS),\n // eslint-disable-line indent\n cfg.ADD_DATA_URI_TAGS,\n // eslint-disable-line indent\n transformCaseFunc // eslint-disable-line indent\n ) // eslint-disable-line indent\n : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : {};\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n const MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n const HTML_INTEGRATION_POINTS = addToSet({}, ['foreignobject', 'annotation-xml']);\n\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n\n /**\n * @param {Element} element a DOM element whose namespace is being checked\n * @returns {boolean} Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either <annotation-xml> or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n\n /**\n * _forceRemove\n *\n * @param {Node} node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n node.parentNode.removeChild(node);\n } catch (_) {\n node.remove();\n }\n };\n\n /**\n * _removeAttribute\n *\n * @param {String} name an Attribute name\n * @param {Node} node a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, node) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: node.getAttributeNode(name),\n from: node\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: node\n });\n }\n node.removeAttribute(name);\n\n // We void attribute values for unremovable \"is\"\" attributes\n if (name === 'is' && !ALLOWED_ATTR[name]) {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(node);\n } catch (_) {}\n } else {\n try {\n node.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n\n /**\n * _initDocument\n *\n * @param {String} dirty a string of dirty markup\n * @return {Document} a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param {Node} root The root element or node to start traversing on.\n * @return {NodeIterator} The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n\n /**\n * _isClobbered\n *\n * @param {Node} elm element to check for clobbering attacks\n * @return {Boolean} true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(elm) {\n return elm instanceof HTMLFormElement && (\n // eslint-disable-next-line unicorn/no-typeof-undefined\n typeof elm.__depth !== 'undefined' && typeof elm.__depth !== 'number' ||\n // eslint-disable-next-line unicorn/no-typeof-undefined\n typeof elm.__removalCount !== 'undefined' && typeof elm.__removalCount !== 'number' || typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');\n };\n\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param {Node} object object to check whether it's a DOM node\n * @return {Boolean} true is object is a DOM node\n */\n const _isNode = function _isNode(object) {\n return typeof Node === 'function' && object instanceof Node;\n };\n\n /**\n * _executeHook\n * Execute user configurable hooks\n *\n * @param {String} entryPoint Name of the hook's entry point\n * @param {Node} currentNode node to work on with the hook\n * @param {Object} data additional hook parameters\n */\n const _executeHook = function _executeHook(entryPoint, currentNode, data) {\n if (!hooks[entryPoint]) {\n return;\n }\n arrayForEach(hooks[entryPoint], hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n };\n\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n *\n * @param {Node} currentNode to check for permission to exist\n * @return {Boolean} true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeElements', currentNode, null);\n\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n\n /* Execute a hook if present */\n _executeHook('uponSanitizeElement', currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n\n /* Detect mXSS attempts abusing namespace confusion */\n if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w]/g, currentNode.innerHTML) && regExpTest(/<[/\\w]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any ocurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeElements', currentNode, null);\n return false;\n };\n\n /**\n * _isValidAttribute\n *\n * @param {string} lcTag Lowercase tag name of containing element.\n * @param {string} lcName Lowercase attribute name.\n * @param {string} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement || value === '__depth' || value === '__removalCount')) {\n return false;\n }\n\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param {string} tagName name of the tag of the node to sanitize\n * @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param {Node} currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHook('beforeSanitizeAttributes', currentNode, null);\n const {\n attributes\n } = currentNode;\n\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR\n };\n let l = attributes.length;\n\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n let value = name === 'value' ? attrValue : stringTrim(attrValue);\n\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHook('uponSanitizeAttribute', currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n\n /* Remove attribute */\n _removeAttribute(name, currentNode);\n\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n continue;\n }\n\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {}\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeAttributes', currentNode, null);\n };\n\n /**\n * _sanitizeShadowDOM\n *\n * @param {DocumentFragment} fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeShadowDOM', fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHook('uponSanitizeShadowNode', shadowNode, null);\n\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n const parentNode = getParentNode(shadowNode);\n\n /* Set the nesting depth of an element */\n if (shadowNode.nodeType === NODE_TYPE.element) {\n if (parentNode && parentNode.__depth) {\n /*\n We want the depth of the node in the original tree, which can\n change when it's removed from its parent.\n */\n shadowNode.__depth = (shadowNode.__removalCount || 0) + parentNode.__depth + 1;\n } else {\n shadowNode.__depth = 1;\n }\n }\n\n /*\n * Remove an element if nested too deeply to avoid mXSS\n * or if the __depth might have been tampered with\n */\n if (shadowNode.__depth >= MAX_NESTING_DEPTH || shadowNode.__depth < 0 || numberIsNaN(shadowNode.__depth)) {\n _forceRemove(shadowNode);\n }\n\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n shadowNode.content.__depth = shadowNode.__depth;\n _sanitizeShadowDOM(shadowNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeShadowDOM', fragment, null);\n };\n\n /**\n * Sanitize\n * Public method providing core sanitation functionality\n *\n * @param {String|Node} dirty string or DOM node\n * @param {Object} cfg object\n */\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n\n /* Clean up removed elements */\n DOMPurify.removed = [];\n\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n const parentNode = getParentNode(currentNode);\n\n /* Set the nesting depth of an element */\n if (currentNode.nodeType === NODE_TYPE.element) {\n if (parentNode && parentNode.__depth) {\n /*\n We want the depth of the node in the original tree, which can\n change when it's removed from its parent.\n */\n currentNode.__depth = (currentNode.__removalCount || 0) + parentNode.__depth + 1;\n } else {\n currentNode.__depth = 1;\n }\n }\n\n /*\n * Remove an element if nested too deeply to avoid mXSS\n * or if the __depth might have been tampered with\n */\n if (currentNode.__depth >= MAX_NESTING_DEPTH || currentNode.__depth < 0 || numberIsNaN(currentNode.__depth)) {\n _forceRemove(currentNode);\n }\n\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n currentNode.content.__depth = currentNode.__depth;\n _sanitizeShadowDOM(currentNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n }\n\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n\n /**\n * Public method to set the configuration once\n * setConfig\n *\n * @param {Object} cfg configuration object\n */\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n\n /**\n * Public method to remove the configuration\n * clearConfig\n *\n */\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n\n /**\n * Public method to check if an attribute value is valid.\n * Uses last set config, if any. Otherwise, uses config defaults.\n * isValidAttribute\n *\n * @param {String} tag Tag name of containing element.\n * @param {String} attr Attribute name.\n * @param {String} value Attribute value.\n * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.\n */\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n\n /**\n * AddHook\n * Public method to add DOMPurify hooks\n *\n * @param {String} entryPoint entry point for the hook to add\n * @param {Function} hookFunction function to execute\n */\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n hooks[entryPoint] = hooks[entryPoint] || [];\n arrayPush(hooks[entryPoint], hookFunction);\n };\n\n /**\n * RemoveHook\n * Public method to remove a DOMPurify hook at a given entryPoint\n * (pops it from the stack of hooks if more are present)\n *\n * @param {String} entryPoint entry point for the hook to remove\n * @return {Function} removed(popped) hook\n */\n DOMPurify.removeHook = function (entryPoint) {\n if (hooks[entryPoint]) {\n return arrayPop(hooks[entryPoint]);\n }\n };\n\n /**\n * RemoveHooks\n * Public method to remove all DOMPurify hooks at a given entryPoint\n *\n * @param {String} entryPoint entry point for the hooks to remove\n */\n DOMPurify.removeHooks = function (entryPoint) {\n if (hooks[entryPoint]) {\n hooks[entryPoint] = [];\n }\n };\n\n /**\n * RemoveAllHooks\n * Public method to remove all DOMPurify hooks\n */\n DOMPurify.removeAllHooks = function () {\n hooks = {};\n };\n return DOMPurify;\n }\n var purify = createDOMPurify();\n\n return purify;\n\n}));\n//# sourceMappingURL=purify.js.map\n\n\n//# sourceURL=webpack://Formio/./node_modules/dompurify/dist/purify.js?");
2872
2882
 
2873
2883
  /***/ }),
2874
2884
 
@@ -5487,7 +5497,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n// A
5487
5497
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5488
5498
 
5489
5499
  "use strict";
5490
- eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst i18n_1 = __webpack_require__(/*! ./utils/i18n */ \"./lib/cjs/utils/i18n.js\");\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 vanilla_text_mask_1 = __importDefault(__webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\"));\n/**\n * The root component for all elements within the Form.io renderer.\n */\nclass Element {\n constructor(options) {\n var _a;\n /**\n * The options for this component.\n * @type {{}}\n */\n this.options = Object.assign({\n language: 'en',\n highlightErrors: true,\n componentErrorClass: 'formio-error-wrapper',\n componentWarningClass: 'formio-warning-wrapper',\n row: '',\n namespace: 'formio'\n }, options || {});\n /**\n * The ID of this component. This value is auto-generated when the component is created, but\n * can also be provided from the component.id value passed into the constructor.\n * @type {string}\n */\n this.id = FormioUtils.getRandomComponentId();\n /**\n * An array of event handlers so that the destry command can deregister them.\n * @type {Array}\n */\n this.eventHandlers = [];\n // Use the i18next that is passed in, otherwise use the global version.\n this.options.i18n = this.options.i18n || {};\n if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.language) {\n this.options.i18n.language = this.options.language;\n }\n this.options.i18next = this.i18next = this.options.i18next || i18n_1.I18n.init(this.options.i18n);\n /**\n * An instance of the EventEmitter class to handle the emitting and registration of events.\n *\n * @type {EventEmitter}\n */\n this.events = (options && options.events) ? options.events : new EventEmitter_1.default();\n this.defaultMask = null;\n /**\n * Conditional to show or hide helplinks in editForm\n *\n * @type {*|boolean}\n */\n this.helplinks = (this.options.helplinks === 'false') ? false : (this.options.helplinks || 'https://help.form.io');\n }\n /**\n * Register for a new event within this component.\n *\n * @example\n * let component = new BaseComponent({\n * type: 'textfield',\n * label: 'First Name',\n * key: 'firstName'\n * });\n * component.on('componentChange', (changed) => {\n * console.log('this element is changed.');\n * });\n *\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function} cb - The callback handler to handle this event.\n * @param {boolean} [internal] - This is an internal event handler.\n * @param {boolean} [once] - This event should only fire once.\n */\n on(event, cb, internal, once = false) {\n if (!this.events) {\n return;\n }\n const type = `${this.options.namespace}.${event}`;\n // Store the component id in the handler so that we can determine which events are for this component.\n cb.id = this.id;\n cb.key = this.key;\n cb.internal = internal;\n // Register for this event.\n return this.events[once ? 'once' : 'on'](type, cb);\n }\n /**\n * Register for a new single-fire event within this component.\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function} cb - The callback handler to handle this event.\n */\n once(event, cb, internal) {\n return this.on(event, cb, internal, true);\n }\n /**\n * Allow catching any event.\n *\n * @param cb\n * @returns {this}\n */\n onAny(cb) {\n if (!this.events) {\n return;\n }\n return this.events.onAny(cb);\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @param cb\n * @returns {this}\n */\n offAny(cb) {\n if (!this.events) {\n return;\n }\n return this.events.offAny(cb);\n }\n /**\n * Removes a listener for a certain event. Not passing the 2nd arg will remove all listeners for that event.\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function|undefined} cb - The callback handler to handle this event.\n */\n off(event, cb) {\n if (!this.events) {\n return;\n }\n const type = `${this.options.namespace}.${event}`;\n this.events.listeners(type).forEach((listener) => {\n // Ensure the listener is for this element\n if (!listener || listener.id !== this.id) {\n return;\n }\n // If there is a given callback, only deal with the match\n if (cb && cb !== listener) {\n return;\n }\n this.events.off(type, listener);\n });\n }\n /**\n * Emit a new event.\n *\n * @param {string} event - The event to emit.\n * @param {Object} data - The data to emit with the handler.\n */\n emit(event, ...data) {\n if (this.events) {\n this.events.emit(`${this.options.namespace}.${event}`, ...data);\n }\n }\n /**\n * Check if the component has an event handler set up for the event.\n *\n * @param {string} event - The event name.\n * @returns {boolean}\n */\n hasEventHandler(event) {\n if (!this.events) {\n return false;\n }\n const type = `${this.options.namespace}.${event}`;\n return this.events.listeners(type).some((listener) => {\n if (!listener) {\n return false;\n }\n return listener.id === this.id || listener.key === this.key;\n });\n }\n /**\n * Wrapper method to add an event listener to an HTML element.\n *\n * @param obj\n * The DOM element to add the event to.\n * @param type\n * The event name to add.\n * @param func\n * The callback function to be executed when the listener is triggered.\n * @param persistent\n * If this listener should persist beyond \"destroy\" commands.\n */\n addEventListener(obj, type, func, persistent, capture) {\n if (!obj) {\n return;\n }\n if (!persistent) {\n this.eventHandlers.push({ id: this.id, obj, type, func });\n }\n if ('addEventListener' in obj) {\n obj.addEventListener(type, func, !!capture);\n }\n else if ('attachEvent' in obj) {\n obj.attachEvent(`on${type}`, func);\n }\n return this;\n }\n /**\n * Remove an event listener from the object.\n *\n * @param obj\n * @param type\n */\n removeEventListener(obj, type, func = null) {\n const indexes = [];\n if (!obj) {\n return;\n }\n this.eventHandlers.forEach((handler, index) => {\n if ((handler.id === this.id)\n && obj.removeEventListener\n && (handler.type === type)\n && (!func || handler.func === func)) {\n obj.removeEventListener(type, handler.func);\n indexes.push(index);\n }\n });\n if (indexes.length) {\n lodash_1.default.pullAt(this.eventHandlers, indexes);\n }\n return this;\n }\n removeEventListeners() {\n this.eventHandlers.forEach(handler => {\n if ((this.id === handler.id) && handler.type && handler.obj && handler.obj.removeEventListener) {\n handler.obj.removeEventListener(handler.type, handler.func);\n }\n });\n this.eventHandlers = [];\n }\n removeAllEvents(includeExternal) {\n lodash_1.default.each(this.events._events, (events, type) => {\n lodash_1.default.each(events, (listener) => {\n if (listener && (this.id === listener.id) && (includeExternal || listener.internal)) {\n this.events.off(type, listener);\n }\n });\n });\n }\n /**\n * Removes all event listeners attached to this component.\n */\n destroy() {\n this.removeEventListeners();\n this.removeAllEvents();\n }\n /**\n * Append an HTML DOM element to a container.\n *\n * @param element\n * @param container\n */\n appendTo(element, container) {\n container === null || container === void 0 ? void 0 : container.appendChild(element);\n return this;\n }\n /**\n * Prepend an HTML DOM element to a container.\n *\n * @param {HTMLElement} element - The DOM element to prepend.\n * @param {HTMLElement} container - The DOM element that is the container of the element getting prepended.\n */\n prependTo(element, container) {\n if (container) {\n if (container.firstChild) {\n try {\n container.insertBefore(element, container.firstChild);\n }\n catch (err) {\n console.warn(err);\n container.appendChild(element);\n }\n }\n else {\n container.appendChild(element);\n }\n }\n return this;\n }\n /**\n * Removes an HTML DOM element from its bounding container.\n *\n * @param {HTMLElement} element - The element to remove.\n * @param {HTMLElement} container - The DOM element that is the container of the element to remove.\n */\n removeChildFrom(element, container) {\n if (container && container.contains(element)) {\n try {\n container.removeChild(element);\n }\n catch (err) {\n console.warn(err);\n }\n }\n return this;\n }\n /**\n * Alias for document.createElement.\n *\n * @param {string} type - The type of element to create\n * @param {Object} attr - The element attributes to add to the created element.\n * @param {Various} children - Child elements. Can be a DOM Element, string or array of both.\n *\n * @return {HTMLElement} - The created element.\n */\n ce(type, attr, children = null) {\n // console.warn('Call to deprecated this.ce(). Dom elements should be created with templates, not manually with ce.');\n // Create the element.\n const element = document.createElement(type);\n // Add attributes.\n if (attr) {\n this.attr(element, attr);\n }\n // Append the children.\n this.appendChild(element, children);\n return element;\n }\n /**\n * Append different types of children.\n *\n * @param child\n */\n appendChild(element, child) {\n if (Array.isArray(child)) {\n child.forEach((oneChild) => this.appendChild(element, oneChild));\n }\n else if (child instanceof HTMLElement || child instanceof Text) {\n element.appendChild(child);\n }\n else if (child) {\n element.appendChild(this.text(child.toString()));\n }\n return this;\n }\n /**\n * Creates a new input mask placeholder.\n * @param {HTMLElement} mask - The input mask.\n * @returns {string} - The placeholder that will exist within the input as they type.\n */\n maskPlaceholder(mask) {\n return mask.map((char) => (char instanceof RegExp) ? this.placeholderChar : char).join('');\n }\n get placeholderChar() {\n var _a;\n return ((_a = this.component) === null || _a === void 0 ? void 0 : _a.inputMaskPlaceholderChar) || '_';\n }\n /**\n * Sets the input mask for an input.\n *\n * @param {HTMLElement} input - The html input to apply the mask to.\n * @param {String} inputMask - The input mask to add to this input.\n * @param {Boolean} usePlaceholder - Set the mask placeholder on the input.\n */\n setInputMask(input, inputMask, usePlaceholder) {\n if (input && inputMask) {\n const mask = FormioUtils.getInputMask(inputMask, this.placeholderChar);\n this.defaultMask = mask;\n try {\n //destroy previous mask\n if (input.mask) {\n input.mask.destroy();\n }\n input.mask = (0, vanilla_text_mask_1.default)({\n inputElement: input,\n mask,\n placeholderChar: this.placeholderChar,\n shadowRoot: this.root ? this.root.shadowRoot : null\n });\n }\n catch (e) {\n // Don't pass error up, to prevent form rejection.\n // Internal bug of vanilla-text-mask on iOS (`selectionEnd`);\n console.warn(e);\n }\n if (mask.numeric) {\n input.setAttribute('pattern', '\\\\d*');\n }\n if (usePlaceholder) {\n input.setAttribute('placeholder', this.maskPlaceholder(mask));\n }\n }\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string|Array<string>} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, ...args) {\n return this.i18next.t(text, ...args);\n }\n /**\n * Alias to create a text node.\n * @param text\n * @returns {Text}\n */\n text(text) {\n return document.createTextNode(this.t(text));\n }\n /**\n * Adds an object of attributes onto an element.\n * @param {HtmlElement} element - The element to add the attributes to.\n * @param {Object} attr - The attributes to add to the input element.\n */\n attr(element, attr) {\n if (!element) {\n return;\n }\n lodash_1.default.each(attr, (value, key) => {\n if (typeof value !== 'undefined') {\n if (key.indexOf('on') === 0) {\n // If this is an event, add a listener.\n this.addEventListener(element, key.substr(2).toLowerCase(), value);\n }\n else {\n // Otherwise it is just an attribute.\n element.setAttribute(key, value);\n }\n }\n });\n }\n /**\n * Determines if an element has a class.\n *\n * Taken from jQuery https://j11y.io/jquery/#v=1.5.0&fn=jQuery.fn.hasClass\n */\n hasClass(element, className) {\n if (!element) {\n return false;\n }\n // Allow templates to intercept.\n className = ` ${className} `;\n return ((` ${element.className} `).replace(/[\\n\\t\\r]/g, ' ').indexOf(className) > -1);\n }\n /**\n * Adds a class to a DOM element.\n *\n * @param element\n * The element to add a class to.\n * @param className\n * The name of the class to add.\n */\n addClass(element, className) {\n if (!element || !(element instanceof HTMLElement)) {\n return this;\n }\n // Allow templates to intercept.\n const classes = element.getAttribute('class');\n if (!(classes === null || classes === void 0 ? void 0 : classes.includes(className))) {\n element.setAttribute('class', `${classes} ${className}`);\n }\n return this;\n }\n /**\n * Remove a class from a DOM element.\n *\n * @param element\n * The DOM element to remove the class from.\n * @param className\n * The name of the class that is to be removed.\n */\n removeClass(element, className) {\n if (!element || !className || !(element instanceof HTMLElement)) {\n return this;\n }\n // Allow templates to intercept.\n let cls = element.getAttribute('class');\n if (cls) {\n cls = cls.replace(new RegExp(` ${className}`, 'g'), '');\n element.setAttribute('class', cls);\n }\n return this;\n }\n /**\n * Empty's an HTML DOM element.\n *\n * @param {HTMLElement} element - The element you wish to empty.\n */\n empty(element) {\n if (element) {\n while (element.firstChild) {\n element.removeChild(element.firstChild);\n }\n }\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n var _a;\n return Object.assign({\n _: lodash_1.default,\n utils: FormioUtils,\n util: FormioUtils,\n user: Formio_1.Formio.getUser(),\n moment: moment_1.default,\n instance: this,\n self: this,\n token: Formio_1.Formio.getToken({\n decode: true\n }),\n options: this.options,\n config: this.root && this.root.form && this.root.form.config\n ? this.root.form.config\n : ((_a = this.options) === null || _a === void 0 ? void 0 : _a.formConfig)\n ? this.options.formConfig\n : {},\n }, additional, lodash_1.default.get(this.root, 'options.evalContext', {}));\n }\n /**\n * Performs an interpolation using the evaluation context of this component.\n *\n * @param string\n * @param data\n * @return {XML|string|*|void}\n */\n interpolate(string, data, options = {}) {\n if (typeof string !== 'function' && (this.component.content || this.component.html)\n && !FormioUtils.Evaluator.templateSettings.interpolate.test(string)) {\n string = FormioUtils.translateHTMLTemplate(String(string), (value) => this.t(value));\n }\n if (this.component.filter === string && !this.options.building) {\n const evalContext = this.evalContext(data);\n evalContext.data = lodash_1.default.mapValues(evalContext.data, (val) => lodash_1.default.isString(val) ? encodeURIComponent(val) : val);\n return FormioUtils.interpolate(string, evalContext, options);\n }\n return FormioUtils.interpolate(string, this.evalContext(data), options);\n }\n /**\n * Performs an evaluation using the evaluation context of this component.\n *\n * @param func\n * @param args\n * @param ret\n * @param tokenize\n * @return {*}\n */\n evaluate(func, args, ret, tokenize) {\n return FormioUtils.evaluate(func, this.evalContext(args), ret, tokenize);\n }\n /**\n * Allow for options to hook into the functionality of this renderer.\n * @return {*}\n */\n hook() {\n const name = arguments[0];\n if (this.options &&\n this.options.hooks &&\n this.options.hooks[name]) {\n return this.options.hooks[name].apply(this, Array.prototype.slice.call(arguments, 1));\n }\n else {\n // If this is an async hook instead of a sync.\n const fn = (typeof arguments[arguments.length - 1] === 'function') ? arguments[arguments.length - 1] : null;\n if (fn) {\n return fn(null, arguments[1]);\n }\n else {\n return arguments[1];\n }\n }\n }\n}\nexports[\"default\"] = Element;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Element.js?");
5500
+ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nconst i18n_1 = __webpack_require__(/*! ./utils/i18n */ \"./lib/cjs/utils/i18n.js\");\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 vanilla_text_mask_1 = __importDefault(__webpack_require__(/*! @formio/vanilla-text-mask */ \"./node_modules/@formio/vanilla-text-mask/dist/vanillaTextMask.js\"));\n/**\n * The root component for all elements within the Form.io renderer.\n */\nclass Element {\n constructor(options) {\n var _a;\n /**\n * The options for this component.\n * @type {{}}\n */\n this.options = Object.assign({\n language: 'en',\n highlightErrors: true,\n componentErrorClass: 'formio-error-wrapper',\n componentWarningClass: 'formio-warning-wrapper',\n row: '',\n namespace: 'formio'\n }, options || {});\n /**\n * The ID of this component. This value is auto-generated when the component is created, but\n * can also be provided from the component.id value passed into the constructor.\n * @type {string}\n */\n this.id = FormioUtils.getRandomComponentId();\n /**\n * An array of event handlers so that the destry command can deregister them.\n * @type {Array}\n */\n this.eventHandlers = [];\n // Use the i18next that is passed in, otherwise use the global version.\n this.options.i18n = this.options.i18n || {};\n if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.language) {\n this.options.i18n.language = this.options.language;\n }\n this.options.i18next = this.i18next = this.options.i18next || i18n_1.I18n.init(this.options.i18n);\n /**\n * An instance of the EventEmitter class to handle the emitting and registration of events.\n *\n * @type {EventEmitter}\n */\n this.events = (options && options.events) ? options.events : new EventEmitter_1.default();\n this.defaultMask = null;\n /**\n * Conditional to show or hide helplinks in editForm\n *\n * @type {*|boolean}\n */\n this.helplinks = (this.options.helplinks === 'false') ? false : (this.options.helplinks || 'https://help.form.io');\n }\n /**\n * Register for a new event within this component.\n *\n * @example\n * let component = new BaseComponent({\n * type: 'textfield',\n * label: 'First Name',\n * key: 'firstName'\n * });\n * component.on('componentChange', (changed) => {\n * console.log('this element is changed.');\n * });\n *\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function} cb - The callback handler to handle this event.\n * @param {boolean} [internal] - This is an internal event handler.\n * @param {boolean} [once] - This event should only fire once.\n */\n on(event, cb, internal, once = false) {\n if (!this.events) {\n return;\n }\n const type = `${this.options.namespace}.${event}`;\n // Store the component id in the handler so that we can determine which events are for this component.\n cb.id = this.id;\n cb.key = this.key;\n cb.internal = internal;\n // Register for this event.\n return this.events[once ? 'once' : 'on'](type, cb);\n }\n /**\n * Register for a new single-fire event within this component.\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function} cb - The callback handler to handle this event.\n */\n once(event, cb, internal) {\n return this.on(event, cb, internal, true);\n }\n /**\n * Allow catching any event.\n *\n * @param cb\n * @returns {this}\n */\n onAny(cb) {\n if (!this.events) {\n return;\n }\n return this.events.onAny(cb);\n }\n /**\n * Removes the listener that will be fired when any event is emitted.\n *\n * @param cb\n * @returns {this}\n */\n offAny(cb) {\n if (!this.events) {\n return;\n }\n return this.events.offAny(cb);\n }\n /**\n * Removes a listener for a certain event. Not passing the 2nd arg will remove all listeners for that event.\n *\n * @param {string} event - The event you wish to register the handler for.\n * @param {function|undefined} cb - The callback handler to handle this event.\n */\n off(event, cb) {\n if (!this.events) {\n return;\n }\n const type = `${this.options.namespace}.${event}`;\n this.events.listeners(type).forEach((listener) => {\n // Ensure the listener is for this element\n if (!listener || listener.id !== this.id) {\n return;\n }\n // If there is a given callback, only deal with the match\n if (cb && cb !== listener) {\n return;\n }\n this.events.off(type, listener);\n });\n }\n /**\n * Emit a new event.\n *\n * @param {string} event - The event to emit.\n * @param {Object} data - The data to emit with the handler.\n */\n emit(event, ...data) {\n if (this.events) {\n this.events.emit(`${this.options.namespace}.${event}`, ...data);\n }\n }\n /**\n * Check if the component has an event handler set up for the event.\n *\n * @param {string} event - The event name.\n * @returns {boolean}\n */\n hasEventHandler(event) {\n if (!this.events) {\n return false;\n }\n const type = `${this.options.namespace}.${event}`;\n return this.events.listeners(type).some((listener) => {\n if (!listener) {\n return false;\n }\n return listener.id === this.id || listener.key === this.key;\n });\n }\n /**\n * Wrapper method to add an event listener to an HTML element.\n *\n * @param obj\n * The DOM element to add the event to.\n * @param type\n * The event name to add.\n * @param func\n * The callback function to be executed when the listener is triggered.\n * @param persistent\n * If this listener should persist beyond \"destroy\" commands.\n */\n addEventListener(obj, type, func, persistent, capture) {\n if (!obj) {\n return;\n }\n if (!persistent) {\n this.eventHandlers.push({ id: this.id, obj, type, func });\n }\n if ('addEventListener' in obj) {\n obj.addEventListener(type, func, !!capture);\n }\n else if ('attachEvent' in obj) {\n obj.attachEvent(`on${type}`, func);\n }\n return this;\n }\n /**\n * Remove an event listener from the object.\n *\n * @param obj\n * @param type\n */\n removeEventListener(obj, type, func = null) {\n const indexes = [];\n if (!obj) {\n return;\n }\n this.eventHandlers.forEach((handler, index) => {\n if ((handler.id === this.id)\n && obj.removeEventListener\n && (handler.type === type)\n && (!func || handler.func === func)) {\n obj.removeEventListener(type, handler.func);\n indexes.push(index);\n }\n });\n if (indexes.length) {\n lodash_1.default.pullAt(this.eventHandlers, indexes);\n }\n return this;\n }\n removeEventListeners() {\n this.eventHandlers.forEach(handler => {\n if ((this.id === handler.id) && handler.type && handler.obj && handler.obj.removeEventListener) {\n handler.obj.removeEventListener(handler.type, handler.func);\n }\n });\n this.eventHandlers = [];\n }\n removeAllEvents(includeExternal) {\n if (this.events) {\n lodash_1.default.each(this.events._events, (events, type) => {\n lodash_1.default.each(events, (listener) => {\n if (listener && (this.id === listener.id) && (includeExternal || listener.internal)) {\n this.events.off(type, listener);\n }\n });\n });\n }\n }\n teardown() {\n delete this.i18next;\n delete this.events;\n }\n /**\n * Removes all event listeners attached to this component.\n */\n destroy(all = false) {\n this.removeEventListeners();\n this.removeAllEvents();\n if (all) {\n this.teardown();\n }\n }\n /**\n * Append an HTML DOM element to a container.\n *\n * @param element\n * @param container\n */\n appendTo(element, container) {\n container === null || container === void 0 ? void 0 : container.appendChild(element);\n return this;\n }\n /**\n * Prepend an HTML DOM element to a container.\n *\n * @param {HTMLElement} element - The DOM element to prepend.\n * @param {HTMLElement} container - The DOM element that is the container of the element getting prepended.\n */\n prependTo(element, container) {\n if (container) {\n if (container.firstChild) {\n try {\n container.insertBefore(element, container.firstChild);\n }\n catch (err) {\n console.warn(err);\n container.appendChild(element);\n }\n }\n else {\n container.appendChild(element);\n }\n }\n return this;\n }\n /**\n * Removes an HTML DOM element from its bounding container.\n *\n * @param {HTMLElement} element - The element to remove.\n * @param {HTMLElement} container - The DOM element that is the container of the element to remove.\n */\n removeChildFrom(element, container) {\n if (container && container.contains(element)) {\n try {\n container.removeChild(element);\n }\n catch (err) {\n console.warn(err);\n }\n }\n return this;\n }\n /**\n * Alias for document.createElement.\n *\n * @param {string} type - The type of element to create\n * @param {Object} attr - The element attributes to add to the created element.\n * @param {Various} children - Child elements. Can be a DOM Element, string or array of both.\n *\n * @return {HTMLElement} - The created element.\n */\n ce(type, attr, children = null) {\n // console.warn('Call to deprecated this.ce(). Dom elements should be created with templates, not manually with ce.');\n // Create the element.\n const element = document.createElement(type);\n // Add attributes.\n if (attr) {\n this.attr(element, attr);\n }\n // Append the children.\n this.appendChild(element, children);\n return element;\n }\n /**\n * Append different types of children.\n *\n * @param child\n */\n appendChild(element, child) {\n if (Array.isArray(child)) {\n child.forEach((oneChild) => this.appendChild(element, oneChild));\n }\n else if (child instanceof HTMLElement || child instanceof Text) {\n element.appendChild(child);\n }\n else if (child) {\n element.appendChild(this.text(child.toString()));\n }\n return this;\n }\n /**\n * Creates a new input mask placeholder.\n * @param {HTMLElement} mask - The input mask.\n * @returns {string} - The placeholder that will exist within the input as they type.\n */\n maskPlaceholder(mask) {\n return mask.map((char) => (char instanceof RegExp) ? this.placeholderChar : char).join('');\n }\n get placeholderChar() {\n var _a;\n return ((_a = this.component) === null || _a === void 0 ? void 0 : _a.inputMaskPlaceholderChar) || '_';\n }\n /**\n * Sets the input mask for an input.\n *\n * @param {HTMLElement} input - The html input to apply the mask to.\n * @param {String} inputMask - The input mask to add to this input.\n * @param {Boolean} usePlaceholder - Set the mask placeholder on the input.\n */\n setInputMask(input, inputMask, usePlaceholder) {\n if (input && inputMask) {\n const mask = FormioUtils.getInputMask(inputMask, this.placeholderChar);\n this.defaultMask = mask;\n try {\n //destroy previous mask\n if (input.mask) {\n input.mask.destroy();\n }\n input.mask = (0, vanilla_text_mask_1.default)({\n inputElement: input,\n mask,\n placeholderChar: this.placeholderChar,\n shadowRoot: this.root ? this.root.shadowRoot : null\n });\n }\n catch (e) {\n // Don't pass error up, to prevent form rejection.\n // Internal bug of vanilla-text-mask on iOS (`selectionEnd`);\n console.warn(e);\n }\n if (mask.numeric) {\n input.setAttribute('pattern', '\\\\d*');\n }\n if (usePlaceholder) {\n input.setAttribute('placeholder', this.maskPlaceholder(mask));\n }\n }\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string|Array<string>} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, ...args) {\n return this.i18next ? this.i18next.t(text, ...args) : text;\n }\n /**\n * Alias to create a text node.\n * @param text\n * @returns {Text}\n */\n text(text) {\n return document.createTextNode(this.t(text));\n }\n /**\n * Adds an object of attributes onto an element.\n * @param {HtmlElement} element - The element to add the attributes to.\n * @param {Object} attr - The attributes to add to the input element.\n */\n attr(element, attr) {\n if (!element) {\n return;\n }\n lodash_1.default.each(attr, (value, key) => {\n if (typeof value !== 'undefined') {\n if (key.indexOf('on') === 0) {\n // If this is an event, add a listener.\n this.addEventListener(element, key.substr(2).toLowerCase(), value);\n }\n else {\n // Otherwise it is just an attribute.\n element.setAttribute(key, value);\n }\n }\n });\n }\n /**\n * Determines if an element has a class.\n *\n * Taken from jQuery https://j11y.io/jquery/#v=1.5.0&fn=jQuery.fn.hasClass\n */\n hasClass(element, className) {\n if (!element) {\n return false;\n }\n // Allow templates to intercept.\n className = ` ${className} `;\n return ((` ${element.className} `).replace(/[\\n\\t\\r]/g, ' ').indexOf(className) > -1);\n }\n /**\n * Adds a class to a DOM element.\n *\n * @param element\n * The element to add a class to.\n * @param className\n * The name of the class to add.\n */\n addClass(element, className) {\n if (!element || !(element instanceof HTMLElement)) {\n return this;\n }\n // Allow templates to intercept.\n const classes = element.getAttribute('class');\n if (!(classes === null || classes === void 0 ? void 0 : classes.includes(className))) {\n element.setAttribute('class', `${classes} ${className}`);\n }\n return this;\n }\n /**\n * Remove a class from a DOM element.\n *\n * @param element\n * The DOM element to remove the class from.\n * @param className\n * The name of the class that is to be removed.\n */\n removeClass(element, className) {\n if (!element || !className || !(element instanceof HTMLElement)) {\n return this;\n }\n // Allow templates to intercept.\n let cls = element.getAttribute('class');\n if (cls) {\n cls = cls.replace(new RegExp(` ${className}`, 'g'), '');\n element.setAttribute('class', cls);\n }\n return this;\n }\n /**\n * Empty's an HTML DOM element.\n *\n * @param {HTMLElement} element - The element you wish to empty.\n */\n empty(element) {\n if (element) {\n while (element.firstChild) {\n element.removeChild(element.firstChild);\n }\n }\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n var _a;\n return Object.assign({\n _: lodash_1.default,\n utils: FormioUtils,\n util: FormioUtils,\n user: Formio_1.Formio.getUser(),\n moment: moment_1.default,\n instance: this,\n self: this,\n token: Formio_1.Formio.getToken({\n decode: true\n }),\n options: this.options,\n config: this.root && this.root.form && this.root.form.config\n ? this.root.form.config\n : ((_a = this.options) === null || _a === void 0 ? void 0 : _a.formConfig)\n ? this.options.formConfig\n : {},\n }, additional, lodash_1.default.get(this.root, 'options.evalContext', {}));\n }\n /**\n * Performs an interpolation using the evaluation context of this component.\n *\n * @param string\n * @param data\n * @return {XML|string|*|void}\n */\n interpolate(string, data, options = {}) {\n if (typeof string !== 'function' && (this.component.content || this.component.html)\n && !FormioUtils.Evaluator.templateSettings.interpolate.test(string)) {\n string = FormioUtils.translateHTMLTemplate(String(string), (value) => this.t(value));\n }\n if (this.component.filter === string && !this.options.building) {\n const evalContext = this.evalContext(data);\n evalContext.data = lodash_1.default.mapValues(evalContext.data, (val) => lodash_1.default.isString(val) ? encodeURIComponent(val) : val);\n return FormioUtils.interpolate(string, evalContext, options);\n }\n return FormioUtils.interpolate(string, this.evalContext(data), options);\n }\n /**\n * Performs an evaluation using the evaluation context of this component.\n *\n * @param func\n * @param args\n * @param ret\n * @param tokenize\n * @return {*}\n */\n evaluate(func, args, ret, tokenize) {\n return FormioUtils.evaluate(func, this.evalContext(args), ret, tokenize);\n }\n /**\n * Allow for options to hook into the functionality of this renderer.\n * @return {*}\n */\n hook() {\n const name = arguments[0];\n if (this.options &&\n this.options.hooks &&\n this.options.hooks[name]) {\n return this.options.hooks[name].apply(this, Array.prototype.slice.call(arguments, 1));\n }\n else {\n // If this is an async hook instead of a sync.\n const fn = (typeof arguments[arguments.length - 1] === 'function') ? arguments[arguments.length - 1] : null;\n if (fn) {\n return fn(null, arguments[1]);\n }\n else {\n return arguments[1];\n }\n }\n }\n}\nexports[\"default\"] = Element;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Element.js?");
5491
5501
 
5492
5502
  /***/ }),
5493
5503
 
@@ -5509,7 +5519,7 @@ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ?
5509
5519
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5510
5520
 
5511
5521
  "use strict";
5512
- eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Element_1 = __importDefault(__webpack_require__(/*! ./Element */ \"./lib/cjs/Element.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst displays_1 = __importDefault(__webpack_require__(/*! ./displays */ \"./lib/cjs/displays/index.js\"));\nconst templates_1 = __importDefault(__webpack_require__(/*! ./templates */ \"./lib/cjs/templates/index.js\"));\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nclass Form extends Element_1.default {\n /**\n * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n *\n * @param {Object} element - The DOM element you wish to render this form within.\n * @param {Object | string} form - Either a Form JSON schema or the URL of a hosted form via. form.io.\n * @param {Object} options - The options to create a new form instance.\n * @param {boolean} options.readOnly - Set this form to readOnly\n * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog.\n * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js\n * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form.\n *\n * @example\n * import Form from '@formio/js/Form';\n * const form = new Form(document.getElementById('formio'), 'https://examples.form.io/example');\n * form.build();\n */\n constructor(...args) {\n let options = args[0] instanceof HTMLElement ? args[2] : args[1];\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n options = Object.assign(options, Formio_1.Formio.options.form);\n }\n super(options);\n if (this.options.useSessionToken) {\n Formio_1.Formio.useSessionToken(this.options);\n }\n this.ready = new Promise((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n this.instance = null;\n if (args[0] instanceof HTMLElement) {\n this.element = args[0];\n this.options = args[2] || {};\n this.options.events = this.events;\n this.setForm(args[1])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else if (args[0]) {\n this.element = null;\n this.options = args[1] || {};\n this.options.events = this.events;\n this.setForm(args[0])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else {\n this.element = null;\n this.options = {};\n this.options.events = this.events;\n }\n this.display = '';\n }\n createElement(tag, attrs, children) {\n const element = document.createElement(tag);\n for (const attr in attrs) {\n if (attrs.hasOwnProperty(attr)) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n (children || []).forEach(child => {\n element.appendChild(this.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n set loading(load) {\n if (!this.element || this.options.noLoader) {\n return;\n }\n if (load) {\n if (this.loader) {\n return;\n }\n this.loader = this.createElement('div', {\n 'class': 'formio-loader'\n }, [{\n tag: 'div',\n attrs: {\n class: 'loader-wrapper'\n },\n children: [{\n tag: 'div',\n attrs: {\n class: 'loader text-center'\n }\n }]\n }]);\n this.element.appendChild(this.loader);\n }\n else if (this.loader) {\n if (this.element.contains(this.loader)) {\n this.element.removeChild(this.loader);\n }\n this.loader = null;\n }\n }\n /**\n * Create a new form instance provided the display of the form.\n *\n * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @return {*}\n */\n create(display) {\n if (this.options && (this.options.flatten || this.options.renderMode === 'flat')) {\n display = 'form';\n }\n this.display = display;\n if (displays_1.default.displays[display]) {\n return new displays_1.default.displays[display](this.element, this.options);\n }\n else {\n // eslint-disable-next-line new-cap\n return new displays_1.default.displays['webform'](this.element, this.options);\n }\n }\n /**\n * Sets the form. Either as JSON or a URL to a form JSON schema.\n *\n * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @return {*}\n */\n set form(formParam) {\n return this.setForm(formParam);\n }\n errorForm(err) {\n return {\n components: [\n {\n 'label': 'HTML',\n 'tag': 'div',\n 'className': 'error error-message alert alert-danger ui red message',\n 'attrs': [\n {\n 'attr': 'role',\n 'value': 'alert'\n }\n ],\n 'key': 'errorMessage',\n 'type': 'htmlelement',\n 'input': false,\n 'content': typeof err === 'string' ? err : err.message,\n }\n ]\n };\n }\n /**\n * Check Subdirectories path and provide correct options\n *\n * @param {string} url - The the URL of the form json.\n * @param {form} object - The form json.\n * @return {object} The initial options with base and project.\n */\n getFormInitOptions(url, form) {\n const options = {};\n const index = url.indexOf(form === null || form === void 0 ? void 0 : form.path);\n // form url doesn't include form path\n if (index === -1) {\n return options;\n }\n const projectUrl = url.substring(0, index - 1);\n const urlParts = Formio_1.Formio.getUrlParts(projectUrl);\n // project url doesn't include subdirectories path\n if (!urlParts || urlParts.filter(part => !!part).length < 4) {\n return options;\n }\n const baseUrl = `${urlParts[1]}${urlParts[2]}`;\n // Skip if baseUrl has already been set\n if (baseUrl !== Formio_1.Formio.baseUrl) {\n return {\n base: baseUrl,\n project: projectUrl,\n };\n }\n return {};\n }\n setForm(formParam) {\n let result;\n formParam = formParam || this.form;\n if (typeof formParam === 'string') {\n const formio = new Formio_1.Formio(formParam);\n let error;\n this.loading = true;\n result = this.getSubmission(formio, this.options)\n .catch((err) => {\n error = err;\n })\n .then((submission) => {\n return formio.loadForm()\n // If the form returned an error, show it instead of the form.\n .catch(err => {\n error = err;\n })\n .then((form) => {\n // If the submission returned an error, show it instead of the form.\n if (error) {\n form = this.errorForm(error);\n }\n this.loading = false;\n this.instance = this.instance || this.create(form.display);\n const options = this.getFormInitOptions(formParam, form);\n this.instance.setUrl(formParam, options);\n this.instance.nosubmit = false;\n this._form = this.instance.form = form;\n if (submission) {\n this.instance.submission = submission;\n }\n if (error) {\n throw error;\n }\n return this.instance;\n });\n });\n }\n else {\n this.instance = this.instance || this.create(formParam.display);\n this._form = this.instance.form = formParam;\n result = this.instance.ready;\n }\n // A redraw has occurred so save off the new element in case of a setDisplay causing a rebuild.\n return result.then(() => {\n this.element = this.instance.element;\n return this.instance;\n });\n }\n getSubmission(formio, opts) {\n if (formio.submissionId) {\n return formio.loadSubmission(null, opts);\n }\n return Promise.resolve();\n }\n /**\n * Returns the loaded forms JSON.\n *\n * @return {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n *\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @return {Promise<T>}\n */\n setDisplay(display) {\n if ((this.display === display) && this.instance) {\n return Promise.resolve(this.instance);\n }\n this.form.display = display;\n this.instance.destroy();\n this.instance = this.create(display);\n return this.setForm(this.form);\n }\n empty() {\n if (this.element) {\n while (this.element.firstChild) {\n this.element.removeChild(this.element.firstChild);\n }\n }\n }\n static embed(embed) {\n return new Promise((resolve) => {\n if (!embed || !embed.src) {\n resolve();\n }\n const id = this.id || `formio-${Math.random().toString(36).substring(7)}`;\n const className = embed.class || 'formio-form-wrapper';\n let code = embed.styles ? `<link rel=\"stylesheet\" href=\"${embed.styles}\">` : '';\n code += `<div id=\"${id}\" class=\"${className}\"></div>`;\n document.write(code);\n let attempts = 0;\n const wait = setInterval(() => {\n attempts++;\n const formElement = document.getElementById(id);\n if (formElement || attempts > 10) {\n resolve(new Form(formElement, embed.src).ready);\n clearInterval(wait);\n }\n }, 10);\n });\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize) {\n // If Sanitize is turned off\n if (this.options.sanitize === false && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, this.options);\n }\n setContent(element, content, forceSanitize) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize);\n return true;\n }\n return false;\n }\n /**\n * Build a new form.\n *\n * @return {Promise<T>}\n */\n build() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (!this.element) {\n return Promise.reject('No DOM element for form.');\n }\n // Add temporary loader.\n const template = (this.options && this.options.template) ? this.options.template : 'bootstrap';\n const loader = templates_1.default[template].loader || templates_1.default.bootstrap.loader;\n this.setContent(this.element, loader.form);\n return this.render().then(html => {\n this.setContent(this.element, html);\n return this.attach(this.element).then(() => this.instance);\n })\n .then((param) => {\n this.emit('build', param);\n return param;\n });\n }\n render() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n return Promise.resolve(this.instance.render())\n .then((param) => {\n this.emit('render', param);\n return param;\n });\n }\n attach(element) {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n this.element = element;\n return this.instance.attach(this.element)\n .then((param) => {\n this.emit('attach', param);\n return param;\n });\n }\n}\nexports[\"default\"] = Form;\n// Allow simple embedding.\nFormio_1.Formio.embedForm = (embed) => Form.embed(embed);\n/**\n * Factory that creates a new form based on the form parameters.\n *\n * @param element {HMTLElement} - The HTML Element to add this form to.\n * @param form {string|Object} - The src of the form, or a form object.\n * @param options {Object} - The options to create this form.\n *\n * @return {Promise} - When the form is instance is ready.\n */\nFormio_1.Formio.createForm = (...args) => {\n return (new Form(...args)).ready;\n};\nFormio_1.Formio.Form = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
5522
+ eval("\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Element_1 = __importDefault(__webpack_require__(/*! ./Element */ \"./lib/cjs/Element.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst displays_1 = __importDefault(__webpack_require__(/*! ./displays */ \"./lib/cjs/displays/index.js\"));\nconst templates_1 = __importDefault(__webpack_require__(/*! ./templates */ \"./lib/cjs/templates/index.js\"));\nconst FormioUtils = __importStar(__webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\"));\nclass Form extends Element_1.default {\n /**\n * Creates an easy to use interface for embedding webforms, pdfs, and wizards into your application.\n *\n * @param {Object} element - The DOM element you wish to render this form within.\n * @param {Object | string} form - Either a Form JSON schema or the URL of a hosted form via. form.io.\n * @param {Object} options - The options to create a new form instance.\n * @param {boolean} options.readOnly - Set this form to readOnly\n * @param {boolean} options.noAlerts - Set to true to disable the alerts dialog.\n * @param {boolean} options.i18n - The translation file for this rendering. @see https://github.com/formio/formio.js/blob/master/i18n.js\n * @param {boolean} options.template - Provides a way to inject custom logic into the creation of every element rendered within the form.\n *\n * @example\n * import Form from '@formio/js/Form';\n * const form = new Form(document.getElementById('formio'), 'https://examples.form.io/example');\n * form.build();\n */\n constructor(...args) {\n let options = args[0] instanceof HTMLElement ? args[2] : args[1];\n if (Formio_1.Formio.options && Formio_1.Formio.options.form) {\n options = Object.assign(options, Formio_1.Formio.options.form);\n }\n super(options);\n if (this.options.useSessionToken) {\n Formio_1.Formio.useSessionToken(this.options);\n }\n this.ready = new Promise((resolve, reject) => {\n this.readyResolve = resolve;\n this.readyReject = reject;\n });\n this.instance = null;\n if (args[0] instanceof HTMLElement) {\n if (this.element) {\n delete this.element.component;\n }\n this.element = args[0];\n this.options = args[2] || {};\n this.options.events = this.events;\n this.setForm(args[1])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else if (args[0]) {\n this.element = null;\n this.options = args[1] || {};\n this.options.events = this.events;\n this.setForm(args[0])\n .then(() => this.readyResolve(this.instance))\n .catch(this.readyReject);\n }\n else {\n this.element = null;\n this.options = {};\n this.options.events = this.events;\n }\n this.display = '';\n }\n createElement(tag, attrs, children) {\n const element = document.createElement(tag);\n for (const attr in attrs) {\n if (attrs.hasOwnProperty(attr)) {\n element.setAttribute(attr, attrs[attr]);\n }\n }\n (children || []).forEach(child => {\n element.appendChild(this.createElement(child.tag, child.attrs, child.children));\n });\n return element;\n }\n set loading(load) {\n if (!this.element || this.options.noLoader) {\n return;\n }\n if (load) {\n if (this.loader) {\n return;\n }\n this.loader = this.createElement('div', {\n 'class': 'formio-loader'\n }, [{\n tag: 'div',\n attrs: {\n class: 'loader-wrapper'\n },\n children: [{\n tag: 'div',\n attrs: {\n class: 'loader text-center'\n }\n }]\n }]);\n this.element.appendChild(this.loader);\n }\n else if (this.loader) {\n if (this.element.contains(this.loader)) {\n this.element.removeChild(this.loader);\n }\n this.loader = null;\n }\n }\n /**\n * Create a new form instance provided the display of the form.\n *\n * @param {string} display - The display of the form, either \"wizard\", \"form\", or \"pdf\"\n * @return {*}\n */\n create(display) {\n if (this.options && (this.options.flatten || this.options.renderMode === 'flat')) {\n display = 'form';\n }\n this.display = display;\n if (displays_1.default.displays[display]) {\n return new displays_1.default.displays[display](this.element, this.options);\n }\n else {\n // eslint-disable-next-line new-cap\n return new displays_1.default.displays['webform'](this.element, this.options);\n }\n }\n /**\n * Sets the form. Either as JSON or a URL to a form JSON schema.\n *\n * @param {string|object} formParam - Either the form JSON or the URL of the form json.\n * @return {*}\n */\n set form(formParam) {\n this.setForm(formParam);\n }\n errorForm(err) {\n return {\n components: [\n {\n 'label': 'HTML',\n 'tag': 'div',\n 'className': 'error error-message alert alert-danger ui red message',\n 'attrs': [\n {\n 'attr': 'role',\n 'value': 'alert'\n }\n ],\n 'key': 'errorMessage',\n 'type': 'htmlelement',\n 'input': false,\n 'content': typeof err === 'string' ? err : err.message,\n }\n ]\n };\n }\n /**\n * Check Subdirectories path and provide correct options\n *\n * @param {string} url - The the URL of the form json.\n * @param {form} object - The form json.\n * @return {object} The initial options with base and project.\n */\n getFormInitOptions(url, form) {\n const options = {};\n const index = url.indexOf(form === null || form === void 0 ? void 0 : form.path);\n // form url doesn't include form path\n if (index === -1) {\n return options;\n }\n const projectUrl = url.substring(0, index - 1);\n const urlParts = Formio_1.Formio.getUrlParts(projectUrl);\n // project url doesn't include subdirectories path\n if (!urlParts || urlParts.filter(part => !!part).length < 4) {\n return options;\n }\n const baseUrl = `${urlParts[1]}${urlParts[2]}`;\n // Skip if baseUrl has already been set\n if (baseUrl !== Formio_1.Formio.baseUrl) {\n return {\n base: baseUrl,\n project: projectUrl,\n };\n }\n return {};\n }\n setForm(formParam) {\n let result;\n formParam = formParam || this.form;\n if (typeof formParam === 'string') {\n const formio = new Formio_1.Formio(formParam);\n let error;\n this.loading = true;\n result = this.getSubmission(formio, this.options)\n .catch((err) => {\n error = err;\n })\n .then((submission) => {\n return formio.loadForm()\n // If the form returned an error, show it instead of the form.\n .catch(err => {\n error = err;\n })\n .then((form) => {\n // If the submission returned an error, show it instead of the form.\n if (error) {\n form = this.errorForm(error);\n }\n this.loading = false;\n this.instance = this.instance || this.create(form.display);\n const options = this.getFormInitOptions(formParam, form);\n this.instance.setUrl(formParam, options);\n this.instance.nosubmit = false;\n this._form = this.instance.form = form;\n if (submission) {\n this.instance.submission = submission;\n }\n if (error) {\n throw error;\n }\n return this.instance;\n });\n });\n }\n else {\n this.instance = this.instance || this.create(formParam.display);\n this._form = this.instance.form = formParam;\n result = this.instance.ready;\n }\n // A redraw has occurred so save off the new element in case of a setDisplay causing a rebuild.\n return result.then(() => {\n if (this.element) {\n delete this.element.component;\n }\n this.element = this.instance.element;\n return this.instance;\n });\n }\n getSubmission(formio, opts) {\n if (formio.submissionId) {\n return formio.loadSubmission(null, opts);\n }\n return Promise.resolve();\n }\n /**\n * Returns the loaded forms JSON.\n *\n * @return {object} - The loaded form's JSON\n */\n get form() {\n return this._form;\n }\n /**\n * Changes the display of the form.\n *\n * @param {string} display - The display to set this form. Either \"wizard\", \"form\", or \"pdf\"\n * @return {Promise<T>}\n */\n setDisplay(display) {\n if ((this.display === display) && this.instance) {\n return Promise.resolve(this.instance);\n }\n this.form.display = display;\n this.instance.destroy();\n this.instance = this.create(display);\n return this.setForm(this.form);\n }\n empty() {\n if (this.element) {\n while (this.element.firstChild) {\n this.element.removeChild(this.element.firstChild);\n }\n }\n }\n static embed(embed) {\n return new Promise((resolve) => {\n if (!embed || !embed.src) {\n resolve();\n }\n const id = this.id || `formio-${Math.random().toString(36).substring(7)}`;\n const className = embed.class || 'formio-form-wrapper';\n let code = embed.styles ? `<link rel=\"stylesheet\" href=\"${embed.styles}\">` : '';\n code += `<div id=\"${id}\" class=\"${className}\"></div>`;\n document.write(code);\n let attempts = 0;\n const wait = setInterval(() => {\n attempts++;\n const formElement = document.getElementById(id);\n if (formElement || attempts > 10) {\n resolve(new Form(formElement, embed.src).ready);\n clearInterval(wait);\n }\n }, 10);\n });\n }\n /**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize) {\n // If Sanitize is turned off\n if (this.options.sanitize === false && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, this.options);\n }\n setContent(element, content, forceSanitize) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize);\n return true;\n }\n return false;\n }\n /**\n * Build a new form.\n *\n * @return {Promise<T>}\n */\n build() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (!this.element) {\n return Promise.reject('No DOM element for form.');\n }\n // Add temporary loader.\n const template = (this.options && this.options.template) ? this.options.template : 'bootstrap';\n const loader = templates_1.default[template].loader || templates_1.default.bootstrap.loader;\n this.setContent(this.element, loader.form);\n return this.render().then(html => {\n this.setContent(this.element, html);\n return this.attach(this.element).then(() => this.instance);\n })\n .then((param) => {\n this.emit('build', param);\n return param;\n });\n }\n render() {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n return Promise.resolve(this.instance.render())\n .then((param) => {\n this.emit('render', param);\n return param;\n });\n }\n attach(element) {\n if (!this.instance) {\n return Promise.reject('Form not ready. Use form.ready promise');\n }\n if (this.element) {\n delete this.element.component;\n }\n this.element = element;\n return this.instance.attach(this.element)\n .then((param) => {\n this.emit('attach', param);\n return param;\n });\n }\n teardown() {\n super.teardown();\n delete this.instance;\n delete this.ready;\n }\n}\nexports[\"default\"] = Form;\n// Allow simple embedding.\nFormio_1.Formio.embedForm = (embed) => Form.embed(embed);\n/**\n * Factory that creates a new form based on the form parameters.\n *\n * @param element {HMTLElement} - The HTML Element to add this form to.\n * @param form {string|Object} - The src of the form, or a form object.\n * @param options {Object} - The options to create this form.\n *\n * @return {Promise} - When the form is instance is ready.\n */\nFormio_1.Formio.createForm = (...args) => {\n return (new Form(...args)).ready;\n};\nFormio_1.Formio.Form = Form;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Form.js?");
5513
5523
 
5514
5524
  /***/ }),
5515
5525
 
@@ -5531,7 +5541,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5531
5541
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5532
5542
 
5533
5543
  "use strict";
5534
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass PDF extends Webform_1.default {\n constructor(element, options) {\n options.display = 'pdf';\n super(element, options);\n this.components = [];\n }\n init() {\n super.init();\n // Handle an iframe submission.\n this.on('iframe-submission', (submission) => this.setValue(submission, {\n fromIframe: true\n }), true);\n this.on('iframe-change', (submission) => this.setValue(submission, {\n fromIframe: true\n }), true);\n this.on('iframe-getIframePositions', (query) => {\n const iframe = document.getElementById(`iframe-${query.formId}`);\n if (iframe) {\n const iframeBoundingClientRect = iframe.getBoundingClientRect();\n this.postMessage({\n name: 'iframePositions',\n data: {\n formId: query.formId,\n iframe: {\n top: iframeBoundingClientRect.top\n },\n scrollY: window.scrollY || window.pageYOffset\n }\n });\n }\n });\n // Trigger when this form is ready.\n this.on('iframe-ready', () => this.iframeReadyResolve(), true);\n }\n render() {\n this.submitButton = this.addComponent({\n disabled: this.form.disableWizardSubmit,\n input: true,\n type: 'button',\n action: 'submit',\n internal: true,\n label: 'Submit',\n key: 'submit',\n ref: 'button',\n hidden: this.isSubmitButtonHidden()\n });\n return this.renderTemplate('pdf', {\n submitButton: this.submitButton.render(),\n classes: 'formio-form-pdf',\n children: this.renderComponents()\n });\n }\n redraw() {\n this.postMessage({ name: 'redraw' });\n return this.builderMode ? Promise.resolve() : super.redraw();\n }\n rebuild() {\n if (this.builderMode && this.component.components) {\n this.destroyComponents();\n this.addComponents();\n return Promise.resolve();\n }\n this.postMessage({ name: 'redraw' });\n return super.rebuild();\n }\n // Do not attach nested components for pdf.\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n return Promise.resolve();\n }\n attach(element) {\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n button: 'single',\n buttonMessageContainer: 'single',\n buttonMessage: 'single',\n zoomIn: 'single',\n zoomOut: 'single',\n iframeContainer: 'single'\n });\n this.submitButton.refs = Object.assign({}, this.refs);\n this.submitButton.attachButton();\n // Reset the iframeReady promise.\n this.iframeReady = new Promise((resolve, reject) => {\n this.iframeReadyResolve = resolve;\n this.iframeReadyReject = reject;\n });\n // iframes cannot be in the template so manually create it\n this.iframeElement = this.ce('iframe', {\n src: this.getSrc(),\n id: `iframe-${this.id}`,\n seamless: true,\n class: 'formio-iframe'\n });\n this.iframeElement.formioContainer = this.component.components;\n this.iframeElement.formioComponent = this;\n // Append the iframe to the iframeContainer in the template\n this.empty(this.refs.iframeContainer);\n this.appendChild(this.refs.iframeContainer, this.iframeElement);\n // Post the form to the iframe\n this.form.base = Formio_1.Formio.getBaseUrl();\n this.form.projectUrl = Formio_1.Formio.getProjectUrl();\n this.postMessage({ name: 'form', data: this.form });\n // Hide the submit button if the associated component is hidden\n const submitButton = this.components.find(c => c.element === this.refs.button);\n if (submitButton) {\n this.refs.button.classList.toggle('hidden', !submitButton.visible);\n }\n this.addEventListener(this.refs.zoomIn, 'click', (event) => {\n event.preventDefault();\n this.postMessage({ name: 'zoomIn' });\n });\n this.addEventListener(this.refs.zoomOut, 'click', (event) => {\n event.preventDefault();\n this.postMessage({ name: 'zoomOut' });\n });\n const form = (0, utils_1.fastCloneDeep)(this.form);\n if (this.formio) {\n form.projectUrl = this.formio.projectUrl;\n form.url = this.formio.formUrl;\n form.base = this.formio.base;\n this.postMessage({ name: 'token', data: this.formio.getToken() });\n }\n this.emit('attach');\n });\n }\n /**\n * Get the submission from the iframe.\n *\n * @return {Promise<any>}\n */\n getSubmission() {\n return new Promise((resolve) => {\n this.once('iframe-submission', resolve);\n this.postMessage({ name: 'getSubmission' });\n });\n }\n /**\n * Ensure we have the submission from the iframe before we submit the form.\n *\n * @param options\n * @return {*}\n */\n submitForm(options = {}) {\n this.postMessage({ name: 'getErrors' });\n return this.getSubmission().then(() => super.submitForm(options));\n }\n getSrc() {\n if (!this._form || !this._form.settings || !this._form.settings.pdf) {\n return '';\n }\n let iframeSrc = `${this._form.settings.pdf.src}.html`;\n const params = [`id=${this.id}`];\n if (this.options.showCheckboxBackground || this._form.settings.showCheckboxBackground) {\n params.push('checkboxbackground=1');\n }\n if (this.options.readOnly) {\n params.push('readonly=1');\n }\n if (this.options.zoom) {\n params.push(`zoom=${this.options.zoom}`);\n }\n if (this.builderMode) {\n params.push('builder=1');\n }\n if (params.length) {\n iframeSrc += `?${params.join('&')}`;\n }\n return iframeSrc;\n }\n setForm(form, flags = {}) {\n return super.setForm(form, flags).then(() => {\n if (this.formio) {\n form.projectUrl = this.formio.projectUrl;\n form.url = this.formio.formUrl;\n form.base = this.formio.base;\n this.postMessage({ name: 'token', data: this.formio.getToken() });\n }\n this.postMessage({ name: 'form', data: this.form });\n });\n }\n /**\n * Set's the value of this form component.\n *\n * @param submission\n * @param flags\n */\n setValue(submission, flags = {}) {\n const changed = super.setValue(submission, flags);\n if (!flags || !flags.fromIframe) {\n this.once('iframe-ready', () => {\n if (changed) {\n this.postMessage({ name: 'submission', data: submission });\n }\n });\n }\n return changed;\n }\n postMessage(message) {\n // If we get here before the iframeReady promise is set up, it's via the superclass constructor\n if (!this.iframeReady) {\n return;\n }\n if (!message.type) {\n message.type = 'iframe-data';\n }\n this.iframeReady.then(() => {\n if (this.iframeElement && this.iframeElement.contentWindow && !(message.name === 'form' && this.iframeFormSetUp)) {\n this.iframeElement.contentWindow.postMessage(JSON.stringify(message), '*');\n this.iframeFormSetUp = message.name === 'form';\n }\n });\n }\n focusOnComponent(key) {\n this.postMessage({\n name: 'focusErroredField',\n data: key,\n });\n }\n // Do not clear the iframe.\n clear() { }\n showErrors(error, triggerEvent) {\n var _a;\n const helpBlock = document.getElementById('submit-error');\n const submitError = this.t('submitError');\n const isSubmitErrorShown = ((_a = this.refs.buttonMessage) === null || _a === void 0 ? void 0 : _a.textContent.trim()) === submitError;\n if (!helpBlock && error.length && !isSubmitErrorShown) {\n const p = this.ce('p', { class: 'help-block' });\n this.setContent(p, submitError);\n p.addEventListener('click', () => {\n window.scrollTo(0, 0);\n });\n const div = this.ce('div', { id: 'submit-error', class: 'has-error' });\n this.appendTo(p, div);\n this.appendTo(div, this.element);\n }\n if (!error.length && helpBlock) {\n helpBlock.remove();\n }\n super.showErrors(error, triggerEvent);\n }\n isSubmitButtonHidden() {\n let hidden = false;\n (0, utils_1.eachComponent)(this.component.components, (component) => {\n if ((component.type === 'button') &&\n ((component.action === 'submit') || !component.action)) {\n hidden = component.hidden || false;\n }\n });\n return hidden;\n }\n}\nexports[\"default\"] = PDF;\n/**\n * Listen for window messages.\n */\nif (typeof window !== 'undefined') {\n window.addEventListener('message', (event) => {\n let eventData = null;\n try {\n eventData = JSON.parse(event.data);\n }\n catch (err) {\n eventData = null;\n }\n // If this form exists, then emit the event within this form.\n if (eventData &&\n eventData.name &&\n eventData.formId &&\n Formio_1.Formio.forms.hasOwnProperty(eventData.formId)) {\n Formio_1.Formio.forms[eventData.formId].emit(`iframe-${eventData.name}`, eventData.data);\n }\n });\n}\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/PDF.js?");
5544
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass PDF extends Webform_1.default {\n constructor(element, options) {\n options.display = 'pdf';\n super(element, options);\n this.components = [];\n }\n init() {\n super.init();\n // Handle an iframe submission.\n this.on('iframe-submission', (submission) => this.setValue(submission, {\n fromIframe: true\n }), true);\n this.on('iframe-change', (submission) => this.setValue(submission, {\n fromIframe: true\n }), true);\n this.on('iframe-getIframePositions', (query) => {\n const iframe = document.getElementById(`iframe-${query.formId}`);\n if (iframe) {\n const iframeBoundingClientRect = iframe.getBoundingClientRect();\n this.postMessage({\n name: 'iframePositions',\n data: {\n formId: query.formId,\n iframe: {\n top: iframeBoundingClientRect.top\n },\n scrollY: window.scrollY || window.pageYOffset\n }\n });\n }\n });\n // Trigger when this form is ready.\n this.on('iframe-ready', () => this.iframeReadyResolve(), true);\n }\n render() {\n this.submitButton = this.addComponent({\n disabled: this.form.disableWizardSubmit,\n input: true,\n type: 'button',\n action: 'submit',\n internal: true,\n label: 'Submit',\n key: 'submit',\n ref: 'button',\n hidden: this.isSubmitButtonHidden()\n });\n return this.renderTemplate('pdf', {\n submitButton: this.submitButton.render(),\n classes: 'formio-form-pdf',\n children: this.renderComponents()\n });\n }\n redraw() {\n this.postMessage({ name: 'redraw' });\n return this.builderMode ? Promise.resolve() : super.redraw();\n }\n destroy(all = false) {\n if (this.iframeElement) {\n delete this.iframeElement.formioComponent;\n this.iframeElement.formioComponent = null;\n }\n super.destroy(all);\n }\n rebuild() {\n if (this.attached && this.builderMode && this.component.components) {\n this.destroyComponents();\n this.addComponents();\n return Promise.resolve();\n }\n this.postMessage({ name: 'redraw' });\n return super.rebuild();\n }\n // Do not attach nested components for pdf.\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n return Promise.resolve();\n }\n attach(element) {\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n button: 'single',\n buttonMessageContainer: 'single',\n buttonMessage: 'single',\n zoomIn: 'single',\n zoomOut: 'single',\n iframeContainer: 'single'\n });\n this.submitButton.refs = Object.assign({}, this.refs);\n this.submitButton.attachButton();\n // Reset the iframeReady promise.\n this.iframeReady = new Promise((resolve, reject) => {\n this.iframeReadyResolve = resolve;\n this.iframeReadyReject = reject;\n });\n // iframes cannot be in the template so manually create it\n this.iframeElement = this.ce('iframe', {\n src: this.getSrc(),\n id: `iframe-${this.id}`,\n seamless: true,\n class: 'formio-iframe'\n });\n this.iframeElement.formioContainer = this.component.components;\n this.iframeElement.formioComponent = this;\n // Append the iframe to the iframeContainer in the template\n this.empty(this.refs.iframeContainer);\n this.appendChild(this.refs.iframeContainer, this.iframeElement);\n // Post the form to the iframe\n this.form.base = Formio_1.Formio.getBaseUrl();\n this.form.projectUrl = Formio_1.Formio.getProjectUrl();\n this.postMessage({ name: 'form', data: this.form });\n // Hide the submit button if the associated component is hidden\n const submitButton = this.components.find(c => c.element === this.refs.button);\n if (submitButton) {\n this.refs.button.classList.toggle('hidden', !submitButton.visible);\n }\n this.addEventListener(this.refs.zoomIn, 'click', (event) => {\n event.preventDefault();\n this.postMessage({ name: 'zoomIn' });\n });\n this.addEventListener(this.refs.zoomOut, 'click', (event) => {\n event.preventDefault();\n this.postMessage({ name: 'zoomOut' });\n });\n const form = (0, utils_1.fastCloneDeep)(this.form);\n if (this.formio) {\n form.projectUrl = this.formio.projectUrl;\n form.url = this.formio.formUrl;\n form.base = this.formio.base;\n this.postMessage({ name: 'token', data: this.formio.getToken() });\n }\n this.emit('attach');\n });\n }\n /**\n * Get the submission from the iframe.\n *\n * @return {Promise<any>}\n */\n getSubmission() {\n return new Promise((resolve) => {\n this.once('iframe-submission', resolve);\n this.postMessage({ name: 'getSubmission' });\n });\n }\n /**\n * Ensure we have the submission from the iframe before we submit the form.\n *\n * @param options\n * @return {*}\n */\n submitForm(options = {}) {\n this.postMessage({ name: 'getErrors' });\n return this.getSubmission().then(() => super.submitForm(options));\n }\n getSrc() {\n if (!this._form || !this._form.settings || !this._form.settings.pdf) {\n return '';\n }\n let iframeSrc = `${this._form.settings.pdf.src}.html`;\n const params = [`id=${this.id}`];\n if (this.options.showCheckboxBackground || this._form.settings.showCheckboxBackground) {\n params.push('checkboxbackground=1');\n }\n if (this.options.readOnly) {\n params.push('readonly=1');\n }\n if (this.options.zoom) {\n params.push(`zoom=${this.options.zoom}`);\n }\n if (this.builderMode) {\n params.push('builder=1');\n }\n if (params.length) {\n iframeSrc += `?${params.join('&')}`;\n }\n return iframeSrc;\n }\n setForm(form, flags = {}) {\n return super.setForm(form, flags).then(() => {\n if (this.formio) {\n form.projectUrl = this.formio.projectUrl;\n form.url = this.formio.formUrl;\n form.base = this.formio.base;\n this.postMessage({ name: 'token', data: this.formio.getToken() });\n }\n this.postMessage({ name: 'form', data: this.form });\n });\n }\n /**\n * Set's the value of this form component.\n *\n * @param submission\n * @param flags\n */\n setValue(submission, flags = {}) {\n const changed = super.setValue(submission, flags);\n if (!flags || !flags.fromIframe) {\n this.once('iframe-ready', () => {\n if (changed) {\n this.postMessage({ name: 'submission', data: submission });\n }\n });\n }\n return changed;\n }\n postMessage(message) {\n // If we get here before the iframeReady promise is set up, it's via the superclass constructor\n if (!this.iframeReady) {\n return;\n }\n if (!message.type) {\n message.type = 'iframe-data';\n }\n this.iframeReady.then(() => {\n if (this.iframeElement && this.iframeElement.contentWindow && !(message.name === 'form' && this.iframeFormSetUp)) {\n this.iframeElement.contentWindow.postMessage(JSON.stringify(message), '*');\n this.iframeFormSetUp = message.name === 'form';\n }\n });\n }\n focusOnComponent(key) {\n this.postMessage({\n name: 'focusErroredField',\n data: key,\n });\n }\n // Do not clear the iframe.\n clear() { }\n showErrors(error, triggerEvent) {\n var _a;\n const helpBlock = document.getElementById('submit-error');\n const submitError = this.t('submitError');\n const isSubmitErrorShown = ((_a = this.refs.buttonMessage) === null || _a === void 0 ? void 0 : _a.textContent.trim()) === submitError;\n if (!helpBlock && error.length && !isSubmitErrorShown) {\n const p = this.ce('p', { class: 'help-block' });\n this.setContent(p, submitError);\n p.addEventListener('click', () => {\n window.scrollTo(0, 0);\n });\n const div = this.ce('div', { id: 'submit-error', class: 'has-error' });\n this.appendTo(p, div);\n this.appendTo(div, this.element);\n }\n if (!error.length && helpBlock) {\n helpBlock.remove();\n }\n super.showErrors(error, triggerEvent);\n }\n isSubmitButtonHidden() {\n let hidden = false;\n (0, utils_1.eachComponent)(this.component.components, (component) => {\n if ((component.type === 'button') &&\n ((component.action === 'submit') || !component.action)) {\n hidden = component.hidden || false;\n }\n });\n return hidden;\n }\n}\nexports[\"default\"] = PDF;\n/**\n * Listen for window messages.\n */\nif (typeof window !== 'undefined') {\n window.addEventListener('message', (event) => {\n let eventData = null;\n try {\n eventData = JSON.parse(event.data);\n }\n catch (err) {\n eventData = null;\n }\n // If this form exists, then emit the event within this form.\n if (eventData &&\n eventData.name &&\n eventData.formId &&\n Formio_1.Formio.forms.hasOwnProperty(eventData.formId)) {\n Formio_1.Formio.forms[eventData.formId].emit(`iframe-${eventData.name}`, eventData.data);\n }\n });\n}\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/PDF.js?");
5535
5545
 
5536
5546
  /***/ }),
5537
5547
 
@@ -5542,7 +5552,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5542
5552
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5543
5553
 
5544
5554
  "use strict";
5545
- 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 Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst WebformBuilder_1 = __importDefault(__webpack_require__(/*! ./WebformBuilder */ \"./lib/cjs/WebformBuilder.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 PDF_1 = __importDefault(__webpack_require__(/*! ./PDF */ \"./lib/cjs/PDF.js\"));\nclass PDFBuilder extends WebformBuilder_1.default {\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 // Force superclass to skip the automatic init; we'll trigger it manually\n options.skipInit = true;\n options.display = 'pdf';\n if (element) {\n super(element, options);\n }\n else {\n super(options);\n }\n this.dragDropEnabled = false;\n }\n get defaultGroups() {\n return {\n pdf: {\n title: 'PDF Fields',\n weight: 0,\n default: true,\n components: {\n textfield: true,\n number: true,\n password: true,\n email: true,\n phoneNumber: true,\n currency: true,\n checkbox: true,\n signature: true,\n select: true,\n textarea: true,\n datetime: true,\n file: true,\n htmlelement: true,\n signrequestsignature: true\n }\n },\n basic: false,\n advanced: false,\n layout: false,\n data: false,\n premium: false,\n resource: false\n };\n }\n get hasPDF() {\n return lodash_1.default.has(this.webform.form, 'settings.pdf');\n }\n get projectUrl() {\n return this.options.projectUrl || Formio_1.Formio.getProjectUrl();\n }\n init() {\n this.options.attachMode = 'builder';\n this.webform = this.webform || this.createForm(this.options);\n this.webform.init();\n }\n render() {\n const result = this.renderTemplate('pdfBuilder', {\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 })),\n }),\n form: this.hasPDF ?\n this.webform.render() :\n this.renderTemplate('pdfBuilderUpload', {})\n });\n return result;\n }\n attach(element) {\n // PDF Upload\n if (!this.hasPDF) {\n this.loadRefs(element, {\n 'fileDrop': 'single',\n 'fileBrowse': 'single',\n 'hiddenFileInputElement': 'single',\n 'uploadError': 'single',\n 'uploadProgress': 'single',\n 'uploadProgressWrapper': 'single',\n 'dragDropText': 'single'\n });\n this.addEventListener(this.refs['pdf-upload-button'], 'click', (event) => {\n event.preventDefault();\n });\n // Init the upload error.\n if (!this.projectUrl) {\n this.setUploadError('Form options.projectUrl not set. Please set the \"projectUrl\" property of the options for this form or use Formio.setProjectUrl(). This setting is necessary to upload a pdf background.');\n }\n else {\n this.setUploadError();\n }\n if (this.refs.fileDrop) {\n const element = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n element.upload(event.dataTransfer.files[0]);\n return false;\n });\n }\n if (this.refs.fileBrowse && this.refs.hiddenFileInputElement) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof this.refs.hiddenFileInputElement.trigger === 'function') {\n this.refs.hiddenFileInputElement.trigger('click');\n }\n else {\n this.refs.hiddenFileInputElement.click();\n }\n });\n this.addEventListener(this.refs.hiddenFileInputElement, 'change', () => {\n if (!this.refs.hiddenFileInputElement.value) {\n return;\n }\n this.upload(this.refs.hiddenFileInputElement.files[0]);\n this.refs.hiddenFileInputElement.value = '';\n });\n }\n return Promise.resolve();\n }\n // Normal PDF Builder\n return super.attach(element).then(() => {\n this.loadRefs(this.element, {\n iframeDropzone: 'single',\n 'sidebar-container': 'multiple',\n 'sidebar': 'single',\n });\n this.afterAttach();\n return this.element;\n });\n }\n afterAttach() {\n this.on('saveComponent', (component) => {\n this.webform.postMessage({ name: 'updateElement', data: component });\n });\n this.on('removeComponent', (component) => {\n this.webform.postMessage({ name: 'removeElement', data: component });\n });\n this.initIframeEvents();\n this.updateDropzoneDimensions();\n const sidebar = this.refs.sidebar;\n if (sidebar) {\n this.addClass(sidebar, 'disabled');\n this.webform.on('iframe-ready', () => {\n this.pdfLoaded = true;\n this.updateDragAndDrop();\n this.removeClass(sidebar, 'disabled');\n }, true);\n }\n }\n upload(file) {\n const formio = new Formio_1.Formio(this.projectUrl);\n if (this.refs.dragDropText) {\n this.refs.dragDropText.style.display = 'none';\n }\n if (this.refs.uploadProgressWrapper) {\n this.refs.uploadProgressWrapper.style.display = 'inherit';\n }\n formio.uploadFile('url', file, file, '', (event) => {\n if (this.refs.uploadProgress) {\n const progress = Math.floor((event.loaded / event.total) * 100);\n this.refs.uploadProgress.style.width = `${progress}%`;\n if (progress > 98) {\n this.refs.uploadProgress.innerHTML = this.t('Converting PDF. Please wait.');\n }\n else {\n this.refs.uploadProgress.innerHTML = `${this.t('Uploading')} ${progress}%`;\n }\n }\n }, `${this.projectUrl}/upload`, {}, 'file')\n .then((result) => {\n var _a, _b, _c, _d;\n let autoConversionComponentsAssigned = false;\n if (((_a = result.data.formfields) === null || _a === void 0 ? void 0 : _a.components) && result.data.formfields.components.length) {\n const formInitState = ((_b = this.webform.form.components[0]) === null || _b === void 0 ? void 0 : _b.key) === 'submit';\n const wizardInitState = ((_c = this.webform.form.components[0]) === null || _c === void 0 ? void 0 : _c.key) === 'page1' &&\n ((_d = this.webform.form.components[0]) === null || _d === void 0 ? void 0 : _d.components.length) === 0;\n const emptyFormState = this.webform.form.components.length === 0;\n if (formInitState || wizardInitState || emptyFormState) {\n autoConversionComponentsAssigned = true;\n this.webform.form.components = result.data.formfields.components;\n }\n }\n if (this.refs.dragDropText) {\n this.refs.dragDropText.style.display = 'inherit';\n }\n if (this.refs.uploadProgressWrapper) {\n this.refs.uploadProgressWrapper.style.display = 'none';\n }\n lodash_1.default.set(this.webform.form, 'settings.pdf', {\n id: result.data.file,\n src: result.data.filesServer ? `${result.data.filesServer}${result.data.path}` : `${new URL(this.projectUrl).origin}/pdf-proxy${result.data.path}`,\n nonFillableConversionUsed: autoConversionComponentsAssigned && result.data.formfields.nonFillableConversionUsed\n });\n this.emit('pdfUploaded', result.data);\n this.redraw();\n })\n .catch((err) => this.setUploadError(err));\n }\n setUploadError(message) {\n if (!this.refs.uploadError) {\n return;\n }\n this.refs.uploadError.style.display = message ? '' : 'none';\n this.refs.uploadError.innerHTML = message;\n }\n createForm(options) {\n // Instantiate the webform from the PDF class instead of Webform\n options.skipInit = false;\n options.hideLoader = true;\n this.webform = new PDF_1.default(this.element, options);\n this.webform.on('attach', () => {\n // If the dropzone exists but has been removed in a PDF rebuild, reinstate it\n if (this.refs.iframeDropzone && ![...this.refs.form.children].includes(this.refs.iframeDropzone)) {\n this.prependTo(this.refs.iframeDropzone, this.refs.form);\n }\n });\n return this.webform;\n }\n destroy(deleteFromGlobal) {\n super.destroy(deleteFromGlobal);\n this.webform.destroy(deleteFromGlobal);\n }\n // d8b 8888888888 888\n // Y8P 888 888\n // 888 888\n // 888 8888888 888d888 8888b. 88888b.d88b. .d88b. .d88b. 888 888 .d88b. 88888b. 888888 .d8888b\n // 888 888 888P\" \"88b 888 \"888 \"88b d8P Y8b d8P Y8b 888 888 d8P Y8b 888 \"88b 888 88K\n // 888 888 888 .d888888 888 888 888 88888888 88888888 Y88 88P 88888888 888 888 888 \"Y8888b.\n // 888 888 888 888 888 888 888 888 Y8b. Y8b. Y8bd8P Y8b. 888 888 Y88b. X88\n // 888 888 888 \"Y888888 888 888 888 \"Y8888 \"Y8888 Y88P \"Y8888 888 888 \"Y888 88888P'\n getParentContainer(component) {\n let container = [];\n let originalComponent = null;\n (0, formUtils_1.eachComponent)(this.webform._form.components, (comp, path, components) => {\n if (comp.id === component.component.id) {\n container = components;\n originalComponent = comp;\n return true;\n }\n }, true);\n return {\n formioComponent: component.parent,\n formioContainer: container,\n originalComponent\n };\n }\n initIframeEvents() {\n this.webform.off('iframe-elementUpdate');\n this.webform.off('iframe-componentUpdate');\n this.webform.off('iframe-componentClick');\n this.webform.on('iframe-elementUpdate', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component && component.component) {\n const isNew = true;\n component.component.overlay = {\n page: schema.page,\n left: schema.left,\n top: schema.top,\n height: schema.height,\n width: schema.width\n };\n if (!this.options.noNewEdit && !component.component.noNewEdit) {\n this.editComponent(component.component, this.getParentContainer(component), isNew);\n }\n this.emit('updateComponent', component.component);\n }\n return component;\n });\n this.webform.on('iframe-componentUpdate', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component && component.component) {\n component.component.overlay = {\n page: schema.overlay.page,\n left: schema.overlay.left,\n top: schema.overlay.top,\n height: schema.overlay.height,\n width: schema.overlay.width\n };\n this.emit('updateComponent', component.component);\n this.emit('change', this.form);\n }\n return component;\n });\n this.webform.on('iframe-componentClick', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component) {\n this.editComponent(component.component, this.getParentContainer(component));\n }\n }, true);\n }\n // 8888888b. 888 d8b\n // 888 \"Y88b 888 Y8P\n // 888 888 888\n // 888 888 888d888 .d88b. 88888b. 88888888 .d88b. 88888b. .d88b. 888 .d88b. .d88b. 888 .d8888b\n // 888 888 888P\" d88\"\"88b 888 \"88b d88P d88\"\"88b 888 \"88b d8P Y8b 888 d88\"\"88b d88P\"88b 888 d88P\"\n // 888 888 888 888 888 888 888 d88P 888 888 888 888 88888888 888 888 888 888 888 888 888\n // 888 .d88P 888 Y88..88P 888 d88P d88P Y88..88P 888 888 Y8b. 888 Y88..88P Y88b 888 888 Y88b.\n // 8888888P\" 888 \"Y88P\" 88888P\" 88888888 \"Y88P\" 888 888 \"Y8888 888 \"Y88P\" \"Y88888 888 \"Y8888P\n // 888 888\n // 888 Y8b d88P\n // 888 \"Y88P\"\n initDropzoneEvents() {\n if (!this.refs.iframeDropzone) {\n return;\n }\n // This is required per HTML spec in order for the drop event to fire\n this.removeEventListener(this.refs.iframeDropzone, 'dragover');\n this.removeEventListener(this.refs.iframeDropzone, 'drop');\n this.addEventListener(this.refs.iframeDropzone, 'dragover', (e) => {\n e.preventDefault();\n return false;\n });\n this.addEventListener(this.refs.iframeDropzone, 'drop', this.onDropzoneDrop.bind(this));\n }\n updateDragAndDrop() {\n if (!this.pdfLoaded) {\n return;\n }\n this.initDropzoneEvents();\n this.prepSidebarComponentsForDrag();\n }\n prepSidebarComponentsForDrag() {\n if (!this.refs['sidebar-container']) {\n return;\n }\n this.refs['sidebar-container'].forEach(container => {\n [...container.children].forEach(el => {\n el.draggable = true;\n el.setAttribute('draggable', true);\n this.removeEventListener(el, 'dragstart');\n this.removeEventListener(el, 'dragend');\n this.addEventListener(el, 'dragstart', this.onDragStart.bind(this), true);\n this.addEventListener(el, 'dragend', this.onDragEnd.bind(this), true);\n this.addEventListener(el, 'drag', (e) => {\n e.target.style.cursor = 'none';\n });\n });\n });\n }\n updateDropzoneDimensions() {\n if (!this.refs.iframeDropzone) {\n return;\n }\n const iframeRect = (0, utils_1.getElementRect)(this.webform.refs.iframeContainer);\n this.refs.iframeDropzone.style.height = iframeRect && iframeRect.height ? `${iframeRect.height}px` : '1000px';\n this.refs.iframeDropzone.style.width = iframeRect && iframeRect.width ? `${iframeRect.width}px` : '100%';\n }\n onDragStart(e) {\n // Taking the current offset of a dragged item relative to the cursor\n const { offsetX = 0, offsetY = 0 } = e;\n this.itemOffsetX = offsetX;\n this.itemOffsetY = offsetY;\n e.dataTransfer.setData('text', '');\n this.updateDropzoneDimensions();\n this.addClass(this.refs.iframeDropzone, 'enabled');\n this.dropEmitted = false;\n }\n onDropzoneDrop(e) {\n this.dropEmitted = true;\n this.dropEvent = e;\n e.preventDefault();\n return false;\n }\n onDragEnd(e) {\n // IMPORTANT - must retrieve offsets BEFORE disabling the dropzone - offsets will\n // reflect absolute positioning if accessed after the target element is hidden\n const iframeRect = this.webform.refs.iframeContainer.getBoundingClientRect();\n const layerX = this.dropEvent ? this.dropEvent.layerX : null;\n const layerY = this.dropEvent ? this.dropEvent.layerY : null;\n const WIDTH = 100;\n const HEIGHT = 20;\n // Always disable the dropzone on drag end\n this.removeClass(this.refs.iframeDropzone, 'enabled');\n // If there hasn't been a drop event on the dropzone, we're done\n if (!this.dropEvent) {\n // a 'drop' event may not be emited in the chrome browser when using a Mac, therefore an additional check has been added\n // eslint-disable-next-line no-undef\n if (!this.dropEmitted && ((0, utils_1.getBrowserInfo)().chrome || (0, utils_1.getBrowserInfo)().edge) && globalThis.navigator.userAgentData.platform === 'macOS' && iframeRect.left < e.clientX && iframeRect.top < e.clientY) {\n this.dropEvent = e;\n this.dropEvent.dataTransfer.effectAllowed = 'all';\n this.dropEmitted = true;\n }\n else {\n return;\n }\n }\n const element = e.target;\n const type = element.getAttribute('data-type');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const schema = (0, utils_1.fastCloneDeep)(this.schemas[type]);\n if (key && group) {\n const info = this.getComponentInfo(key, group);\n lodash_1.default.merge(schema, info);\n }\n // Set a unique key for this component.\n builder_1.default.uniquify([this.webform._form], schema);\n this.webform._form.components.push(schema);\n schema.overlay = {\n top: layerY ? (layerY - this.itemOffsetY + HEIGHT) : (e.clientY - iframeRect.top - (this.itemOffsetY - HEIGHT) * 2),\n left: layerX ? (layerX - this.itemOffsetX) : (e.clientX - iframeRect.left - this.itemOffsetX * 2),\n width: WIDTH,\n height: HEIGHT\n };\n this.webform.addComponent(schema, {}, null, true);\n this.webform.postMessage({ name: 'addElement', data: schema });\n this.emit('addComponent', schema, this.webform, schema.key, this.webform.component.components.length, !this.options.noNewEdit && !schema.noNewEdit);\n // Delete the stored drop event now that it's been handled\n this.dropEvent = null;\n e.target.style.cursor = 'default';\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n // update elements which path was duplicated if any pathes have been changed\n if (!lodash_1.default.isEqual(this.repeatablePaths, repeatablePaths)) {\n (0, formUtils_1.eachComponent)(this.webform.getComponents(), (comp, path) => {\n if (this.repeatablePaths.includes(path)) {\n this.webform.postMessage({ name: 'updateElement', data: comp.component });\n }\n });\n this.repeatablePaths = repeatablePaths;\n }\n if (!repeatablePaths.length) {\n return;\n }\n (0, formUtils_1.eachComponent)(this.webform.getComponents(), (comp, path) => {\n if (this.repeatablePaths.includes(path)) {\n this.webform.postMessage({\n name: 'showBuilderErrors',\n data: {\n compId: comp.component.id,\n errorMessage: `API Key is not unique: ${comp.key}`,\n }\n });\n }\n });\n }\n}\nexports[\"default\"] = PDFBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/PDFBuilder.js?");
5555
+ 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 Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst WebformBuilder_1 = __importDefault(__webpack_require__(/*! ./WebformBuilder */ \"./lib/cjs/WebformBuilder.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 PDF_1 = __importDefault(__webpack_require__(/*! ./PDF */ \"./lib/cjs/PDF.js\"));\nclass PDFBuilder extends WebformBuilder_1.default {\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 // Force superclass to skip the automatic init; we'll trigger it manually\n options.skipInit = true;\n options.display = 'pdf';\n if (element) {\n super(element, options);\n }\n else {\n super(options);\n }\n this.dragDropEnabled = false;\n }\n get defaultGroups() {\n return {\n pdf: {\n title: 'PDF Fields',\n weight: 0,\n default: true,\n components: {\n textfield: true,\n number: true,\n password: true,\n email: true,\n phoneNumber: true,\n currency: true,\n checkbox: true,\n signature: true,\n select: true,\n textarea: true,\n datetime: true,\n file: true,\n htmlelement: true,\n signrequestsignature: true\n }\n },\n basic: false,\n advanced: false,\n layout: false,\n data: false,\n premium: false,\n resource: false\n };\n }\n get hasPDF() {\n return lodash_1.default.has(this.webform.form, 'settings.pdf');\n }\n get projectUrl() {\n return this.options.projectUrl || Formio_1.Formio.getProjectUrl();\n }\n init() {\n this.options.attachMode = 'builder';\n this.webform = this.webform || this.createForm(this.options);\n this.webform.init();\n }\n render() {\n const result = this.renderTemplate('pdfBuilder', {\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 })),\n }),\n form: this.hasPDF ?\n this.webform.render() :\n this.renderTemplate('pdfBuilderUpload', {})\n });\n return result;\n }\n attach(element) {\n // PDF Upload\n if (!this.hasPDF) {\n this.loadRefs(element, {\n 'fileDrop': 'single',\n 'fileBrowse': 'single',\n 'hiddenFileInputElement': 'single',\n 'uploadError': 'single',\n 'uploadProgress': 'single',\n 'uploadProgressWrapper': 'single',\n 'dragDropText': 'single'\n });\n this.addEventListener(this.refs['pdf-upload-button'], 'click', (event) => {\n event.preventDefault();\n });\n // Init the upload error.\n if (!this.projectUrl) {\n this.setUploadError('Form options.projectUrl not set. Please set the \"projectUrl\" property of the options for this form or use Formio.setProjectUrl(). This setting is necessary to upload a pdf background.');\n }\n else {\n this.setUploadError();\n }\n if (this.refs.fileDrop) {\n const element = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n element.upload(event.dataTransfer.files[0]);\n return false;\n });\n }\n if (this.refs.fileBrowse && this.refs.hiddenFileInputElement) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof this.refs.hiddenFileInputElement.trigger === 'function') {\n this.refs.hiddenFileInputElement.trigger('click');\n }\n else {\n this.refs.hiddenFileInputElement.click();\n }\n });\n this.addEventListener(this.refs.hiddenFileInputElement, 'change', () => {\n if (!this.refs.hiddenFileInputElement.value) {\n return;\n }\n this.upload(this.refs.hiddenFileInputElement.files[0]);\n this.refs.hiddenFileInputElement.value = '';\n });\n }\n return Promise.resolve();\n }\n // Normal PDF Builder\n return super.attach(element).then(() => {\n this.loadRefs(this.element, {\n iframeDropzone: 'single',\n 'sidebar-container': 'multiple',\n 'sidebar': 'single',\n });\n this.afterAttach();\n return this.element;\n });\n }\n afterAttach() {\n this.on('saveComponent', (component) => {\n this.webform.postMessage({ name: 'updateElement', data: component });\n });\n this.on('removeComponent', (component) => {\n this.webform.postMessage({ name: 'removeElement', data: component });\n });\n this.initIframeEvents();\n this.updateDropzoneDimensions();\n const sidebar = this.refs.sidebar;\n if (sidebar) {\n this.addClass(sidebar, 'disabled');\n this.webform.on('iframe-ready', () => {\n this.pdfLoaded = true;\n this.updateDragAndDrop();\n this.removeClass(sidebar, 'disabled');\n }, true);\n }\n }\n upload(file) {\n const formio = new Formio_1.Formio(this.projectUrl);\n if (this.refs.dragDropText) {\n this.refs.dragDropText.style.display = 'none';\n }\n if (this.refs.uploadProgressWrapper) {\n this.refs.uploadProgressWrapper.style.display = 'inherit';\n }\n formio.uploadFile('url', file, file, '', (event) => {\n if (this.refs.uploadProgress) {\n const progress = Math.floor((event.loaded / event.total) * 100);\n this.refs.uploadProgress.style.width = `${progress}%`;\n if (progress > 98) {\n this.refs.uploadProgress.innerHTML = this.t('Converting PDF. Please wait.');\n }\n else {\n this.refs.uploadProgress.innerHTML = `${this.t('Uploading')} ${progress}%`;\n }\n }\n }, `${this.projectUrl}/upload`, {}, 'file')\n .then((result) => {\n var _a, _b, _c, _d;\n let autoConversionComponentsAssigned = false;\n if (((_a = result.data.formfields) === null || _a === void 0 ? void 0 : _a.components) && result.data.formfields.components.length) {\n const formInitState = ((_b = this.webform.form.components[0]) === null || _b === void 0 ? void 0 : _b.key) === 'submit';\n const wizardInitState = ((_c = this.webform.form.components[0]) === null || _c === void 0 ? void 0 : _c.key) === 'page1' &&\n ((_d = this.webform.form.components[0]) === null || _d === void 0 ? void 0 : _d.components.length) === 0;\n const emptyFormState = this.webform.form.components.length === 0;\n if (formInitState || wizardInitState || emptyFormState) {\n autoConversionComponentsAssigned = true;\n this.webform.form.components = result.data.formfields.components;\n }\n }\n if (this.refs.dragDropText) {\n this.refs.dragDropText.style.display = 'inherit';\n }\n if (this.refs.uploadProgressWrapper) {\n this.refs.uploadProgressWrapper.style.display = 'none';\n }\n lodash_1.default.set(this.webform.form, 'settings.pdf', {\n id: result.data.file,\n src: result.data.filesServer ? `${result.data.filesServer}${result.data.path}` : `${new URL(this.projectUrl).origin}/pdf-proxy${result.data.path}`,\n nonFillableConversionUsed: autoConversionComponentsAssigned && result.data.formfields.nonFillableConversionUsed\n });\n this.emit('pdfUploaded', result.data);\n this.redraw();\n })\n .catch((err) => this.setUploadError(err));\n }\n setUploadError(message) {\n if (!this.refs.uploadError) {\n return;\n }\n this.refs.uploadError.style.display = message ? '' : 'none';\n this.refs.uploadError.innerHTML = message;\n }\n createForm(options) {\n // Instantiate the webform from the PDF class instead of Webform\n options.skipInit = false;\n options.hideLoader = true;\n this.webform = new PDF_1.default(this.element, options);\n this.webform.on('attach', () => {\n // If the dropzone exists but has been removed in a PDF rebuild, reinstate it\n if (this.refs.iframeDropzone && ![...this.refs.form.children].includes(this.refs.iframeDropzone)) {\n this.prependTo(this.refs.iframeDropzone, this.refs.form);\n }\n });\n return this.webform;\n }\n destroy(all = false) {\n super.destroy(all);\n this.webform.destroy(all);\n }\n // d8b 8888888888 888\n // Y8P 888 888\n // 888 888\n // 888 8888888 888d888 8888b. 88888b.d88b. .d88b. .d88b. 888 888 .d88b. 88888b. 888888 .d8888b\n // 888 888 888P\" \"88b 888 \"888 \"88b d8P Y8b d8P Y8b 888 888 d8P Y8b 888 \"88b 888 88K\n // 888 888 888 .d888888 888 888 888 88888888 88888888 Y88 88P 88888888 888 888 888 \"Y8888b.\n // 888 888 888 888 888 888 888 888 Y8b. Y8b. Y8bd8P Y8b. 888 888 Y88b. X88\n // 888 888 888 \"Y888888 888 888 888 \"Y8888 \"Y8888 Y88P \"Y8888 888 888 \"Y888 88888P'\n getParentContainer(component) {\n let container = [];\n let originalComponent = null;\n (0, formUtils_1.eachComponent)(this.webform._form.components, (comp, path, components) => {\n if (comp.id === component.component.id) {\n container = components;\n originalComponent = comp;\n return true;\n }\n }, true);\n return {\n formioComponent: component.parent,\n formioContainer: container,\n originalComponent\n };\n }\n initIframeEvents() {\n this.webform.off('iframe-elementUpdate');\n this.webform.off('iframe-componentUpdate');\n this.webform.off('iframe-componentClick');\n this.webform.on('iframe-elementUpdate', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component && component.component) {\n const isNew = true;\n component.component.overlay = {\n page: schema.page,\n left: schema.left,\n top: schema.top,\n height: schema.height,\n width: schema.width\n };\n if (!this.options.noNewEdit && !component.component.noNewEdit) {\n this.editComponent(component.component, this.getParentContainer(component), isNew);\n }\n this.emit('updateComponent', component.component);\n }\n return component;\n });\n this.webform.on('iframe-componentUpdate', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component && component.component) {\n component.component.overlay = {\n page: schema.overlay.page,\n left: schema.overlay.left,\n top: schema.overlay.top,\n height: schema.overlay.height,\n width: schema.overlay.width\n };\n this.emit('updateComponent', component.component);\n this.emit('change', this.form);\n }\n return component;\n });\n this.webform.on('iframe-componentClick', schema => {\n const component = this.webform.getComponentById(schema.id);\n if (component) {\n this.editComponent(component.component, this.getParentContainer(component));\n }\n }, true);\n }\n // 8888888b. 888 d8b\n // 888 \"Y88b 888 Y8P\n // 888 888 888\n // 888 888 888d888 .d88b. 88888b. 88888888 .d88b. 88888b. .d88b. 888 .d88b. .d88b. 888 .d8888b\n // 888 888 888P\" d88\"\"88b 888 \"88b d88P d88\"\"88b 888 \"88b d8P Y8b 888 d88\"\"88b d88P\"88b 888 d88P\"\n // 888 888 888 888 888 888 888 d88P 888 888 888 888 88888888 888 888 888 888 888 888 888\n // 888 .d88P 888 Y88..88P 888 d88P d88P Y88..88P 888 888 Y8b. 888 Y88..88P Y88b 888 888 Y88b.\n // 8888888P\" 888 \"Y88P\" 88888P\" 88888888 \"Y88P\" 888 888 \"Y8888 888 \"Y88P\" \"Y88888 888 \"Y8888P\n // 888 888\n // 888 Y8b d88P\n // 888 \"Y88P\"\n initDropzoneEvents() {\n if (!this.refs.iframeDropzone) {\n return;\n }\n // This is required per HTML spec in order for the drop event to fire\n this.removeEventListener(this.refs.iframeDropzone, 'dragover');\n this.removeEventListener(this.refs.iframeDropzone, 'drop');\n this.addEventListener(this.refs.iframeDropzone, 'dragover', (e) => {\n e.preventDefault();\n return false;\n });\n this.addEventListener(this.refs.iframeDropzone, 'drop', this.onDropzoneDrop.bind(this));\n }\n updateDragAndDrop() {\n if (!this.pdfLoaded) {\n return;\n }\n this.initDropzoneEvents();\n this.prepSidebarComponentsForDrag();\n }\n prepSidebarComponentsForDrag() {\n if (!this.refs['sidebar-container']) {\n return;\n }\n this.refs['sidebar-container'].forEach(container => {\n [...container.children].forEach(el => {\n el.draggable = true;\n el.setAttribute('draggable', true);\n this.removeEventListener(el, 'dragstart');\n this.removeEventListener(el, 'dragend');\n this.addEventListener(el, 'dragstart', this.onDragStart.bind(this), true);\n this.addEventListener(el, 'dragend', this.onDragEnd.bind(this), true);\n this.addEventListener(el, 'drag', (e) => {\n e.target.style.cursor = 'none';\n });\n });\n });\n }\n updateDropzoneDimensions() {\n if (!this.refs.iframeDropzone) {\n return;\n }\n const iframeRect = (0, utils_1.getElementRect)(this.webform.refs.iframeContainer);\n this.refs.iframeDropzone.style.height = iframeRect && iframeRect.height ? `${iframeRect.height}px` : '1000px';\n this.refs.iframeDropzone.style.width = iframeRect && iframeRect.width ? `${iframeRect.width}px` : '100%';\n }\n onDragStart(e) {\n // Taking the current offset of a dragged item relative to the cursor\n const { offsetX = 0, offsetY = 0 } = e;\n this.itemOffsetX = offsetX;\n this.itemOffsetY = offsetY;\n e.dataTransfer.setData('text', '');\n this.updateDropzoneDimensions();\n this.addClass(this.refs.iframeDropzone, 'enabled');\n this.dropEmitted = false;\n }\n onDropzoneDrop(e) {\n this.dropEmitted = true;\n this.dropEvent = e;\n e.preventDefault();\n return false;\n }\n onDragEnd(e) {\n // IMPORTANT - must retrieve offsets BEFORE disabling the dropzone - offsets will\n // reflect absolute positioning if accessed after the target element is hidden\n const iframeRect = this.webform.refs.iframeContainer.getBoundingClientRect();\n const layerX = this.dropEvent ? this.dropEvent.layerX : null;\n const layerY = this.dropEvent ? this.dropEvent.layerY : null;\n const WIDTH = 100;\n const HEIGHT = 20;\n // Always disable the dropzone on drag end\n this.removeClass(this.refs.iframeDropzone, 'enabled');\n // If there hasn't been a drop event on the dropzone, we're done\n if (!this.dropEvent) {\n // a 'drop' event may not be emited in the chrome browser when using a Mac, therefore an additional check has been added\n // eslint-disable-next-line no-undef\n if (!this.dropEmitted && ((0, utils_1.getBrowserInfo)().chrome || (0, utils_1.getBrowserInfo)().edge) && globalThis.navigator.userAgentData.platform === 'macOS' && iframeRect.left < e.clientX && iframeRect.top < e.clientY) {\n this.dropEvent = e;\n this.dropEvent.dataTransfer.effectAllowed = 'all';\n this.dropEmitted = true;\n }\n else {\n return;\n }\n }\n const element = e.target;\n const type = element.getAttribute('data-type');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const schema = (0, utils_1.fastCloneDeep)(this.schemas[type]);\n if (key && group) {\n const info = this.getComponentInfo(key, group);\n lodash_1.default.merge(schema, info);\n }\n // Set a unique key for this component.\n builder_1.default.uniquify([this.webform._form], schema);\n this.webform._form.components.push(schema);\n schema.overlay = {\n top: layerY ? (layerY - this.itemOffsetY + HEIGHT) : (e.clientY - iframeRect.top - (this.itemOffsetY - HEIGHT) * 2),\n left: layerX ? (layerX - this.itemOffsetX) : (e.clientX - iframeRect.left - this.itemOffsetX * 2),\n width: WIDTH,\n height: HEIGHT\n };\n this.webform.addComponent(schema, {}, null, true);\n this.webform.postMessage({ name: 'addElement', data: schema });\n this.emit('addComponent', schema, this.webform, schema.key, this.webform.component.components.length, !this.options.noNewEdit && !schema.noNewEdit);\n // Delete the stored drop event now that it's been handled\n this.dropEvent = null;\n e.target.style.cursor = 'default';\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n // update elements which path was duplicated if any pathes have been changed\n if (!lodash_1.default.isEqual(this.repeatablePaths, repeatablePaths)) {\n (0, formUtils_1.eachComponent)(this.webform.getComponents(), (comp, path) => {\n if (this.repeatablePaths.includes(path)) {\n this.webform.postMessage({ name: 'updateElement', data: comp.component });\n }\n });\n this.repeatablePaths = repeatablePaths;\n }\n if (!repeatablePaths.length) {\n return;\n }\n (0, formUtils_1.eachComponent)(this.webform.getComponents(), (comp, path) => {\n if (this.repeatablePaths.includes(path)) {\n this.webform.postMessage({\n name: 'showBuilderErrors',\n data: {\n compId: comp.component.id,\n errorMessage: `API Key is not unique: ${comp.key}`,\n }\n });\n }\n });\n }\n}\nexports[\"default\"] = PDFBuilder;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/PDFBuilder.js?");
5546
5556
 
5547
5557
  /***/ }),
5548
5558
 
@@ -5553,7 +5563,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5553
5563
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5554
5564
 
5555
5565
  "use strict";
5556
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst compare_versions_1 = __webpack_require__(/*! compare-versions */ \"./node_modules/compare-versions/lib/esm/index.js\");\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst i18n_1 = __importDefault(__webpack_require__(/*! ./i18n */ \"./lib/cjs/i18n.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst NestedDataComponent_1 = __importDefault(__webpack_require__(/*! ./components/_classes/nesteddata/NestedDataComponent */ \"./lib/cjs/components/_classes/nesteddata/NestedDataComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\n// Initialize the available forms.\nFormio_1.Formio.forms = {};\n// Allow people to register components.\nFormio_1.Formio.registerComponent = Components_1.default.setComponent;\nfunction getIconSet(icons) {\n if (icons === 'fontawesome') {\n return 'fa';\n }\n return icons || '';\n}\nfunction getOptions(options) {\n options = lodash_1.default.defaults(options, {\n submitOnEnter: false,\n iconset: getIconSet((options && options.icons) ? options.icons : Formio_1.Formio.icons),\n i18next: null,\n saveDraft: false,\n alwaysDirty: false,\n saveDraftThrottle: 5000,\n display: 'form',\n cdnUrl: Formio_1.Formio.cdn.baseUrl\n });\n if (!options.events) {\n options.events = new EventEmitter_1.default();\n }\n return options;\n}\n/**\n * Represents a JSON value.\n * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON\n */\n/**\n * Represents a JSON array.\n * @typedef {Array<JSON>} JSONArray\n */\n/**\n * Represents a JSON object.\n * @typedef {{[key: string]: JSON}} JSONObject\n */\n/**\n * @typedef {Object} FormioHooks\n * @property {function} [beforeSubmit]\n * @property {function} [beforeCancel]\n * @property {function} [beforeNext]\n * @property {function} [beforePrev]\n * @property {function} [attachComponent]\n * @property {function} [setDataValue]\n * @property {function} [addComponents]\n * @property {function} [addComponent]\n * @property {function} [customValidation]\n * @property {function} [attachWebform]\n */\n/**\n * @typedef {Object} SanitizeConfig\n * @property {string[]} [addAttr]\n * @property {string[]} [addTags]\n * @property {string[]} [allowedAttrs]\n * @property {string[]} [allowedTags]\n * @property {string[]} [allowedUriRegex]\n * @property {string[]} [addUriSafeAttr]\n */\n/**\n * @typedef {Object} ButtonSettings\n * @property {boolean} [showPrevious]\n * @property {boolean} [showNext]\n * @property {boolean} [showCancel]\n * @property {boolean} [showSubmit]\n */\n/**\n * @typedef {Object} FormOptions\n * @property {boolean} [saveDraft] - Enable the save draft feature.\n * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.\n * @property {boolean} [readOnly] - Set this form to readOnly.\n * @property {boolean} [noAlerts] - Disable the alerts dialog.\n * @property {{[key: string]: string}} [i18n] - The translation file for this rendering.\n * @property {string} [template] - Custom logic for creation of elements.\n * @property {boolean} [noDefaults] - Exclude default values from the settings.\n * @property {any} [fileService] - The file service for this form.\n * @property {EventEmitter} [events] - The EventEmitter for this form.\n * @property {string} [language] - The language to render this form in.\n * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form.\n * @property {boolean} [viewAsHtml] - View the form as raw HTML.\n * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form.\n * @property {boolean} [highlightErrors] - Highlight any errors on the form.\n * @property {string} [componentErrorClass] - The error class for components.\n * @property {any} [templates] - The templates for this form.\n * @property {string} [iconset] - The iconset for this form.\n * @property {Component[]} [components] - The components for this form.\n * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form.\n * @property {boolean} [showHiddenFields] - Show hidden fields.\n * @property {{[key: string]: boolean}} [hide] - Hidden components for this form.\n * @property {{[key: string]: boolean}} [show] - Components to show for this form.\n * @property {Formio} [formio] - The Formio instance for this form.\n * @property {string} [decimalSeparator] - The decimal separator for this form.\n * @property {string} [thousandsSeparator] - The thousands separator for this form.\n * @property {FormioHooks} [hooks] - The hooks for this form.\n * @property {boolean} [alwaysDirty] - Always be dirty.\n * @property {boolean} [skipDraftRestore] - Skip restoring a draft.\n * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form.\n * @property {string} [cdnUrl] - The CDN url for this form.\n * @property {boolean} [flatten] - Flatten the form.\n * @property {boolean} [sanitize] - Sanitize the form.\n * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form.\n * @property {ButtonSettings} [buttonSettings] - The button settings for this form.\n * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form.\n * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms).\n * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms).\n * @property {boolean} [showCheckboxBackground] - Show the checkbox background.\n * @property {number} [zoom] - The zoom for PDF forms.\n */\n/**\n * Renders a Form.io form within the webpage.\n */\nclass Webform extends NestedDataComponent_1.default {\n /**\n * Creates a new Form instance.\n *\n * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance.\n * @param {FormOptions} [options] - The options to create a new form instance.\n */\n constructor(elementOrOptions, options) {\n let element, formOptions;\n if (elementOrOptions instanceof HTMLElement || options) {\n element = elementOrOptions;\n formOptions = options;\n }\n else {\n formOptions = elementOrOptions;\n }\n super(null, getOptions(formOptions));\n this.executeShortcuts = (event) => {\n const { target } = event;\n if (!this.keyboardCatchableElement(target)) {\n return;\n }\n const ctrl = event.ctrlKey || event.metaKey;\n const keyCode = event.keyCode;\n let char = '';\n if (65 <= keyCode && keyCode <= 90) {\n char = String.fromCharCode(keyCode);\n }\n else if (keyCode === 13) {\n char = 'Enter';\n }\n else if (keyCode === 27) {\n char = 'Esc';\n }\n lodash_1.default.each(this.shortcuts, (shortcut) => {\n if (shortcut.ctrl && !ctrl) {\n return;\n }\n if (shortcut.shortcut === char) {\n shortcut.element.click();\n event.preventDefault();\n }\n });\n };\n this.element = element;\n // Keep track of all available forms globally.\n Formio_1.Formio.forms[this.id] = this;\n // Set the base url.\n if (this.options.baseUrl) {\n Formio_1.Formio.setBaseUrl(this.options.baseUrl);\n }\n /**\n * The type of this element.\n * @type {string}\n */\n this.type = 'form';\n this._src = '';\n this._loading = false;\n this._form = {};\n this.draftEnabled = false;\n this.savingDraft = true;\n if (this.options.saveDraftThrottle) {\n this.triggerSaveDraft = lodash_1.default.throttle(this.saveDraft.bind(this), this.options.saveDraftThrottle);\n }\n else {\n this.triggerSaveDraft = this.saveDraft.bind(this);\n }\n /**\n * Determines if this form should submit the API on submit.\n * @type {boolean}\n */\n this.nosubmit = false;\n /**\n * Determines if the form has tried to be submitted, error or not.\n *\n * @type {boolean}\n */\n this.submitted = false;\n /**\n * Determines if the form is being submitted at the moment.\n *\n * @type {boolean}\n */\n this.submitting = false;\n /**\n * The Formio instance for this form.\n * @type {Formio}\n */\n this.formio = null;\n /**\n * The loader HTML element.\n * @type {HTMLElement}\n */\n this.loader = null;\n /**\n * The alert HTML element\n * @type {HTMLElement}\n */\n this.alert = null;\n /**\n * Promise that is triggered when the submission is done loading.\n * @type {Promise}\n */\n this.onSubmission = null;\n /**\n * Determines if this submission is explicitly set.\n * @type {boolean}\n */\n this.submissionSet = false;\n /**\n * Promise that executes when the form is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is ready!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n this.formReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.formReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.formReadyReject = reject;\n });\n /**\n * Promise that executes when the submission is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.submissionReady.then(() => {\n * console.log('The submission is ready!');\n * });\n * form.src = 'https://examples.form.io/example/submission/234234234234234243';\n */\n this.submissionReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.submissionReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.submissionReadyReject = reject;\n });\n this.shortcuts = [];\n // Set language after everything is established.\n this.language = this.i18next.language;\n // See if we need to restore the draft from a user.\n if (this.options.saveDraft) {\n this.formReady.then(() => {\n if (!this.options.skipDraftRestore) {\n const user = Formio_1.Formio.getUser();\n // Only restore a draft if the submission isn't explicitly set.\n if (user && !this.submissionSet) {\n this.restoreDraft(user._id);\n }\n }\n else {\n // Enable drafts\n this.draftEnabled = true;\n this.savingDraft = false;\n }\n });\n }\n this.component.clearOnHide = false;\n // Ensure the root is set to this component.\n this.root = this;\n this.localRoot = this;\n }\n /* eslint-enable max-statements */\n get language() {\n return this.options.language;\n }\n get emptyValue() {\n return null;\n }\n componentContext() {\n return this._data;\n }\n /**\n * Sets the language for this form.\n *\n * @param lang\n * @return {Promise}\n */\n set language(lang) {\n if (!this.i18next) {\n return;\n }\n this.options.language = lang;\n if (this.i18next.language === lang) {\n return;\n }\n this.i18next.changeLanguage(lang, (err) => {\n if (err) {\n return;\n }\n this.rebuild();\n this.emit('languageChanged');\n });\n }\n get componentComponents() {\n return this.form.components;\n }\n get shadowRoot() {\n return this.options.shadowRoot;\n }\n /**\n * Add a language for translations\n *\n * @param code\n * @param lang\n * @param active\n * @return {*}\n */\n addLanguage(code, lang, active = false) {\n var translations = lodash_1.default.assign((0, utils_1.fastCloneDeep)(i18n_1.default.resources.en.translation), lang);\n this.i18next.addResourceBundle(code, 'translation', translations, true, true);\n if (active) {\n this.language = code;\n }\n }\n keyboardCatchableElement(element) {\n if (element.nodeName === 'TEXTAREA') {\n return false;\n }\n if (element.nodeName === 'INPUT') {\n return [\n 'text',\n 'email',\n 'password'\n ].indexOf(element.type) === -1;\n }\n return true;\n }\n addShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n shortcut = lodash_1.default.capitalize(shortcut);\n if (shortcut === 'Enter' || shortcut === 'Esc') {\n // Restrict Enter and Esc only for buttons\n if (element.tagName !== 'BUTTON') {\n return;\n }\n this.shortcuts.push({\n shortcut,\n element\n });\n }\n else {\n this.shortcuts.push({\n ctrl: true,\n shortcut,\n element\n });\n }\n }\n removeShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n lodash_1.default.remove(this.shortcuts, {\n shortcut,\n element\n });\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get src() {\n return this._src;\n }\n /**\n * Loads the submission if applicable.\n */\n loadSubmission() {\n this.loadingSubmission = true;\n if (this.formio.submissionId) {\n this.onSubmission = this.formio.loadSubmission().then((submission) => this.setSubmission(submission), (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n else {\n this.submissionReadyResolve();\n }\n return this.submissionReady;\n }\n /**\n * Set the src of the form renderer.\n *\n * @param value\n * @param options\n */\n setSrc(value, options) {\n if (this.setUrl(value, options)) {\n this.nosubmit = false;\n return this.formio.loadForm({ params: { live: 1 } }).then((form) => {\n const setForm = this.setForm(form);\n this.loadSubmission();\n return setForm;\n }).catch((err) => {\n console.warn(err);\n this.formReadyReject(err);\n });\n }\n return Promise.resolve();\n }\n /**\n * Set the Form source, which is typically the Form.io embed URL.\n *\n * @param {string} value - The value of the form embed url.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is formReady!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n set src(value) {\n this.setSrc(value);\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get url() {\n return this._src;\n }\n /**\n * Sets the url of the form renderer.\n *\n * @param value\n * @param options\n */\n setUrl(value, options) {\n if (!value ||\n (typeof value !== 'string') ||\n (value === this._src)) {\n return false;\n }\n this._src = value;\n this.nosubmit = true;\n this.formio = this.options.formio = new Formio_1.Formio(value, options);\n if (this.type === 'form') {\n // Set the options source so this can be passed to other components.\n this.options.src = value;\n }\n return true;\n }\n /**\n * Set the form source but don't initialize the form and submission from the url.\n *\n * @param {string} value - The value of the form embed url.\n */\n set url(value) {\n this.setUrl(value);\n }\n /**\n * Called when both the form and submission have been loaded.\n *\n * @returns {Promise} - The promise to trigger when both form and submission have loaded.\n */\n get ready() {\n return this.formReady.then(() => {\n return super.ready.then(() => {\n return this.loadingSubmission ? this.submissionReady : true;\n });\n });\n }\n /**\n * Returns if this form is loading.\n *\n * @returns {boolean} - TRUE means the form is loading, FALSE otherwise.\n */\n get loading() {\n return this._loading;\n }\n /**\n * Set the loading state for this form, and also show the loader spinner.\n *\n * @param {boolean} loading - If this form should be \"loading\" or not.\n */\n set loading(loading) {\n if (this._loading !== loading) {\n this._loading = loading;\n if (!this.loader && loading) {\n this.loader = this.ce('div', {\n class: 'loader-wrapper'\n });\n const spinner = this.ce('div', {\n class: 'loader text-center'\n });\n this.loader.appendChild(spinner);\n }\n /* eslint-disable max-depth */\n if (this.loader) {\n try {\n if (loading) {\n this.prependTo(this.loader, this.wrapper);\n }\n else {\n this.removeChildFrom(this.loader, this.wrapper);\n }\n }\n catch (err) {\n // ingore\n }\n }\n /* eslint-enable max-depth */\n }\n }\n /**\n * Sets the JSON schema for the form to be rendered.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.setForm({\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name',\n * placeholder: 'Enter your first name.',\n * input: true\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name',\n * placeholder: 'Enter your last name',\n * input: true\n * },\n * {\n * type: 'button',\n * action: 'submit',\n * label: 'Submit',\n * theme: 'primary'\n * }\n * ]\n * });\n *\n * @param {Object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema.\n * @param flags\n * @returns {*}\n */\n setForm(form, flags) {\n var _a, _b, _c;\n const isFormAlreadySet = this._form && ((_a = this._form.components) === null || _a === void 0 ? void 0 : _a.length);\n try {\n // Do not set the form again if it has been already set\n if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) {\n return Promise.resolve();\n }\n // Create the form.\n this._form = (flags === null || flags === void 0 ? void 0 : flags.keepAsReference) ? form : lodash_1.default.cloneDeep(form);\n if (this.onSetForm) {\n this.onSetForm(lodash_1.default.cloneDeep(this._form), form);\n }\n if ((_c = (_b = this.parent) === null || _b === void 0 ? void 0 : _b.component) === null || _c === void 0 ? void 0 : _c.modalEdit) {\n return Promise.resolve();\n }\n }\n catch (err) {\n console.warn(err);\n // If provided form is not a valid JSON object, do not set it too\n return Promise.resolve();\n }\n // Allow the form to provide component overrides.\n if (form && form.settings && form.settings.components) {\n this.options.components = form.settings.components;\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options\n if (!this.options.sanitizeConfig && !this.builderMode) {\n this.options.sanitizeConfig = lodash_1.default.get(form, 'settings.sanitizeConfig') || lodash_1.default.get(form, 'globalSettings.sanitizeConfig');\n }\n if ('schema' in form && (0, compare_versions_1.compareVersions)(form.schema, '1.x') > 0) {\n this.ready.then(() => {\n this.setAlert('alert alert-danger', 'Form schema is for a newer version, please upgrade your renderer. Some functionality may not work.');\n });\n }\n // See if they pass a module, and evaluate it if so.\n if (form && form.module) {\n let formModule = null;\n if (typeof form.module === 'string') {\n try {\n formModule = this.evaluate(`return ${form.module}`);\n }\n catch (err) {\n console.warn(err);\n }\n }\n else {\n formModule = form.module;\n }\n if (formModule) {\n Formio_1.Formio.use(formModule);\n // Since we got here after instantiation, we need to manually apply form options.\n if (formModule.options && formModule.options.form) {\n this.options = Object.assign(this.options, formModule.options.form);\n }\n }\n }\n this.initialized = false;\n const rebuild = this.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n this.emit('formLoad', form);\n this.triggerRecaptcha();\n // Make sure to trigger onChange after a render event occurs to speed up form rendering.\n setTimeout(() => {\n this.onChange(flags);\n this.formReadyResolve();\n }, 0);\n return this.formReady;\n });\n }\n /**\n * Gets the form object.\n *\n * @returns {Object} - The form JSON schema.\n */\n get form() {\n if (!this._form) {\n this._form = {\n components: []\n };\n }\n return this._form;\n }\n /**\n * Sets the form value.\n *\n * @alias setForm\n * @param {Object} form - The form schema object.\n */\n set form(form) {\n this.setForm(form);\n }\n /**\n * Returns the submission object that was set within this form.\n *\n * @returns {Object}\n */\n get submission() {\n return this.getValue();\n }\n /**\n * Sets the submission of a form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n *\n * @param {Object} submission - The Form.io submission object.\n */\n set submission(submission) {\n this.setSubmission(submission);\n }\n /**\n * Sets a submission and returns the promise when it is ready.\n * @param submission\n * @param flags\n * @return {Promise.<TResult>}\n */\n setSubmission(submission, flags = {}) {\n flags = Object.assign(Object.assign({}, flags), { fromSubmission: lodash_1.default.has(flags, 'fromSubmission') ? flags.fromSubmission : true });\n return this.onSubmission = this.formReady.then((resolveFlags) => {\n if (resolveFlags) {\n flags = Object.assign(Object.assign({}, flags), resolveFlags);\n }\n this.submissionSet = true;\n this.triggerChange(flags);\n this.emit('beforeSetSubmission', submission);\n this.setValue(submission, flags);\n return this.submissionReadyResolve(submission);\n }, (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n handleDraftError(errName, errDetails, restoreDraft) {\n const errorMessage = lodash_1.default.trim(`${this.t(errName)} ${errDetails || ''}`);\n console.warn(errorMessage);\n this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage);\n }\n /**\n * Saves a submission draft.\n */\n saveDraft() {\n if (!this.draftEnabled) {\n return;\n }\n if (!this.formio) {\n this.handleDraftError('saveDraftInstanceError');\n return;\n }\n if (!Formio_1.Formio.getUser()) {\n this.handleDraftError('saveDraftAuthError');\n return;\n }\n const draft = (0, utils_1.fastCloneDeep)(this.submission);\n draft.state = 'draft';\n if (!this.savingDraft && !this.submitting) {\n this.emit('saveDraftBegin');\n this.savingDraft = true;\n this.formio.saveSubmission(draft).then((sub) => {\n // Set id to submission to avoid creating new draft submission\n this.submission._id = sub._id;\n this.savingDraft = false;\n this.emit('saveDraft', sub);\n })\n .catch(err => {\n this.savingDraft = false;\n this.handleDraftError('saveDraftError', err);\n });\n }\n }\n /**\n * Restores a draft submission based on the user who is authenticated.\n *\n * @param {userId} - The user id where we need to restore the draft from.\n */\n restoreDraft(userId) {\n const formio = this.formio || this.options.formio;\n if (!formio) {\n this.handleDraftError('restoreDraftInstanceError', null, true);\n return;\n }\n this.savingDraft = true;\n formio.loadSubmissions({\n params: {\n state: 'draft',\n owner: userId\n }\n }).then(submissions => {\n if (submissions.length > 0 && !this.options.skipDraftRestore) {\n const draft = (0, utils_1.fastCloneDeep)(submissions[0]);\n return this.setSubmission(draft).then(() => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', draft);\n });\n }\n // Enable drafts so that we can keep track of changes.\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', null);\n })\n .catch(err => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.handleDraftError('restoreDraftError', err, true);\n });\n }\n get schema() {\n const schema = (0, utils_1.fastCloneDeep)(lodash_1.default.omit(this._form, ['components']));\n schema.components = [];\n this.eachComponent((component) => schema.components.push(component.schema));\n return schema;\n }\n mergeData(_this, _that) {\n lodash_1.default.mergeWith(_this, _that, (thisValue, thatValue) => {\n if (Array.isArray(thisValue) && Array.isArray(thatValue) && thisValue.length !== thatValue.length) {\n return thatValue;\n }\n });\n }\n setValue(submission, flags = {}) {\n if (!submission || !submission.data) {\n submission = {\n data: {},\n metadata: submission.metadata,\n };\n }\n // Metadata needs to be available before setValue\n this._submission.metadata = submission.metadata || {};\n this.editing = !!submission._id;\n // Set the timezone in the options if available.\n if (!this.options.submissionTimezone &&\n submission.metadata &&\n submission.metadata.timezone) {\n this.options.submissionTimezone = submission.metadata.timezone;\n }\n const changed = super.setValue(submission.data, flags);\n if (!flags.sanitize) {\n this.mergeData(this.data, submission.data);\n }\n submission.data = this.data;\n this._submission = submission;\n return changed;\n }\n getValue() {\n if (!this._submission.data) {\n this._submission.data = {};\n }\n if (this.viewOnly) {\n return this._submission;\n }\n const submission = this._submission;\n submission.data = this.data;\n return this._submission;\n }\n /**\n * Build the form.\n */\n init() {\n if (this.options.submission) {\n const submission = lodash_1.default.extend({}, this.options.submission);\n this._submission = submission;\n this._data = submission.data;\n }\n else {\n this._submission = this._submission || { data: {} };\n }\n // Remove any existing components.\n if (this.components && this.components.length) {\n this.destroyComponents();\n this.components = [];\n }\n if (this.component) {\n this.component.components = this.form ? this.form.components : [];\n }\n else {\n this.component = this.form;\n }\n this.component.type = 'form';\n this.component.input = false;\n this.addComponents();\n this.on('submitButton', options => {\n this.submit(false, options).catch(e => {\n options.instance.loading = false;\n return e !== false && e !== undefined && console.log(e);\n });\n }, true);\n this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true);\n this.on('requestUrl', (args) => (this.submitUrl(args.url, args.headers)), true);\n this.on('resetForm', () => this.resetValue(), true);\n this.on('deleteSubmission', () => this.deleteSubmission(), true);\n this.on('refreshData', () => this.updateValue(), true);\n this.executeFormController();\n return this.formReady;\n }\n executeFormController() {\n // If no controller value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n if (!this.form || !this.form.controller\n || ((!this.visible || this.component.hidden) && this.component.clearOnHide && !this.rootPristine)) {\n return false;\n }\n this.formReady.then(() => {\n this.evaluate(this.form.controller, {\n components: this.components,\n instance: this,\n });\n });\n }\n destroy(deleteFromGlobal = false) {\n this.off('submitButton');\n this.off('checkValidity');\n this.off('requestUrl');\n this.off('resetForm');\n this.off('deleteSubmission');\n this.off('refreshData');\n if (deleteFromGlobal) {\n this.emit('formDelete', this.id);\n delete Formio_1.Formio.forms[this.id];\n }\n return super.destroy();\n }\n build(element) {\n if (element || this.element) {\n return this.ready.then(() => {\n element = element || this.element;\n super.build(element);\n });\n }\n return this.ready;\n }\n getClassName() {\n let classes = 'formio-form';\n if (this.options.readOnly) {\n classes += ' formio-read-only';\n }\n return classes;\n }\n render() {\n return super.render(this.renderTemplate('webform', {\n classes: this.getClassName(),\n children: this.renderComponents(),\n }), this.builderMode ? 'builder' : 'form', true);\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element) {\n return Promise.resolve();\n }\n this.clear();\n this.setContent(this.element, this.render());\n return this.attach(this.element);\n }\n attach(element) {\n this.element = element;\n this.loadRefs(element, { webform: 'single' });\n const childPromise = this.attachComponents(this.refs.webform);\n this.addEventListener(document, 'keydown', this.executeShortcuts);\n this.currentForm = this;\n this.hook('attachWebform', element, this);\n return childPromise.then(() => {\n this.emit('render', this.element);\n return this.setValue(this._submission, {\n noUpdateEvent: true,\n });\n });\n }\n hasRequiredFields() {\n let result = false;\n (0, formUtils_1.eachComponent)(this.form.components, (component) => {\n if (component.validate.required) {\n result = true;\n return true;\n }\n }, true);\n return result;\n }\n resetValue() {\n lodash_1.default.each(this.getComponents(), (comp) => (comp.resetValue()));\n this.setPristine(true);\n this.onChange({ resetValue: true });\n }\n /**\n * Sets a new alert to display in the error dialog of the form.\n *\n * @param {string} type - The type of alert to display. \"danger\", \"success\", \"warning\", etc.\n * @param {string} message - The message to show in the alert.\n * @param {Object} options\n */\n setAlert(type, message, options) {\n if (!type && this.submitted) {\n if (this.alert) {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n return;\n }\n if (this.options.noAlerts) {\n if (!message) {\n this.emit('error', false);\n }\n return;\n }\n if (this.alert) {\n try {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n catch (err) {\n // ignore\n }\n }\n if (message) {\n const attrs = {\n class: (options && options.classes) || `alert alert-${type}`,\n id: `error-list-${this.id}`,\n };\n const templateOptions = {\n message: message instanceof HTMLElement ? message.outerHTML : message,\n attrs: attrs,\n type\n };\n this.alert = (0, utils_1.convertStringToHTMLElement)(this.renderTemplate('alert', templateOptions), `#${attrs.id}`);\n }\n if (!this.alert) {\n return;\n }\n this.loadRefs(this.alert, { errorRef: 'multiple' });\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.addEventListener(el, 'click', (e) => {\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n });\n this.addEventListener(el, 'keydown', (e) => {\n if (e.keyCode === 13) {\n e.preventDefault();\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n }\n });\n });\n }\n this.prepend(this.alert);\n }\n /**\n * Focus on selected component.\n *\n * @param {string} key - The key of selected component.\n * @returns {*}\n */\n focusOnComponent(key) {\n if (key) {\n const component = this.getComponent(key);\n if (component) {\n component.focus();\n }\n }\n }\n /**\n * Show the errors of this form within the alert dialog.\n *\n * @param {Object} error - An optional additional error to display along with the component errors.\n * @returns {*}\n */\n /* eslint-disable no-unused-vars */\n showErrors(errors, triggerEvent) {\n this.loading = false;\n if (!Array.isArray(errors)) {\n errors = [errors];\n }\n errors = errors.concat(this.customErrors).filter((err) => !!err);\n if (!errors.length) {\n this.setAlert(false);\n return;\n }\n // Mark any components as invalid if in a custom message.\n errors.forEach((err) => {\n const { components = [] } = err;\n if (err.component) {\n components.push(err.component);\n }\n if (err.path) {\n components.push(err.path);\n }\n components.forEach((path) => {\n const originalPath = (0, utils_1.getStringFromComponentPath)(path);\n const component = this.getComponent(path, lodash_1.default.identity, originalPath);\n if (err.fromServer) {\n if (component.serverErrors) {\n component.serverErrors.push(err);\n }\n else {\n component.serverErrors = [err];\n }\n }\n const components = lodash_1.default.compact(Array.isArray(component) ? component : [component]);\n components.forEach((component) => component.setCustomValidity(err.message, true));\n });\n });\n const displayedErrors = [];\n if (errors.length) {\n errors = lodash_1.default.uniqBy(errors, error => error.message);\n const createListItem = (message, index) => {\n var _a, _b, _c;\n const err = errors[index];\n const messageFromIndex = !lodash_1.default.isUndefined(index) && errors && errors[index];\n const keyOrPath = ((messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.formattedKeyOrPath) || (messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.path) || ((_a = messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.context) === null || _a === void 0 ? void 0 : _a.path)) || (((_b = err.context) === null || _b === void 0 ? void 0 : _b.component) && ((_c = err.context) === null || _c === void 0 ? void 0 : _c.component.key)) || (err.component && err.component.key) || err.fromServer && err.path;\n const formattedKeyOrPath = keyOrPath ? (0, utils_1.getStringFromComponentPath)(keyOrPath) : '';\n if (typeof err !== 'string' && !err.formattedKeyOrPath) {\n err.formattedKeyOrPath = formattedKeyOrPath;\n }\n return {\n message: (0, utils_1.unescapeHTML)(message),\n keyOrPath: formattedKeyOrPath\n };\n };\n errors.forEach(({ message, context, fromServer, component }, index) => {\n const text = !(component === null || component === void 0 ? void 0 : component.label) || (context === null || context === void 0 ? void 0 : context.hasLabel) || fromServer\n ? this.t('alertMessage', { message: this.t(message) })\n : this.t('alertMessageWithLabel', {\n label: this.t(component === null || component === void 0 ? void 0 : component.label),\n message: this.t(message),\n });\n displayedErrors.push(createListItem(text, index));\n });\n }\n const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });\n this.root.setAlert('danger', errorsList);\n if (triggerEvent) {\n this.emit('error', errors);\n }\n return errors;\n }\n /* eslint-enable no-unused-vars */\n /**\n * Called when the submission has completed, or if the submission needs to be sent to an external library.\n *\n * @param {Object} submission - The submission object.\n * @param {boolean} saved - Whether or not this submission was saved to the server.\n * @returns {object} - The submission object.\n */\n onSubmit(submission, saved) {\n var _a;\n this.loading = false;\n this.submitting = false;\n this.setPristine(true);\n // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here.\n this.setValue((0, utils_1.fastCloneDeep)(submission), {\n noValidate: true,\n noCheck: true\n });\n this.setAlert('success', `<p>${this.t('complete')}</p>`);\n // Cancel triggered saveDraft to prevent overriding the submitted state\n if (this.draftEnabled && ((_a = this.triggerSaveDraft) === null || _a === void 0 ? void 0 : _a.cancel)) {\n this.triggerSaveDraft.cancel();\n }\n this.emit('submit', submission, saved);\n if (saved) {\n this.emit('submitDone', submission);\n }\n return submission;\n }\n normalizeError(error) {\n if (error) {\n if (typeof error === 'object' && 'details' in error) {\n error = error.details;\n }\n if (typeof error === 'string') {\n error = { message: error };\n }\n }\n return error;\n }\n /**\n * Called when an error occurs during the submission.\n *\n * @param {Object} error - The error that occured.\n */\n onSubmissionError(error) {\n error = this.normalizeError(error);\n this.submitting = false;\n this.setPristine(false);\n this.emit('submitError', error || this.errors);\n // Allow for silent cancellations (no error message, no submit button error state)\n if (error && error.silent) {\n this.emit('change', { isValid: true }, { silent: true });\n return false;\n }\n const errors = this.showErrors(error, true);\n if (this.root && this.root.alert) {\n this.scrollIntoView(this.root.alert);\n }\n return errors;\n }\n /**\n * Trigger the change event for this form.\n *\n * @param changed\n * @param flags\n */\n onChange(flags, changed, modified, changes) {\n flags = flags || {};\n let isChangeEventEmitted = false;\n super.onChange(flags, true);\n const value = lodash_1.default.clone(this.submission);\n flags.changed = value.changed = changed;\n flags.changes = changes;\n if (modified && this.pristine) {\n this.pristine = false;\n }\n this.checkData(value.data, flags);\n const shouldValidate = !flags.noValidate || flags.fromIFrame || (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed);\n const errors = shouldValidate ? this.validate(value.data, Object.assign(Object.assign({}, flags), { process: 'change' })) : [];\n value.isValid = errors.length === 0;\n this.loading = false;\n if (this.submitted) {\n // show server errors while they are not cleaned/fixed\n const nonComponentServerErrors = lodash_1.default.filter(this.serverErrors || [], err => !err.component && !err.path);\n this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors);\n }\n // See if we need to save the draft of the form.\n if (modified && this.options.saveDraft) {\n this.triggerSaveDraft();\n }\n if (!flags || !flags.noEmit) {\n this.emit('change', value, flags, modified);\n isChangeEventEmitted = true;\n }\n // The form is initialized after the first change event occurs.\n if (isChangeEventEmitted && !this.initialized) {\n this.emit('initialized');\n this.initialized = true;\n }\n }\n /**\n * Send a delete request to the server.\n */\n deleteSubmission() {\n return this.formio.deleteSubmission()\n .then(() => {\n this.emit('submissionDeleted', this.submission);\n this.resetValue();\n });\n }\n /**\n * Cancels the submission.\n *\n * @alias reset\n */\n cancel(noconfirm) {\n const shouldReset = this.hook('beforeCancel', true);\n if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) {\n this.resetValue();\n return true;\n }\n else {\n this.emit('cancelSubmit');\n return false;\n }\n }\n setMetadata(submission) {\n // Add in metadata about client submitting the form\n submission.metadata = submission.metadata || {};\n lodash_1.default.defaults(submission.metadata, {\n timezone: lodash_1.default.get(this, '_submission.metadata.timezone', (0, utils_1.currentTimezone)()),\n offset: parseInt(lodash_1.default.get(this, '_submission.metadata.offset', (0, moment_1.default)().utcOffset()), 10),\n origin: document.location.origin,\n referrer: document.referrer,\n browserName: navigator.appName,\n userAgent: navigator.userAgent,\n pathName: window.location.pathname,\n onLine: navigator.onLine\n });\n }\n submitForm(options = {}) {\n this.clearServerErrors();\n return new Promise((resolve, reject) => {\n // Read-only forms should never submit.\n if (this.options.readOnly) {\n return resolve({\n submission: this.submission,\n saved: false\n });\n }\n const submission = (0, utils_1.fastCloneDeep)(this.submission || {});\n this.setMetadata(submission);\n submission.state = options.state || submission.state || 'submitted';\n const isDraft = (submission.state === 'draft');\n this.hook('beforeSubmit', Object.assign(Object.assign({}, submission), { component: options.component }), (err, data) => {\n var _a;\n if (err) {\n return reject(err);\n }\n submission._vnote = data && data._vnote ? data._vnote : '';\n try {\n if (!isDraft && !options.noValidate) {\n if (!submission.data) {\n return reject('Invalid Submission');\n }\n const errors = this.validate(submission.data, {\n dirty: true,\n silentCheck: false,\n process: 'submit'\n });\n if (errors.length || ((_a = options.beforeSubmitResults) === null || _a === void 0 ? void 0 : _a.some((result) => result.status === 'rejected'))) {\n return reject(errors);\n }\n }\n }\n catch (err) {\n console.error(err);\n }\n this.everyComponent((comp) => {\n if (submission._vnote && comp.type === 'form' && comp.component.reference) {\n lodash_1.default.get(submission.data, comp.path, {})._vnote = submission._vnote;\n }\n const { persistent } = comp.component;\n if (persistent === 'client-only') {\n lodash_1.default.unset(submission.data, comp.path);\n }\n });\n this.hook('customValidation', Object.assign(Object.assign({}, submission), { component: options.component }), (err) => {\n if (err) {\n // If string is returned, cast to object.\n if (typeof err === 'string') {\n err = {\n message: err\n };\n }\n // Ensure err is an array.\n err = Array.isArray(err) ? err : [err];\n return reject(err);\n }\n this.loading = true;\n // Use the form action to submit the form if available.\n if (this._form && this._form.action) {\n const method = (submission.data._id && this._form.action.includes(submission.data._id)) ? 'PUT' : 'POST';\n return Formio_1.Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {})\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n }\n const submitFormio = this.formio;\n if (this.nosubmit || !submitFormio) {\n return resolve({\n submission,\n saved: false,\n });\n }\n // If this is an actionUrl, then make sure to save the action and not the submission.\n const submitMethod = submitFormio.actionUrl ? 'saveAction' : 'saveSubmission';\n submitFormio[submitMethod](submission)\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n });\n });\n });\n }\n setServerErrors(error) {\n if (error.details) {\n this.serverErrors = error.details.filter((err) => err.level ? err.level === 'error' : err).map((err) => {\n err.fromServer = true;\n return err;\n });\n }\n else if (typeof error === 'string') {\n this.serverErrors = [{ fromServer: true, level: 'error', message: error }];\n }\n }\n executeSubmit(options) {\n this.submitted = true;\n this.submitting = true;\n return this.submitForm(options)\n .then(({ submission, saved }) => this.onSubmit(submission, saved))\n .then((results) => {\n this.submissionInProcess = false;\n return results;\n })\n .catch((err) => {\n this.submissionInProcess = false;\n return Promise.reject(this.onSubmissionError(err));\n });\n }\n clearServerErrors() {\n var _a;\n (_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.forEach((error) => {\n if (error.path) {\n const pathArray = (0, utils_1.getArrayFromComponentPath)(error.path);\n const component = this.getComponent(pathArray, lodash_1.default.identity, error.formattedKeyOrPath);\n if (component) {\n component.serverErrors = [];\n }\n }\n });\n this.serverErrors = [];\n }\n /**\n * Submits the form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n * form.submit().then((submission) => {\n * console.log(submission);\n * });\n *\n * @param {boolean} before - If this submission occured from the before handlers.\n *\n * @returns {Promise} - A promise when the form is done submitting.\n */\n submit(before, options = {}) {\n this.submissionInProcess = true;\n if (!before) {\n return this.beforeSubmit(options).then(() => this.executeSubmit(options));\n }\n else {\n return this.executeSubmit(options);\n }\n }\n submitUrl(URL, headers) {\n if (!URL) {\n return console.warn('Missing URL argument');\n }\n const submission = this.submission || {};\n const API_URL = URL;\n const settings = {\n method: 'POST',\n headers: {}\n };\n if (headers && headers.length > 0) {\n headers.map((e) => {\n if (e.header !== '' && e.value !== '') {\n settings.headers[e.header] = this.interpolate(e.value, submission);\n }\n });\n }\n if (API_URL && settings) {\n Formio_1.Formio.makeStaticRequest(API_URL, settings.method, submission, { headers: settings.headers }).then(() => {\n this.emit('requestDone');\n this.setAlert('success', '<p> Success </p>');\n }).catch((e) => {\n const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`;\n this.emit('error', message);\n console.error(message);\n this.setAlert('danger', `<p> ${message} </p>`);\n return Promise.reject(this.onSubmissionError(e));\n });\n }\n else {\n this.emit('error', 'You should add a URL to this button.');\n this.setAlert('warning', 'You should add a URL to this button.');\n return console.warn('You should add a URL to this button.');\n }\n }\n triggerRecaptcha() {\n if (!this || !this.components) {\n return;\n }\n const recaptchaComponent = (0, utils_1.searchComponents)(this.components, {\n 'component.type': 'recaptcha',\n 'component.eventType': 'formLoad'\n });\n if (recaptchaComponent.length > 0) {\n recaptchaComponent[0].verify(`${this.form.name ? this.form.name : 'form'}Load`);\n }\n }\n set nosubmit(value) {\n this._nosubmit = !!value;\n this.emit('nosubmit', this._nosubmit);\n }\n get nosubmit() {\n return this._nosubmit || false;\n }\n get conditions() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.conditions) !== null && _b !== void 0 ? _b : [];\n }\n get variables() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.variables) !== null && _b !== void 0 ? _b : [];\n }\n}\nexports[\"default\"] = Webform;\nWebform.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWebform.setApiUrl = Formio_1.Formio.setApiUrl;\nWebform.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Webform.js?");
5566
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst compare_versions_1 = __webpack_require__(/*! compare-versions */ \"./node_modules/compare-versions/lib/esm/index.js\");\nconst core_1 = __webpack_require__(/*! @formio/core */ \"./node_modules/@formio/core/lib/index.js\");\nconst EventEmitter_1 = __importDefault(__webpack_require__(/*! ./EventEmitter */ \"./lib/cjs/EventEmitter.js\"));\nconst i18n_1 = __importDefault(__webpack_require__(/*! ./i18n */ \"./lib/cjs/i18n.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst Components_1 = __importDefault(__webpack_require__(/*! ./components/Components */ \"./lib/cjs/components/Components.js\"));\nconst NestedDataComponent_1 = __importDefault(__webpack_require__(/*! ./components/_classes/nesteddata/NestedDataComponent */ \"./lib/cjs/components/_classes/nesteddata/NestedDataComponent.js\"));\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst formUtils_1 = __webpack_require__(/*! ./utils/formUtils */ \"./lib/cjs/utils/formUtils.js\");\n// Initialize the available forms.\nFormio_1.Formio.forms = {};\n// Allow people to register components.\nFormio_1.Formio.registerComponent = Components_1.default.setComponent;\nfunction getIconSet(icons) {\n if (icons === 'fontawesome') {\n return 'fa';\n }\n return icons || '';\n}\nfunction getOptions(options) {\n options = lodash_1.default.defaults(options, {\n submitOnEnter: false,\n iconset: getIconSet((options && options.icons) ? options.icons : Formio_1.Formio.icons),\n i18next: null,\n saveDraft: false,\n alwaysDirty: false,\n saveDraftThrottle: 5000,\n display: 'form',\n cdnUrl: Formio_1.Formio.cdn.baseUrl\n });\n if (!options.events) {\n options.events = new EventEmitter_1.default();\n }\n return options;\n}\n/**\n * Represents a JSON value.\n * @typedef {(string | number | boolean | null | JSONArray | JSONObject)} JSON\n */\n/**\n * Represents a JSON array.\n * @typedef {Array<JSON>} JSONArray\n */\n/**\n * Represents a JSON object.\n * @typedef {{[key: string]: JSON}} JSONObject\n */\n/**\n * @typedef {Object} FormioHooks\n * @property {function} [beforeSubmit]\n * @property {function} [beforeCancel]\n * @property {function} [beforeNext]\n * @property {function} [beforePrev]\n * @property {function} [attachComponent]\n * @property {function} [setDataValue]\n * @property {function} [addComponents]\n * @property {function} [addComponent]\n * @property {function} [customValidation]\n * @property {function} [attachWebform]\n */\n/**\n * @typedef {Object} SanitizeConfig\n * @property {string[]} [addAttr]\n * @property {string[]} [addTags]\n * @property {string[]} [allowedAttrs]\n * @property {string[]} [allowedTags]\n * @property {string[]} [allowedUriRegex]\n * @property {string[]} [addUriSafeAttr]\n */\n/**\n * @typedef {Object} ButtonSettings\n * @property {boolean} [showPrevious]\n * @property {boolean} [showNext]\n * @property {boolean} [showCancel]\n * @property {boolean} [showSubmit]\n */\n/**\n * @typedef {Object} FormOptions\n * @property {boolean} [saveDraft] - Enable the save draft feature.\n * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.\n * @property {boolean} [readOnly] - Set this form to readOnly.\n * @property {boolean} [noAlerts] - Disable the alerts dialog.\n * @property {{[key: string]: string}} [i18n] - The translation file for this rendering.\n * @property {string} [template] - Custom logic for creation of elements.\n * @property {boolean} [noDefaults] - Exclude default values from the settings.\n * @property {any} [fileService] - The file service for this form.\n * @property {EventEmitter} [events] - The EventEmitter for this form.\n * @property {string} [language] - The language to render this form in.\n * @property {{[key: string]: string}} [i18next] - The i18next configuration for this form.\n * @property {boolean} [viewAsHtml] - View the form as raw HTML.\n * @property {'form' | 'html' | 'flat' | 'builder' | 'pdf'} [renderMode] - The render mode for this form.\n * @property {boolean} [highlightErrors] - Highlight any errors on the form.\n * @property {string} [componentErrorClass] - The error class for components.\n * @property {any} [templates] - The templates for this form.\n * @property {string} [iconset] - The iconset for this form.\n * @property {Component[]} [components] - The components for this form.\n * @property {{[key: string]: boolean}} [disabled] - Disabled components for this form.\n * @property {boolean} [showHiddenFields] - Show hidden fields.\n * @property {{[key: string]: boolean}} [hide] - Hidden components for this form.\n * @property {{[key: string]: boolean}} [show] - Components to show for this form.\n * @property {Formio} [formio] - The Formio instance for this form.\n * @property {string} [decimalSeparator] - The decimal separator for this form.\n * @property {string} [thousandsSeparator] - The thousands separator for this form.\n * @property {FormioHooks} [hooks] - The hooks for this form.\n * @property {boolean} [alwaysDirty] - Always be dirty.\n * @property {boolean} [skipDraftRestore] - Skip restoring a draft.\n * @property {'form' | 'wizard' | 'pdf'} [display] - The display for this form.\n * @property {string} [cdnUrl] - The CDN url for this form.\n * @property {boolean} [flatten] - Flatten the form.\n * @property {boolean} [sanitize] - Sanitize the form.\n * @property {SanitizeConfig} [sanitizeConfig] - The sanitize configuration for this form.\n * @property {ButtonSettings} [buttonSettings] - The button settings for this form.\n * @property {Object} [breadCrumbSettings] - The breadcrumb settings for this form.\n * @property {boolean} [allowPrevious] - Allow the previous button (for Wizard forms).\n * @property {string[]} [wizardButtonOrder] - The order of the buttons (for Wizard forms).\n * @property {boolean} [showCheckboxBackground] - Show the checkbox background.\n * @property {number} [zoom] - The zoom for PDF forms.\n */\n/**\n * Renders a Form.io form within the webpage.\n */\nclass Webform extends NestedDataComponent_1.default {\n /**\n * Creates a new Form instance.\n *\n * @param {HTMLElement | Object | FormOptions} [elementOrOptions] - The DOM element to render this form within or the options to create this form instance.\n * @param {FormOptions} [options] - The options to create a new form instance.\n */\n constructor(elementOrOptions, options) {\n let element, formOptions;\n if (elementOrOptions instanceof HTMLElement || options) {\n element = elementOrOptions;\n formOptions = options;\n }\n else {\n formOptions = elementOrOptions;\n }\n super(null, getOptions(formOptions));\n this.executeShortcuts = (event) => {\n const { target } = event;\n if (!this.keyboardCatchableElement(target)) {\n return;\n }\n const ctrl = event.ctrlKey || event.metaKey;\n const keyCode = event.keyCode;\n let char = '';\n if (65 <= keyCode && keyCode <= 90) {\n char = String.fromCharCode(keyCode);\n }\n else if (keyCode === 13) {\n char = 'Enter';\n }\n else if (keyCode === 27) {\n char = 'Esc';\n }\n lodash_1.default.each(this.shortcuts, (shortcut) => {\n if (shortcut.ctrl && !ctrl) {\n return;\n }\n if (shortcut.shortcut === char) {\n shortcut.element.click();\n event.preventDefault();\n }\n });\n };\n this.setElement(element);\n // Keep track of all available forms globally.\n Formio_1.Formio.forms[this.id] = this;\n // Set the base url.\n if (this.options.baseUrl) {\n Formio_1.Formio.setBaseUrl(this.options.baseUrl);\n }\n /**\n * The type of this element.\n * @type {string}\n */\n this.type = 'form';\n this._src = '';\n this._loading = false;\n this._form = {};\n this.draftEnabled = false;\n this.savingDraft = true;\n if (this.options.saveDraftThrottle) {\n this.triggerSaveDraft = lodash_1.default.throttle(this.saveDraft.bind(this), this.options.saveDraftThrottle);\n }\n else {\n this.triggerSaveDraft = this.saveDraft.bind(this);\n }\n /**\n * Determines if this form should submit the API on submit.\n * @type {boolean}\n */\n this.nosubmit = false;\n /**\n * Determines if the form has tried to be submitted, error or not.\n *\n * @type {boolean}\n */\n this.submitted = false;\n /**\n * Determines if the form is being submitted at the moment.\n *\n * @type {boolean}\n */\n this.submitting = false;\n /**\n * The Formio instance for this form.\n * @type {Formio}\n */\n this.formio = null;\n /**\n * The loader HTML element.\n * @type {HTMLElement}\n */\n this.loader = null;\n /**\n * The alert HTML element\n * @type {HTMLElement}\n */\n this.alert = null;\n /**\n * Promise that is triggered when the submission is done loading.\n * @type {Promise}\n */\n this.onSubmission = null;\n /**\n * Determines if this submission is explicitly set.\n * @type {boolean}\n */\n this.submissionSet = false;\n /**\n * Promise that executes when the form is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is ready!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n this.formReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.formReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.formReadyReject = reject;\n });\n /**\n * Promise that executes when the submission is ready and rendered.\n * @type {Promise}\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.submissionReady.then(() => {\n * console.log('The submission is ready!');\n * });\n * form.src = 'https://examples.form.io/example/submission/234234234234234243';\n */\n this.submissionReady = new Promise((resolve, reject) => {\n /**\n * Called when the formReady state of this form has been resolved.\n *\n * @type {function}\n */\n this.submissionReadyResolve = resolve;\n /**\n * Called when this form could not load and is rejected.\n *\n * @type {function}\n */\n this.submissionReadyReject = reject;\n });\n this.shortcuts = [];\n // Set language after everything is established.\n this.language = this.i18next.language;\n // See if we need to restore the draft from a user.\n if (this.options.saveDraft) {\n this.formReady.then(() => {\n if (!this.options.skipDraftRestore) {\n const user = Formio_1.Formio.getUser();\n // Only restore a draft if the submission isn't explicitly set.\n if (user && !this.submissionSet) {\n this.restoreDraft(user._id);\n }\n }\n else {\n // Enable drafts\n this.draftEnabled = true;\n this.savingDraft = false;\n }\n });\n }\n this.component.clearOnHide = false;\n // Ensure the root is set to this component.\n this.root = this;\n this.localRoot = this;\n }\n /* eslint-enable max-statements */\n get language() {\n return this.options.language;\n }\n get emptyValue() {\n return null;\n }\n componentContext() {\n return this._data;\n }\n /**\n * Sets the language for this form.\n *\n * @param lang\n * @return {Promise}\n */\n set language(lang) {\n if (!this.i18next) {\n return;\n }\n this.options.language = lang;\n if (this.i18next.language === lang) {\n return;\n }\n this.i18next.changeLanguage(lang, (err) => {\n if (err) {\n return;\n }\n this.rebuild();\n this.emit('languageChanged');\n });\n }\n get componentComponents() {\n return this.form.components;\n }\n get shadowRoot() {\n return this.options.shadowRoot;\n }\n /**\n * Add a language for translations\n *\n * @param code\n * @param lang\n * @param active\n * @return {*}\n */\n addLanguage(code, lang, active = false) {\n if (this.i18next) {\n var translations = lodash_1.default.assign((0, utils_1.fastCloneDeep)(i18n_1.default.resources.en.translation), lang);\n this.i18next.addResourceBundle(code, 'translation', translations, true, true);\n if (active) {\n this.language = code;\n }\n }\n }\n keyboardCatchableElement(element) {\n if (element.nodeName === 'TEXTAREA') {\n return false;\n }\n if (element.nodeName === 'INPUT') {\n return [\n 'text',\n 'email',\n 'password'\n ].indexOf(element.type) === -1;\n }\n return true;\n }\n addShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n shortcut = lodash_1.default.capitalize(shortcut);\n if (shortcut === 'Enter' || shortcut === 'Esc') {\n // Restrict Enter and Esc only for buttons\n if (element.tagName !== 'BUTTON') {\n return;\n }\n this.shortcuts.push({\n shortcut,\n element\n });\n }\n else {\n this.shortcuts.push({\n ctrl: true,\n shortcut,\n element\n });\n }\n }\n removeShortcut(element, shortcut) {\n if (!shortcut || !/^([A-Z]|Enter|Esc)$/i.test(shortcut)) {\n return;\n }\n lodash_1.default.remove(this.shortcuts, {\n shortcut,\n element\n });\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get src() {\n return this._src;\n }\n /**\n * Loads the submission if applicable.\n */\n loadSubmission() {\n this.loadingSubmission = true;\n if (this.formio.submissionId) {\n this.onSubmission = this.formio.loadSubmission().then((submission) => this.setSubmission(submission), (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n else {\n this.submissionReadyResolve();\n }\n return this.submissionReady;\n }\n /**\n * Set the src of the form renderer.\n *\n * @param value\n * @param options\n */\n setSrc(value, options) {\n if (this.setUrl(value, options)) {\n this.nosubmit = false;\n return this.formio.loadForm({ params: { live: 1 } }).then((form) => {\n const setForm = this.setForm(form);\n this.loadSubmission();\n return setForm;\n }).catch((err) => {\n console.warn(err);\n this.formReadyReject(err);\n });\n }\n return Promise.resolve();\n }\n /**\n * Set the Form source, which is typically the Form.io embed URL.\n *\n * @param {string} value - The value of the form embed url.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.formReady.then(() => {\n * console.log('The form is formReady!');\n * });\n * form.src = 'https://examples.form.io/example';\n */\n set src(value) {\n this.setSrc(value);\n }\n /**\n * Get the embed source of the form.\n *\n * @returns {string}\n */\n get url() {\n return this._src;\n }\n /**\n * Sets the url of the form renderer.\n *\n * @param value\n * @param options\n */\n setUrl(value, options) {\n if (!value ||\n (typeof value !== 'string') ||\n (value === this._src)) {\n return false;\n }\n this._src = value;\n this.nosubmit = true;\n this.formio = this.options.formio = new Formio_1.Formio(value, options);\n if (this.type === 'form') {\n // Set the options source so this can be passed to other components.\n this.options.src = value;\n }\n return true;\n }\n /**\n * Set the form source but don't initialize the form and submission from the url.\n *\n * @param {string} value - The value of the form embed url.\n */\n set url(value) {\n this.setUrl(value);\n }\n /**\n * Called when both the form and submission have been loaded.\n *\n * @returns {Promise} - The promise to trigger when both form and submission have loaded.\n */\n get ready() {\n return this.formReady.then(() => {\n return super.ready.then(() => {\n return this.loadingSubmission ? this.submissionReady : true;\n });\n });\n }\n /**\n * Returns if this form is loading.\n *\n * @returns {boolean} - TRUE means the form is loading, FALSE otherwise.\n */\n get loading() {\n return this._loading;\n }\n /**\n * Set the loading state for this form, and also show the loader spinner.\n *\n * @param {boolean} loading - If this form should be \"loading\" or not.\n */\n set loading(loading) {\n if (this._loading !== loading) {\n this._loading = loading;\n if (!this.loader && loading) {\n this.loader = this.ce('div', {\n class: 'loader-wrapper'\n });\n const spinner = this.ce('div', {\n class: 'loader text-center'\n });\n this.loader.appendChild(spinner);\n }\n /* eslint-disable max-depth */\n if (this.loader) {\n try {\n if (loading) {\n this.prependTo(this.loader, this.wrapper);\n }\n else {\n this.removeChildFrom(this.loader, this.wrapper);\n }\n }\n catch (err) {\n // ingore\n }\n }\n /* eslint-enable max-depth */\n }\n }\n /**\n * Sets the JSON schema for the form to be rendered.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.setForm({\n * components: [\n * {\n * type: 'textfield',\n * key: 'firstName',\n * label: 'First Name',\n * placeholder: 'Enter your first name.',\n * input: true\n * },\n * {\n * type: 'textfield',\n * key: 'lastName',\n * label: 'Last Name',\n * placeholder: 'Enter your last name',\n * input: true\n * },\n * {\n * type: 'button',\n * action: 'submit',\n * label: 'Submit',\n * theme: 'primary'\n * }\n * ]\n * });\n *\n * @param {Object} form - The JSON schema of the form @see https://examples.form.io/example for an example JSON schema.\n * @param flags\n * @returns {*}\n */\n setForm(form, flags) {\n var _a, _b, _c;\n const isFormAlreadySet = this._form && ((_a = this._form.components) === null || _a === void 0 ? void 0 : _a.length);\n try {\n // Do not set the form again if it has been already set\n if (isFormAlreadySet && JSON.stringify(this._form) === JSON.stringify(form)) {\n return Promise.resolve();\n }\n // Create the form.\n this._form = (flags === null || flags === void 0 ? void 0 : flags.keepAsReference) ? form : lodash_1.default.cloneDeep(form);\n if (this.onSetForm) {\n this.onSetForm(lodash_1.default.cloneDeep(this._form), form);\n }\n if ((_c = (_b = this.parent) === null || _b === void 0 ? void 0 : _b.component) === null || _c === void 0 ? void 0 : _c.modalEdit) {\n return Promise.resolve();\n }\n }\n catch (err) {\n console.warn(err);\n // If provided form is not a valid JSON object, do not set it too\n return Promise.resolve();\n }\n // Allow the form to provide component overrides.\n if (form && form.settings && form.settings.components) {\n this.options.components = form.settings.components;\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n // Use the sanitize config from the form settings or the global sanitize config if it is not provided in the options\n if (!this.options.sanitizeConfig && !this.builderMode) {\n this.options.sanitizeConfig = lodash_1.default.get(form, 'settings.sanitizeConfig') || lodash_1.default.get(form, 'globalSettings.sanitizeConfig');\n }\n if ('schema' in form && (0, compare_versions_1.compareVersions)(form.schema, '1.x') > 0) {\n this.ready.then(() => {\n this.setAlert('alert alert-danger', 'Form schema is for a newer version, please upgrade your renderer. Some functionality may not work.');\n });\n }\n // See if they pass a module, and evaluate it if so.\n if (form && form.module) {\n let formModule = null;\n if (typeof form.module === 'string') {\n try {\n formModule = this.evaluate(`return ${form.module}`);\n }\n catch (err) {\n console.warn(err);\n }\n }\n else {\n formModule = form.module;\n }\n if (formModule) {\n Formio_1.Formio.use(formModule);\n // Since we got here after instantiation, we need to manually apply form options.\n if (formModule.options && formModule.options.form) {\n this.options = Object.assign(this.options, formModule.options.form);\n }\n }\n }\n this.initialized = false;\n const rebuild = this.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n this.emit('formLoad', form);\n this.triggerRecaptcha();\n // Make sure to trigger onChange after a render event occurs to speed up form rendering.\n setTimeout(() => {\n this.onChange(flags);\n this.formReadyResolve();\n }, 0);\n return this.formReady;\n });\n }\n /**\n * Gets the form object.\n *\n * @returns {Object} - The form JSON schema.\n */\n get form() {\n if (!this._form) {\n this._form = {\n components: []\n };\n }\n return this._form;\n }\n /**\n * Sets the form value.\n *\n * @alias setForm\n * @param {Object} form - The form schema object.\n */\n set form(form) {\n this.setForm(form);\n }\n /**\n * Returns the submission object that was set within this form.\n *\n * @returns {Object}\n */\n get submission() {\n return this.getValue();\n }\n /**\n * Sets the submission of a form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n *\n * @param {Object} submission - The Form.io submission object.\n */\n set submission(submission) {\n this.setSubmission(submission);\n }\n /**\n * Sets a submission and returns the promise when it is ready.\n * @param submission\n * @param flags\n * @return {Promise.<TResult>}\n */\n setSubmission(submission, flags = {}) {\n flags = Object.assign(Object.assign({}, flags), { fromSubmission: lodash_1.default.has(flags, 'fromSubmission') ? flags.fromSubmission : true });\n return this.onSubmission = this.formReady.then((resolveFlags) => {\n if (resolveFlags) {\n flags = Object.assign(Object.assign({}, flags), resolveFlags);\n }\n this.submissionSet = true;\n this.triggerChange(flags);\n this.emit('beforeSetSubmission', submission);\n this.setValue(submission, flags);\n return this.submissionReadyResolve(submission);\n }, (err) => this.submissionReadyReject(err)).catch((err) => this.submissionReadyReject(err));\n }\n handleDraftError(errName, errDetails, restoreDraft) {\n const errorMessage = lodash_1.default.trim(`${this.t(errName)} ${errDetails || ''}`);\n console.warn(errorMessage);\n this.emit(restoreDraft ? 'restoreDraftError' : 'saveDraftError', errDetails || errorMessage);\n }\n /**\n * Saves a submission draft.\n */\n saveDraft() {\n if (!this.draftEnabled) {\n return;\n }\n if (!this.formio) {\n this.handleDraftError('saveDraftInstanceError');\n return;\n }\n if (!Formio_1.Formio.getUser()) {\n this.handleDraftError('saveDraftAuthError');\n return;\n }\n const draft = (0, utils_1.fastCloneDeep)(this.submission);\n draft.state = 'draft';\n if (!this.savingDraft && !this.submitting) {\n this.emit('saveDraftBegin');\n this.savingDraft = true;\n this.formio.saveSubmission(draft).then((sub) => {\n // Set id to submission to avoid creating new draft submission\n this.submission._id = sub._id;\n this.savingDraft = false;\n this.emit('saveDraft', sub);\n })\n .catch(err => {\n this.savingDraft = false;\n this.handleDraftError('saveDraftError', err);\n });\n }\n }\n /**\n * Restores a draft submission based on the user who is authenticated.\n *\n * @param {userId} - The user id where we need to restore the draft from.\n */\n restoreDraft(userId) {\n const formio = this.formio || this.options.formio;\n if (!formio) {\n this.handleDraftError('restoreDraftInstanceError', null, true);\n return;\n }\n this.savingDraft = true;\n formio.loadSubmissions({\n params: {\n state: 'draft',\n owner: userId\n }\n }).then(submissions => {\n if (submissions.length > 0 && !this.options.skipDraftRestore) {\n const draft = (0, utils_1.fastCloneDeep)(submissions[0]);\n return this.setSubmission(draft).then(() => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', draft);\n });\n }\n // Enable drafts so that we can keep track of changes.\n this.draftEnabled = true;\n this.savingDraft = false;\n this.emit('restoreDraft', null);\n })\n .catch(err => {\n this.draftEnabled = true;\n this.savingDraft = false;\n this.handleDraftError('restoreDraftError', err, true);\n });\n }\n get schema() {\n const schema = (0, utils_1.fastCloneDeep)(lodash_1.default.omit(this._form, ['components']));\n schema.components = [];\n this.eachComponent((component) => schema.components.push(component.schema));\n return schema;\n }\n mergeData(_this, _that) {\n lodash_1.default.mergeWith(_this, _that, (thisValue, thatValue) => {\n if (Array.isArray(thisValue) && Array.isArray(thatValue) && thisValue.length !== thatValue.length) {\n return thatValue;\n }\n });\n }\n setValue(submission, flags = {}) {\n if (!submission || !submission.data) {\n submission = {\n data: {},\n metadata: submission.metadata,\n };\n }\n // Metadata needs to be available before setValue\n this._submission.metadata = submission.metadata || {};\n this.editing = !!submission._id;\n // Set the timezone in the options if available.\n if (!this.options.submissionTimezone &&\n submission.metadata &&\n submission.metadata.timezone) {\n this.options.submissionTimezone = submission.metadata.timezone;\n }\n const changed = super.setValue(submission.data, flags);\n if (!flags.sanitize) {\n this.mergeData(this.data, submission.data);\n }\n submission.data = this.data;\n this._submission = submission;\n return changed;\n }\n getValue() {\n if (!this._submission.data) {\n this._submission.data = {};\n }\n if (this.viewOnly) {\n return this._submission;\n }\n const submission = this._submission;\n submission.data = this.data;\n return this._submission;\n }\n /**\n * Build the form.\n */\n init() {\n if (this.options.submission) {\n const submission = lodash_1.default.extend({}, this.options.submission);\n this._submission = submission;\n this._data = submission.data;\n }\n else {\n this._submission = this._submission || { data: {} };\n }\n // Remove any existing components.\n if (this.components && this.components.length) {\n this.destroyComponents();\n this.components = [];\n }\n if (this.component) {\n this.component.components = this.form ? this.form.components : [];\n }\n else {\n this.component = this.form;\n }\n this.component.type = 'form';\n this.component.input = false;\n this.addComponents();\n this.on('submitButton', options => {\n this.submit(false, options).catch(e => {\n options.instance.loading = false;\n return e !== false && e !== undefined && console.log(e);\n });\n }, true);\n this.on('checkValidity', (data) => this.validate(data, { dirty: true, process: 'change' }), true);\n this.on('requestUrl', (args) => (this.submitUrl(args.url, args.headers)), true);\n this.on('resetForm', () => this.resetValue(), true);\n this.on('deleteSubmission', () => this.deleteSubmission(), true);\n this.on('refreshData', () => this.updateValue(), true);\n this.executeFormController();\n return this.formReady;\n }\n executeFormController() {\n // If no controller value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n if (!this.form || !this.form.controller\n || ((!this.visible || this.component.hidden) && this.component.clearOnHide && !this.rootPristine)) {\n return false;\n }\n this.formReady.then(() => {\n this.evaluate(this.form.controller, {\n components: this.components,\n instance: this,\n });\n });\n }\n teardown() {\n this.emit('formDelete', this.id);\n delete Formio_1.Formio.forms[this.id];\n delete this.executeShortcuts;\n delete this.triggerSaveDraft;\n super.teardown();\n }\n destroy(all = false) {\n this.off('submitButton');\n this.off('checkValidity');\n this.off('requestUrl');\n this.off('resetForm');\n this.off('deleteSubmission');\n this.off('refreshData');\n return super.destroy(all);\n }\n build(element) {\n if (element || this.element) {\n return this.ready.then(() => {\n element = element || this.element;\n super.build(element);\n });\n }\n return this.ready;\n }\n getClassName() {\n let classes = 'formio-form';\n if (this.options.readOnly) {\n classes += ' formio-read-only';\n }\n return classes;\n }\n render() {\n return super.render(this.renderTemplate('webform', {\n classes: this.getClassName(),\n children: this.renderComponents(),\n }), this.builderMode ? 'builder' : 'form', true);\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element) {\n return Promise.resolve();\n }\n this.clear();\n this.setContent(this.element, this.render());\n return this.attach(this.element);\n }\n attach(element) {\n this.setElement(element);\n this.loadRefs(element, { webform: 'single' });\n const childPromise = this.attachComponents(this.refs.webform);\n this.addEventListener(document, 'keydown', this.executeShortcuts);\n this.currentForm = this;\n this.hook('attachWebform', element, this);\n return childPromise.then(() => {\n this.emit('render', this.element);\n return this.setValue(this._submission, {\n noUpdateEvent: true,\n });\n });\n }\n hasRequiredFields() {\n let result = false;\n (0, formUtils_1.eachComponent)(this.form.components, (component) => {\n if (component.validate.required) {\n result = true;\n return true;\n }\n }, true);\n return result;\n }\n resetValue() {\n lodash_1.default.each(this.getComponents(), (comp) => (comp.resetValue()));\n this.setPristine(true);\n this.onChange({ resetValue: true });\n }\n /**\n * Sets a new alert to display in the error dialog of the form.\n *\n * @param {string} type - The type of alert to display. \"danger\", \"success\", \"warning\", etc.\n * @param {string} message - The message to show in the alert.\n * @param {Object} options\n */\n setAlert(type, message, options) {\n if (!type && this.submitted) {\n if (this.alert) {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n return;\n }\n if (this.options.noAlerts) {\n if (!message) {\n this.emit('error', false);\n }\n return;\n }\n if (this.alert) {\n try {\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.removeEventListener(el, 'click');\n this.removeEventListener(el, 'keypress');\n });\n }\n this.removeChild(this.alert);\n this.alert = null;\n }\n catch (err) {\n // ignore\n }\n }\n if (message) {\n const attrs = {\n class: (options && options.classes) || `alert alert-${type}`,\n id: `error-list-${this.id}`,\n };\n const templateOptions = {\n message: message instanceof HTMLElement ? message.outerHTML : message,\n attrs: attrs,\n type\n };\n this.alert = (0, utils_1.convertStringToHTMLElement)(this.renderTemplate('alert', templateOptions), `#${attrs.id}`);\n }\n if (!this.alert) {\n return;\n }\n this.loadRefs(this.alert, { errorRef: 'multiple' });\n if (this.refs.errorRef && this.refs.errorRef.length) {\n this.refs.errorRef.forEach(el => {\n this.addEventListener(el, 'click', (e) => {\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n });\n this.addEventListener(el, 'keydown', (e) => {\n if (e.keyCode === 13) {\n e.preventDefault();\n const key = e.currentTarget.dataset.componentKey;\n this.focusOnComponent(key);\n }\n });\n });\n }\n this.prepend(this.alert);\n }\n /**\n * Focus on selected component.\n *\n * @param {string} key - The key of selected component.\n * @returns {*}\n */\n focusOnComponent(key) {\n if (key) {\n const component = this.getComponent(key);\n if (component) {\n component.focus();\n }\n }\n }\n /**\n * Show the errors of this form within the alert dialog.\n *\n * @param {Object} error - An optional additional error to display along with the component errors.\n * @returns {*}\n */\n /* eslint-disable no-unused-vars */\n showErrors(errors, triggerEvent) {\n this.loading = false;\n if (!Array.isArray(errors)) {\n errors = [errors];\n }\n errors = errors.concat(this.customErrors).filter((err) => !!err);\n if (!errors.length) {\n this.setAlert(false);\n return;\n }\n // Mark any components as invalid if in a custom message.\n errors.forEach((err) => {\n const { components = [] } = err;\n if (err.component) {\n components.push(err.component);\n }\n if (err.path) {\n components.push(err.path);\n }\n components.forEach((path) => {\n const originalPath = (0, utils_1.getStringFromComponentPath)(path);\n const component = this.getComponent(path, lodash_1.default.identity, originalPath);\n if (err.fromServer) {\n if (component.serverErrors) {\n component.serverErrors.push(err);\n }\n else {\n component.serverErrors = [err];\n }\n }\n const components = lodash_1.default.compact(Array.isArray(component) ? component : [component]);\n components.forEach((component) => component.setCustomValidity(err.message, true));\n });\n });\n const displayedErrors = [];\n if (errors.length) {\n errors = lodash_1.default.uniqBy(errors, error => error.message);\n const createListItem = (message, index) => {\n var _a, _b, _c;\n const err = errors[index];\n const messageFromIndex = !lodash_1.default.isUndefined(index) && errors && errors[index];\n const keyOrPath = ((messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.formattedKeyOrPath) || (messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.path) || ((_a = messageFromIndex === null || messageFromIndex === void 0 ? void 0 : messageFromIndex.context) === null || _a === void 0 ? void 0 : _a.path)) || (((_b = err.context) === null || _b === void 0 ? void 0 : _b.component) && ((_c = err.context) === null || _c === void 0 ? void 0 : _c.component.key)) || (err.component && err.component.key) || err.fromServer && err.path;\n const formattedKeyOrPath = keyOrPath ? (0, utils_1.getStringFromComponentPath)(keyOrPath) : '';\n if (typeof err !== 'string' && !err.formattedKeyOrPath) {\n err.formattedKeyOrPath = formattedKeyOrPath;\n }\n return {\n message: (0, utils_1.unescapeHTML)(message),\n keyOrPath: formattedKeyOrPath\n };\n };\n errors.forEach(({ message, context, fromServer, component }, index) => {\n const text = !(component === null || component === void 0 ? void 0 : component.label) || (context === null || context === void 0 ? void 0 : context.hasLabel) || fromServer\n ? this.t('alertMessage', { message: this.t(message) })\n : this.t('alertMessageWithLabel', {\n label: this.t(component === null || component === void 0 ? void 0 : component.label),\n message: this.t(message),\n });\n displayedErrors.push(createListItem(text, index));\n });\n }\n const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });\n this.root.setAlert('danger', errorsList);\n if (triggerEvent) {\n this.emit('error', errors);\n }\n return errors;\n }\n /* eslint-enable no-unused-vars */\n /**\n * Called when the submission has completed, or if the submission needs to be sent to an external library.\n *\n * @param {Object} submission - The submission object.\n * @param {boolean} saved - Whether or not this submission was saved to the server.\n * @returns {object} - The submission object.\n */\n onSubmit(submission, saved) {\n var _a;\n this.loading = false;\n this.submitting = false;\n this.setPristine(true);\n // We want to return the submitted submission and setValue will mutate the submission so cloneDeep it here.\n this.setValue((0, utils_1.fastCloneDeep)(submission), {\n noValidate: true,\n noCheck: true\n });\n this.setAlert('success', `<p>${this.t('complete')}</p>`);\n // Cancel triggered saveDraft to prevent overriding the submitted state\n if (this.draftEnabled && ((_a = this.triggerSaveDraft) === null || _a === void 0 ? void 0 : _a.cancel)) {\n this.triggerSaveDraft.cancel();\n }\n this.emit('submit', submission, saved);\n if (saved) {\n this.emit('submitDone', submission);\n }\n return submission;\n }\n normalizeError(error) {\n if (error) {\n if (typeof error === 'object' && 'details' in error) {\n error = error.details;\n }\n if (typeof error === 'string') {\n error = { message: error };\n }\n }\n return error;\n }\n /**\n * Called when an error occurs during the submission.\n *\n * @param {Object} error - The error that occured.\n */\n onSubmissionError(error) {\n error = this.normalizeError(error);\n this.submitting = false;\n this.setPristine(false);\n this.emit('submitError', error || this.errors);\n // Allow for silent cancellations (no error message, no submit button error state)\n if (error && error.silent) {\n this.emit('change', { isValid: true }, { silent: true });\n return false;\n }\n const errors = this.showErrors(error, true);\n if (this.root && this.root.alert) {\n this.scrollIntoView(this.root.alert);\n }\n return errors;\n }\n /**\n * Trigger the change event for this form.\n *\n * @param changed\n * @param flags\n */\n onChange(flags, changed, modified, changes) {\n flags = flags || {};\n let isChangeEventEmitted = false;\n super.onChange(flags, true);\n const value = lodash_1.default.clone(this.submission);\n flags.changed = value.changed = changed;\n flags.changes = changes;\n if (modified && this.pristine) {\n this.pristine = false;\n }\n this.checkData(value.data, flags);\n const shouldValidate = !flags.noValidate || flags.fromIFrame || (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed);\n const errors = shouldValidate ? this.validate(value.data, Object.assign(Object.assign({}, flags), { process: 'change' })) : [];\n value.isValid = errors.length === 0;\n this.loading = false;\n if (this.submitted) {\n // show server errors while they are not cleaned/fixed\n const nonComponentServerErrors = lodash_1.default.filter(this.serverErrors || [], err => !err.component && !err.path);\n this.showErrors(nonComponentServerErrors.length ? nonComponentServerErrors : errors);\n }\n // See if we need to save the draft of the form.\n if (modified && this.options.saveDraft) {\n this.triggerSaveDraft();\n }\n if (!flags || !flags.noEmit) {\n this.emit('change', value, flags, modified);\n isChangeEventEmitted = true;\n }\n // The form is initialized after the first change event occurs.\n if (isChangeEventEmitted && !this.initialized) {\n this.emit('initialized');\n this.initialized = true;\n }\n }\n /**\n * Send a delete request to the server.\n */\n deleteSubmission() {\n return this.formio.deleteSubmission()\n .then(() => {\n this.emit('submissionDeleted', this.submission);\n this.resetValue();\n });\n }\n /**\n * Cancels the submission.\n *\n * @alias reset\n */\n cancel(noconfirm) {\n const shouldReset = this.hook('beforeCancel', true);\n if (shouldReset && (noconfirm || confirm(this.t('confirmCancel')))) {\n this.resetValue();\n return true;\n }\n else {\n this.emit('cancelSubmit');\n return false;\n }\n }\n setMetadata(submission) {\n // Add in metadata about client submitting the form\n submission.metadata = submission.metadata || {};\n lodash_1.default.defaults(submission.metadata, {\n timezone: lodash_1.default.get(this, '_submission.metadata.timezone', (0, utils_1.currentTimezone)()),\n offset: parseInt(lodash_1.default.get(this, '_submission.metadata.offset', (0, moment_1.default)().utcOffset()), 10),\n origin: document.location.origin,\n referrer: document.referrer,\n browserName: navigator.appName,\n userAgent: navigator.userAgent,\n pathName: window.location.pathname,\n onLine: navigator.onLine\n });\n }\n submitForm(options = {}) {\n this.clearServerErrors();\n return new Promise((resolve, reject) => {\n // Read-only forms should never submit.\n if (this.options.readOnly) {\n return resolve({\n submission: this.submission,\n saved: false\n });\n }\n const submission = (0, utils_1.fastCloneDeep)(this.submission || {});\n this.setMetadata(submission);\n submission.state = options.state || submission.state || 'submitted';\n const isDraft = (submission.state === 'draft');\n this.hook('beforeSubmit', Object.assign(Object.assign({}, submission), { component: options.component }), (err, data) => {\n var _a;\n if (err) {\n return reject(err);\n }\n submission._vnote = data && data._vnote ? data._vnote : '';\n try {\n if (!isDraft && !options.noValidate) {\n if (!submission.data) {\n return reject('Invalid Submission');\n }\n const errors = this.validate(submission.data, {\n dirty: true,\n silentCheck: false,\n process: 'submit'\n });\n if (errors.length || ((_a = options.beforeSubmitResults) === null || _a === void 0 ? void 0 : _a.some((result) => result.status === 'rejected'))) {\n return reject(errors);\n }\n }\n }\n catch (err) {\n console.error(err);\n }\n this.everyComponent((comp) => {\n if (submission._vnote && comp.type === 'form' && comp.component.reference) {\n lodash_1.default.get(submission.data, comp.path, {})._vnote = submission._vnote;\n }\n const { persistent } = comp.component;\n if (persistent === 'client-only') {\n lodash_1.default.unset(submission.data, comp.path);\n }\n });\n this.hook('customValidation', Object.assign(Object.assign({}, submission), { component: options.component }), (err) => {\n if (err) {\n // If string is returned, cast to object.\n if (typeof err === 'string') {\n err = {\n message: err\n };\n }\n // Ensure err is an array.\n err = Array.isArray(err) ? err : [err];\n return reject(err);\n }\n this.loading = true;\n // Use the form action to submit the form if available.\n if (this._form && this._form.action) {\n const method = (submission.data._id && this._form.action.includes(submission.data._id)) ? 'PUT' : 'POST';\n return Formio_1.Formio.makeStaticRequest(this._form.action, method, submission, this.formio ? this.formio.options : {})\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n }\n const submitFormio = this.formio;\n if (this.nosubmit || !submitFormio) {\n return resolve({\n submission,\n saved: false,\n });\n }\n // If this is an actionUrl, then make sure to save the action and not the submission.\n const submitMethod = submitFormio.actionUrl ? 'saveAction' : 'saveSubmission';\n submitFormio[submitMethod](submission)\n .then((result) => resolve({\n submission: result,\n saved: true,\n }))\n .catch((error) => {\n this.setServerErrors(error);\n return reject(error);\n });\n });\n });\n });\n }\n setServerErrors(error) {\n if (error.details) {\n this.serverErrors = error.details.filter((err) => err.level ? err.level === 'error' : err).map((err) => {\n err.fromServer = true;\n return err;\n });\n }\n else if (typeof error === 'string') {\n this.serverErrors = [{ fromServer: true, level: 'error', message: error }];\n }\n }\n executeSubmit(options) {\n this.submitted = true;\n this.submitting = true;\n return this.submitForm(options)\n .then(({ submission, saved }) => this.onSubmit(submission, saved))\n .then((results) => {\n this.submissionInProcess = false;\n return results;\n })\n .catch((err) => {\n this.submissionInProcess = false;\n return Promise.reject(this.onSubmissionError(err));\n });\n }\n clearServerErrors() {\n var _a;\n (_a = this.serverErrors) === null || _a === void 0 ? void 0 : _a.forEach((error) => {\n if (error.path) {\n const pathArray = (0, utils_1.getArrayFromComponentPath)(error.path);\n const component = this.getComponent(pathArray, lodash_1.default.identity, error.formattedKeyOrPath);\n if (component) {\n component.serverErrors = [];\n }\n }\n });\n this.serverErrors = [];\n }\n /**\n * Submits the form.\n *\n * @example\n * import Webform from '@formio/js/Webform';\n * let form = new Webform(document.getElementById('formio'));\n * form.src = 'https://examples.form.io/example';\n * form.submission = {data: {\n * firstName: 'Joe',\n * lastName: 'Smith',\n * email: 'joe@example.com'\n * }};\n * form.submit().then((submission) => {\n * console.log(submission);\n * });\n *\n * @param {boolean} before - If this submission occured from the before handlers.\n *\n * @returns {Promise} - A promise when the form is done submitting.\n */\n submit(before, options = {}) {\n this.submissionInProcess = true;\n if (!before) {\n return this.beforeSubmit(options).then(() => this.executeSubmit(options));\n }\n else {\n return this.executeSubmit(options);\n }\n }\n submitUrl(URL, headers) {\n if (!URL) {\n return console.warn('Missing URL argument');\n }\n const submission = this.submission || {};\n const API_URL = URL;\n const settings = {\n method: 'POST',\n headers: {}\n };\n if (headers && headers.length > 0) {\n headers.map((e) => {\n if (e.header !== '' && e.value !== '') {\n settings.headers[e.header] = this.interpolate(e.value, submission);\n }\n });\n }\n if (API_URL && settings) {\n Formio_1.Formio.makeStaticRequest(API_URL, settings.method, submission, { headers: settings.headers }).then(() => {\n this.emit('requestDone');\n this.setAlert('success', '<p> Success </p>');\n }).catch((e) => {\n const message = `${e.statusText ? e.statusText : ''} ${e.status ? e.status : e}`;\n this.emit('error', message);\n console.error(message);\n this.setAlert('danger', `<p> ${message} </p>`);\n return Promise.reject(this.onSubmissionError(e));\n });\n }\n else {\n this.emit('error', 'You should add a URL to this button.');\n this.setAlert('warning', 'You should add a URL to this button.');\n return console.warn('You should add a URL to this button.');\n }\n }\n triggerRecaptcha() {\n if (!this || !this.components) {\n return;\n }\n const recaptchaComponent = (0, utils_1.searchComponents)(this.components, {\n 'component.type': 'recaptcha',\n 'component.eventType': 'formLoad'\n });\n if (recaptchaComponent.length > 0) {\n recaptchaComponent[0].verify(`${this.form.name ? this.form.name : 'form'}Load`);\n }\n }\n set nosubmit(value) {\n this._nosubmit = !!value;\n this.emit('nosubmit', this._nosubmit);\n }\n get nosubmit() {\n return this._nosubmit || false;\n }\n get conditions() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.conditions) !== null && _b !== void 0 ? _b : [];\n }\n get variables() {\n var _a, _b;\n return (_b = (_a = this.schema.settings) === null || _a === void 0 ? void 0 : _a.variables) !== null && _b !== void 0 ? _b : [];\n }\n}\nexports[\"default\"] = Webform;\nWebform.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWebform.setApiUrl = Formio_1.Formio.setApiUrl;\nWebform.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Webform.js?");
5557
5567
 
5558
5568
  /***/ }),
5559
5569
 
@@ -5564,7 +5574,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5564
5574
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5565
5575
 
5566
5576
  "use strict";
5567
- 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.element = 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 *\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 component\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.populateRecaptchaSettings(form);\n this.webform.setAlert(false);\n });\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n form: 'single',\n sidebar: 'single',\n 'sidebar-search': 'single',\n 'sidebar-groups': 'single',\n 'container': 'multiple',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n 'sidebar-component': 'multiple',\n });\n if (this.sideBarScroll && Templates_1.default.current.handleBuilderSidebarScroll) {\n Templates_1.default.current.handleBuilderSidebarScroll.call(this, this);\n }\n // Add the paste status in form\n if (typeof window !== 'undefined' && window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n this.addClass(this.refs.form, 'builder-paste-mode');\n }\n }\n if (!(0, utils_1.bootstrapVersion)(this.options)) {\n const getAttribute = (anchor, attribute) => {\n let elem = anchor.getAttribute(`data-${attribute}`);\n if (!elem) {\n elem = anchor.getAttribute(`data-bs-${attribute}`);\n }\n return elem;\n };\n const hideShow = (group, show) => {\n if (show) {\n group.classList.add(['show']);\n group.style.display = 'inherit';\n }\n else {\n group.classList.remove(['show']);\n group.style.display = 'none';\n }\n };\n // Initialize\n this.refs['sidebar-group'].forEach((group) => {\n hideShow(group, getAttribute(group, 'default') === 'true');\n });\n // Click event\n this.refs['sidebar-anchor'].forEach((anchor, index) => {\n this.addEventListener(anchor, 'click', () => {\n const clickedParentId = getAttribute(anchor, 'parent').slice('#builder-sidebar-'.length);\n const clickedId = getAttribute(anchor, 'target').slice('#group-'.length);\n this.refs['sidebar-group'].forEach((group, groupIndex) => {\n const openByDefault = getAttribute(group, 'default') === 'true';\n const groupId = group.getAttribute('id').slice('group-'.length);\n const groupParent = getAttribute(group, 'parent').slice('#builder-sidebar-'.length);\n hideShow(group, ((openByDefault && groupParent === clickedId) || groupId === clickedParentId || groupIndex === index));\n });\n }, true);\n });\n }\n if (this.keyboardActionsEnabled) {\n this.refs['sidebar-component'].forEach((component) => {\n this.addEventListener(component, 'keydown', (event) => {\n if (event.keyCode === 13) {\n this.addNewComponent(component);\n }\n });\n });\n }\n this.addEventListener(this.refs['sidebar-search'], 'input', lodash_1.default.debounce((e) => {\n const searchString = e.target.value;\n this.searchFields(searchString);\n }, 300));\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n const drake = this.dragula;\n if (this.refs.form) {\n (0, dom_autoscroller_1.default)([window], {\n margin: 20,\n maxSpeed: 6,\n scrollWhenOutside: true,\n autoScroll: function () {\n return this.down && (drake === null || drake === void 0 ? void 0 : drake.dragging);\n }\n });\n return this.webform.attach(this.refs.form);\n }\n });\n }\n searchFields(searchString = '') {\n const searchValue = searchString.toLowerCase();\n const sidebar = this.refs['sidebar'];\n const sidebarGroups = this.refs['sidebar-groups'];\n if (!sidebar || !sidebarGroups) {\n return;\n }\n const filterGroupBy = (group, searchValue = '') => {\n const result = lodash_1.default.toPlainObject(group);\n const { subgroups = [], components } = result;\n const filteredComponents = [];\n for (const key in components) {\n const isMatchedToTitle = this.t(components[key].title).toLowerCase().match(searchValue);\n const isMatchedToKey = components[key].key.toLowerCase().match(searchValue);\n if (isMatchedToTitle || isMatchedToKey) {\n filteredComponents.push(components[key]);\n }\n }\n this.orderComponents(result, filteredComponents);\n if (searchValue) {\n result.default = true;\n }\n if (result.componentOrder.length || subgroups.length) {\n return result;\n }\n return null;\n };\n const filterGroupOrder = (groupOrder, searchValue) => {\n const result = lodash_1.default.cloneDeep(groupOrder);\n return result.filter(key => filterGroupBy(this.groups[key], searchValue));\n };\n const filterSubgroups = (groups, searchValue) => {\n const result = lodash_1.default.clone(groups);\n return result\n .map(subgroup => filterGroupBy(subgroup, searchValue))\n .filter(subgroup => !lodash_1.default.isNull(subgroup));\n };\n const toTemplate = groupKey => {\n return {\n group: filterGroupBy(this.groups[groupKey], searchValue),\n groupKey,\n groupId: sidebar.id || sidebarGroups.id,\n subgroups: filterSubgroups(this.groups[groupKey].subgroups, searchValue)\n .map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n };\n };\n sidebarGroups.innerHTML = filterGroupOrder(this.groupOrder, searchValue)\n .map(groupKey => this.renderTemplate('builderSidebarGroup', toTemplate(groupKey)))\n .join('');\n this.loadRefs(this.element, {\n 'sidebar-groups': 'single',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n });\n this.updateDragAndDrop();\n if (searchValue === '') {\n this.triggerRedraw();\n }\n }\n orderComponents(groupInfo, foundComponents) {\n const components = foundComponents || groupInfo.components;\n const isResource = groupInfo.key.indexOf('resource-') === 0;\n if (components) {\n groupInfo.componentOrder = Object.keys(components)\n .map(key => components[key])\n .filter(component => component && !component.ignore && !component.ignoreForForm)\n .sort((a, b) => a.weight - b.weight)\n .map(component => isResource ? `component-${component.key}` : component.key);\n }\n }\n updateDragAndDrop() {\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n if (this.refs.form) {\n return this.webform.attach(this.refs.form);\n }\n }\n initDragula() {\n const options = this.options;\n if (this.dragula) {\n this.dragula.destroy();\n }\n const containersArray = Array.prototype.slice.call(this.refs['sidebar-container']).filter(item => {\n return item.id !== 'group-container-resource';\n });\n if (!dragula_1.default) {\n return;\n }\n this.dragula = (0, dragula_1.default)(containersArray, {\n moves(el) {\n let moves = true;\n const list = Array.from(el.classList).filter(item => item.indexOf('formio-component-') === 0);\n list.forEach(item => {\n const key = item.slice('formio-component-'.length);\n if (options.disabled && options.disabled.includes(key)) {\n moves = false;\n }\n });\n if (el.classList.contains('no-drag')) {\n moves = false;\n }\n return moves;\n },\n copy(el) {\n return el.classList.contains('drag-copy');\n },\n accepts(el, target) {\n return !el.contains(target) && !target.classList.contains('no-drop');\n }\n }).on('drop', (element, target, source, sibling) => this.onDrop(element, target, source, sibling));\n }\n detach() {\n if (this.dragula) {\n this.dragula.destroy();\n }\n this.dragula = null;\n if (this.sideBarScroll && Templates_1.default.current.clearBuilderSidebarScroll) {\n Templates_1.default.current.clearBuilderSidebarScroll.call(this, this);\n }\n super.detach();\n }\n getComponentInfo(key, group) {\n let info;\n // Need to check in first order as resource component key can be the same as from webform default components\n if (group && group.slice(0, group.indexOf('-')) === 'resource') {\n // This is an existing resource field.\n const resourceGroups = this.groups.resource.subgroups;\n const resourceGroup = lodash_1.default.find(resourceGroups, { key: group });\n if (resourceGroup && resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n }\n }\n // This is a new component\n else if (this.schemas.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(this.schemas[key]);\n }\n else if (this.groups.hasOwnProperty(group)) {\n const groupComponents = this.groups[group].components;\n if (groupComponents.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(groupComponents[key].schema);\n }\n }\n else if (group === 'searchFields') { //Search components go into this group\n const resourceGroups = this.groups.resource.subgroups;\n for (let ix = 0; ix < resourceGroups.length; ix++) {\n const resourceGroup = resourceGroups[ix];\n if (resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n break;\n }\n }\n }\n if (info) {\n //if this is a custom component that was already assigned a key, don't stomp on it\n if (!Components_1.default.components.hasOwnProperty(info.type) && info.key) {\n return info;\n }\n info.key = this.generateKey(info);\n }\n return info;\n }\n getComponentsPath(component, parent) {\n // Get path to the component in the parent component.\n let path = 'components';\n let columnIndex = 0;\n let tableRowIndex = 0;\n let tableColumnIndex = 0;\n let tabIndex = 0;\n switch (parent.type) {\n case 'table':\n tableRowIndex = lodash_1.default.findIndex(parent.rows, row => row.some(column => column.components.some(comp => comp.key === component.key)));\n tableColumnIndex = lodash_1.default.findIndex(parent.rows[tableRowIndex], (column => column.components.some(comp => comp.key === component.key)));\n path = `rows[${tableRowIndex}][${tableColumnIndex}].components`;\n break;\n case 'columns':\n columnIndex = lodash_1.default.findIndex(parent.columns, column => column.components.some(comp => comp.key === component.key));\n path = `columns[${columnIndex}].components`;\n break;\n case 'tabs':\n tabIndex = lodash_1.default.findIndex(parent.components, tab => tab.components.some(comp => comp.key === component.key));\n path = `components[${tabIndex}].components`;\n break;\n }\n return path;\n }\n /* eslint-disable max-statements */\n onDrop(element, target, source, sibling) {\n var _a;\n if (!target) {\n return;\n }\n // If you try to drop within itself.\n if (element.contains(target)) {\n return;\n }\n const key = element.getAttribute('data-key');\n const type = element.getAttribute('data-type');\n const group = element.getAttribute('data-group');\n let info, isNew, path, index;\n if (key && group) {\n // This is a new component.\n info = this.getComponentInfo(key, group);\n if (!info && type) {\n info = this.getComponentInfo(type, group);\n }\n isNew = true;\n }\n else if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n // Grab and remove the component from the source container.\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n // Since splice returns an array of one object, we need to destructure it.\n info = info[0];\n }\n }\n // If we haven't found the component, stop.\n if (!info) {\n return;\n }\n // Show an error if siblings are disabled for a component and such a component already exists.\n const compKey = (group === 'resource') ? `component-${key}` : key;\n const draggableComponent = ((_a = this.groups[group]) === null || _a === void 0 ? void 0 : _a.components[compKey]) || {};\n if (draggableComponent.disableSiblings) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.type === draggableComponent.schema.type) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.key} component to one page.`);\n return;\n }\n }\n if (draggableComponent.uniqueComponent) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.key === draggableComponent.schema.key) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.title} component to one page.`);\n return;\n }\n }\n if (target !== source) {\n // Ensure the key remains unique in its new container.\n builder_1.default.uniquify(this.findNamespaceRoot(target.formioComponent), info);\n }\n const parent = target.formioComponent;\n // Insert in the new container.\n if (target.formioContainer) {\n if (sibling) {\n if (!sibling.getAttribute('data-noattach')) {\n index = lodash_1.default.findIndex(target.formioContainer, { key: lodash_1.default.get(sibling, 'formioComponent.component.key') });\n index = (index === -1) ? 0 : index;\n }\n else {\n index = sibling.getAttribute('data-position');\n }\n if (index !== -1) {\n target.formioContainer.splice(index, 0, info);\n }\n }\n else {\n target.formioContainer.push(info);\n }\n path = this.getComponentsPath(info, parent.component);\n index = lodash_1.default.findIndex(lodash_1.default.get(parent.schema, path), { key: info.key });\n if (index === -1) {\n index = 0;\n }\n }\n if (parent && parent.addChildComponent) {\n parent.addChildComponent(info, element, target, source, sibling);\n }\n const componentInDataGrid = parent.type === 'datagrid';\n if (isNew && !this.options.noNewEdit && !info.noNewEdit && !(this.options.design && info.type === 'reviewpage')) {\n this.editComponent(info, target, isNew, null, null, { inDataGrid: componentInDataGrid });\n }\n // Only rebuild the parts needing to be rebuilt.\n let rebuild;\n if (target !== source) {\n if (source.formioContainer && source.contains(target)) {\n rebuild = source.formioComponent.rebuild();\n }\n else if (target.contains(source)) {\n rebuild = target.formioComponent.rebuild();\n }\n else {\n if (source.formioContainer) {\n rebuild = source.formioComponent.rebuild();\n }\n rebuild = target.formioComponent.rebuild();\n }\n }\n else {\n // If they are the same, only rebuild one.\n rebuild = target.formioComponent.rebuild();\n }\n if (!rebuild) {\n rebuild = Promise.resolve();\n }\n return rebuild.then(() => {\n this.emit('addComponent', info, parent, path, index, isNew && !this.options.noNewEdit && !info.noNewEdit);\n if (!isNew || this.options.noNewEdit || info.noNewEdit) {\n this.emit('change', this.form);\n }\n });\n }\n setForm(form) {\n var _a;\n if (!form.components) {\n form.components = [];\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n this.keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n const isShowSubmitButton = !this.options.noDefaultSubmitButton\n && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));\n // Ensure there is at least a submit button.\n if (isShowSubmitButton) {\n form.components.push({\n type: 'button',\n label: 'Submit',\n key: 'submit',\n size: 'md',\n block: false,\n action: 'submit',\n disableOnInvalid: true,\n theme: 'primary'\n });\n }\n if (this.webform) {\n const shouldRebuild = !this.webform.form.components ||\n (form.components.length !== this.webform.form.components.length);\n return this.webform.setForm(form, { keepAsReference: true }).then(() => {\n if (this.refs.form) {\n this.builderHeight = this.refs.form.offsetHeight;\n }\n if (!shouldRebuild) {\n return this.form;\n }\n return this.rebuild().then(() => this.form);\n });\n }\n return Promise.resolve(form);\n }\n populateRecaptchaSettings(form) {\n //populate isEnabled for recaptcha form settings\n let isRecaptchaEnabled = false;\n if (this.form.components) {\n (0, formUtils_1.eachComponent)(form.components, component => {\n if (isRecaptchaEnabled) {\n return;\n }\n if (component.type === 'recaptcha') {\n isRecaptchaEnabled = true;\n return false;\n }\n });\n if (isRecaptchaEnabled) {\n lodash_1.default.set(form, 'settings.recaptcha.isEnabled', true);\n }\n else if (lodash_1.default.get(form, 'settings.recaptcha.isEnabled')) {\n lodash_1.default.set(form, 'settings.recaptcha.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 && componentInstance.parent) {\n lodash_1.default.unset(componentInstance._data, componentInstance.key);\n }\n const rebuild = parent.formioComponent.rebuild() || Promise.resolve();\n rebuild.then(() => {\n this.emit('removeComponent', component, parent.formioComponent.schema, path, index);\n this.emit('change', this.form);\n });\n }\n return remove;\n }\n replaceDoubleQuotes(data, fieldsToRemoveDoubleQuotes = []) {\n if (data) {\n fieldsToRemoveDoubleQuotes.forEach((key) => {\n if (data[key]) {\n data[key] = data[key].replace(/\"/g, \"'\");\n }\n });\n return data;\n }\n }\n updateComponent(component, changed) {\n const sanitizeConfig = lodash_1.default.get(this.webform, 'form.settings.sanitizeConfig') || lodash_1.default.get(this.webform, 'form.globalSettings.sanitizeConfig');\n // Update the preview.\n if (this.preview) {\n this.preview.form = {\n components: [lodash_1.default.omit(Object.assign({}, component), [\n 'hidden',\n 'conditional',\n 'calculateValue',\n 'logic',\n 'autofocus',\n 'customConditional',\n ])],\n config: this.options.formConfig || {},\n sanitizeConfig,\n };\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.preview.form.components.forEach(component => this.replaceDoubleQuotes(component, fieldsToRemoveDoubleQuotes));\n const previewElement = this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"preview\"]`);\n if (previewElement) {\n this.setContent(previewElement, this.preview.render(), null, sanitizeConfig);\n this.preview.attach(previewElement);\n }\n }\n // Change the \"default value\" field to be reflective of this component.\n const defaultValueComponent = (0, formUtils_1.getComponent)(this.editForm.components, 'defaultValue', true);\n if (defaultValueComponent && component.type !== 'hidden') {\n const defaultChanged = changed && ((changed.component && changed.component.key === 'defaultValue')\n || (changed.instance && defaultValueComponent.hasComponent && defaultValueComponent.hasComponent(changed.instance)));\n if (!defaultChanged) {\n lodash_1.default.assign(defaultValueComponent.component, lodash_1.default.omit(Object.assign({}, component), [\n 'key',\n 'label',\n 'labelPosition',\n 'labelMargin',\n 'labelWidth',\n 'placeholder',\n 'tooltip',\n 'hidden',\n 'autofocus',\n 'validate',\n 'disabled',\n 'defaultValue',\n 'customDefaultValue',\n 'calculateValue',\n 'conditional',\n 'customConditional',\n 'id'\n ]));\n const parentComponent = defaultValueComponent.parent;\n let tabIndex = -1;\n let index = -1;\n parentComponent.tabs.some((tab, tIndex) => {\n tab.some((comp, compIndex) => {\n if (comp.id === defaultValueComponent.id) {\n tabIndex = tIndex;\n index = compIndex;\n return true;\n }\n return false;\n });\n });\n if (tabIndex !== -1 && index !== -1 && changed && !lodash_1.default.isNil(changed.value)) {\n const sibling = parentComponent.tabs[tabIndex][index + 1];\n parentComponent.removeComponent(defaultValueComponent);\n const newComp = parentComponent.addComponent(defaultValueComponent.component, defaultValueComponent.data, sibling);\n lodash_1.default.pull(newComp.validators, 'required');\n parentComponent.tabs[tabIndex].splice(index, 1, newComp);\n newComp.checkValidity = () => true;\n newComp.build(defaultValueComponent.element);\n }\n }\n else {\n let dataPath = changed.instance._data.key;\n const path = (0, utils_1.getArrayFromComponentPath)(changed.instance.path);\n path.shift();\n if (path.length) {\n path.unshift(component.key);\n dataPath = (0, utils_1.getStringFromComponentPath)(path);\n }\n lodash_1.default.set(this.preview._data, dataPath, changed.value);\n lodash_1.default.set(this.webform._data, dataPath, changed.value);\n }\n }\n // Called when we update a component.\n this.emit('updateComponent', component);\n }\n findRepeatablePaths() {\n const repeatablePaths = [];\n const keys = new Map();\n (0, formUtils_1.eachComponent)(this.form.components, (comp, path) => {\n if (!comp.key) {\n return;\n }\n if (keys.has(comp.key)) {\n if (keys.get(comp.key).includes(path)) {\n repeatablePaths.push(path);\n }\n else {\n keys.set(comp.key, [...keys.get(comp.key), path]);\n }\n }\n else {\n keys.set(comp.key, [path]);\n }\n }, true);\n return repeatablePaths;\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n let hasInvalidComponents = false;\n this.webform.everyComponent((comp) => {\n var _a;\n const path = comp.path;\n const errors = comp.visibleErrors || [];\n if (repeatablePaths.includes(path)) {\n comp.setCustomValidity(`API Key is not unique: ${comp.key}`);\n hasInvalidComponents = true;\n }\n else if (errors.length && ((_a = errors[0].message) === null || _a === void 0 ? void 0 : _a.startsWith('API Key is not unique'))) {\n comp.setCustomValidity('');\n }\n });\n this.emit('builderFormValidityChange', hasInvalidComponents);\n }\n /**\n * Called when a new component is saved.\n *\n * @param parent\n * @param component\n * @return {boolean}\n */\n saveComponent(component, parent, isNew, original) {\n this.editForm.detach();\n const parentContainer = parent ? parent.formioContainer : this.container;\n const parentComponent = parent ? parent.formioComponent : this;\n this.dialog.close();\n const path = parentContainer ? this.getComponentsPath(component, parentComponent.component) : '';\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parentContainer ? parentContainer.indexOf(original) : 0;\n if (index !== -1) {\n let submissionData = this.editForm.submission.data;\n submissionData = submissionData.componentJson || submissionData;\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.replaceDoubleQuotes(submissionData, fieldsToRemoveDoubleQuotes);\n this.hook('beforeSaveComponentSettings', submissionData);\n let comp = null;\n parentComponent.getComponents().forEach((component) => {\n if (component.component.key === original.key) {\n comp = component;\n }\n });\n const originalComp = comp === null || comp === void 0 ? void 0 : comp.component;\n const originalComponentSchema = comp === null || comp === void 0 ? void 0 : comp.schema;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parentContainer && !isParentSaveChildMethod) {\n parentContainer[index] = submissionData;\n if (comp) {\n comp.component = submissionData;\n }\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(submissionData);\n }\n const rebuild = parentComponent.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n const schema = parentContainer ? parentContainer[index] : (comp ? comp.schema : []);\n this.emitSaveComponentEvent(schema, originalComp, parentComponent.schema, path, index, isNew, originalComponentSchema);\n this.emit('change', this.form);\n this.highlightInvalidComponents();\n if (this.isComponentCreated) {\n const component = parent.formioComponent.components[0];\n this.moveComponent(component);\n this.isComponentCreated = false;\n }\n });\n }\n this.highlightInvalidComponents();\n return Promise.resolve();\n }\n emitSaveComponentEvent(schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema) {\n this.emit('saveComponent', schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema);\n }\n attachEditComponentControls(component, parent, isNew, original, ComponentClass) {\n const cancelButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"cancelButton\"]`);\n cancelButtons.forEach((cancelButton) => {\n this.editForm.addEventListener(cancelButton, 'click', (event) => {\n event.preventDefault();\n this.editForm.detach();\n this.emit('cancelComponent', component);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const removeButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"removeButton\"]`);\n removeButtons.forEach((removeButton) => {\n this.editForm.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n // Since we are already removing the component, don't trigger another remove.\n this.saved = true;\n this.editForm.detach();\n this.removeComponent(component, parent, original);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const saveButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"saveButton\"]`);\n saveButtons.forEach((saveButton) => {\n this.editForm.addEventListener(saveButton, 'click', (event) => {\n event.preventDefault();\n const errors = this.editForm.validate(this.editForm.data, {\n dirty: true\n });\n if (errors.length) {\n this.editForm.setPristine(false);\n this.editForm.showErrors(errors);\n return false;\n }\n this.saved = true;\n this.saveComponent(component, parent, isNew, original);\n });\n });\n const previewButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"previewButton\"]`);\n previewButtons.forEach((previewButton) => {\n this.editForm.addEventListener(previewButton, 'click', (event) => {\n event.preventDefault();\n this.showPreview = !this.showPreview;\n this.editForm.detach();\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks,\n }));\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n });\n });\n }\n editComponent(component, parent, isNew, isJsonEdit, original, flags = {}) {\n var _a, _b;\n if (!component.key) {\n return;\n }\n this.saved = false;\n const componentCopy = (0, utils_1.fastCloneDeep)(component);\n let ComponentClass = Components_1.default.components[componentCopy.type];\n const isCustom = ComponentClass === undefined;\n isJsonEdit = isJsonEdit || isCustom;\n ComponentClass = isCustom ? Components_1.default.components.unknown : ComponentClass;\n // Make sure we only have one dialog open at a time.\n if (this.dialog) {\n this.dialog.close();\n this.highlightInvalidComponents();\n }\n // This is the render step.\n const editFormOptions = lodash_1.default.clone(lodash_1.default.get(this, 'options.editForm', {}));\n if (this.editForm) {\n this.editForm.destroy();\n }\n // Allow editForm overrides per component.\n const overrides = lodash_1.default.get(this.options, `editForm.${componentCopy.type}`, {});\n // Pass along the form being edited.\n editFormOptions.editForm = this.form;\n editFormOptions.editComponent = component;\n editFormOptions.flags = flags;\n this.hook('editComponentParentInstance', editFormOptions, parent);\n this.editForm = new Webform_1.default(Object.assign(Object.assign(Object.assign(Object.assign({}, lodash_1.default.omit(this.options, ['hooks', 'builder', 'events', 'attachMode', 'skipInit'])), { language: this.options.language }), editFormOptions), { evalContext: Object.assign(Object.assign({}, ((editFormOptions === null || editFormOptions === void 0 ? void 0 : editFormOptions.evalContext) || ((_a = this.options) === null || _a === void 0 ? void 0 : _a.evalContext) || {})), { buildingForm: this.form }) }));\n this.hook('editFormProperties', parent);\n this.editForm.form = (isJsonEdit && !isCustom) ? {\n components: [\n {\n type: 'textarea',\n as: 'json',\n editor: 'ace',\n weight: 10,\n input: true,\n key: 'componentJson',\n label: 'Component JSON',\n tooltip: 'Edit the JSON for this component.'\n },\n {\n type: 'checkbox',\n key: 'showFullSchema',\n label: 'Full Schema'\n }\n ]\n } : ComponentClass.editForm(lodash_1.default.cloneDeep(overrides));\n const instanceOptions = {\n inFormBuilder: true,\n };\n this.hook('instanceOptionsPreview', instanceOptions);\n const instance = new ComponentClass(componentCopy, instanceOptions);\n const schema = this.hook('builderComponentSchema', component, instance);\n this.editForm.submission = isJsonEdit ? {\n data: {\n componentJson: schema,\n showFullSchema: this.options.showFullJsonSchema\n },\n } : {\n data: instance.component,\n };\n if (this.preview) {\n this.preview.destroy();\n }\n if (!ComponentClass.builderInfo.hasOwnProperty('preview') || ComponentClass.builderInfo.preview) {\n this.preview = new Webform_1.default(lodash_1.default.omit(Object.assign(Object.assign({}, this.options), { preview: true }), [\n 'hooks',\n 'builder',\n 'events',\n 'attachMode',\n 'calculateValue'\n ]));\n this.hook('previewFormSettitngs', schema, isJsonEdit);\n }\n this.showPreview = (_b = ComponentClass.builderInfo.showPreview) !== null && _b !== void 0 ? _b : true;\n this.componentEdit = this.ce('div', { 'class': 'component-edit-container' });\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks\n }));\n this.dialog = this.createModal(this.componentEdit, lodash_1.default.get(this.options, 'dialogAttr', {}));\n // This is the attach step.\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.hook('editFormWrapper');\n this.updateComponent(componentCopy);\n this.editForm.on('change', (event) => {\n if (event.changed) {\n if (event.changed.component && event.changed.component.key === 'showFullSchema') {\n const { value } = event.changed;\n this.editForm.submission = {\n data: {\n componentJson: value ? instance.component : component,\n showFullSchema: value\n },\n };\n return;\n }\n // See if this is a manually modified key. Treat custom component keys as manually modified\n if ((event.changed.component && (event.changed.component.key === 'key')) || isJsonEdit) {\n componentCopy.keyModified = true;\n }\n let isComponentLabelChanged = false;\n if (event.changed.instance) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.instance.path);\n }\n else if (event.changed.component) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.component.key);\n }\n if (isComponentLabelChanged) {\n // Ensure this component has a key.\n if (isNew) {\n if (!event.data.keyModified) {\n this.editForm.everyComponent(component => {\n if (component.key === 'key' && component.parent.component.key === 'tabs') {\n component.setValue(this.updateComponentKey(event.data));\n return false;\n }\n });\n }\n if (this.form) {\n let formComponents = this.findNamespaceRoot(parent.formioComponent);\n // excluding component which key uniqueness is to be checked to prevent the comparing of the same keys\n formComponents = formComponents.filter(comp => editFormOptions.editComponent.id !== comp.id);\n // Set a unique key for this component.\n builder_1.default.uniquify(formComponents, event.data);\n }\n }\n }\n // If the edit form has any nested form inside, we get a partial data (nested form's data) in the\n // event.data property\n let editFormData;\n if (event.changed.instance && event.changed.instance.root && event.changed.instance.root.id !== this.editForm.id) {\n editFormData = this.editForm.data;\n }\n // Update the component.\n this.updateComponent(event.data.componentJson || editFormData || event.data, event.changed);\n }\n });\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n const dialogClose = () => {\n this.editForm.destroy(true);\n if (this.preview) {\n this.preview.destroy(true);\n this.preview = null;\n }\n if (isNew && !this.saved) {\n this.removeComponent(component, parent, original);\n this.highlightInvalidComponents();\n }\n // Clean up.\n this.removeEventListener(this.dialog, 'close', dialogClose);\n this.dialog = null;\n };\n this.addEventListener(this.dialog, 'close', dialogClose);\n // Called when we edit a component.\n this.emit('editComponent', component);\n }\n updateComponentKey(data) {\n return lodash_1.default.camelCase(data.title ||\n data.label ||\n data.placeholder ||\n data.type).replace(/^[0-9]*/, '');\n }\n moveComponent(component) {\n var _a;\n if (this.selectedComponent) {\n const prevSelected = this.selectedComponent;\n (_a = prevSelected.element) === null || _a === void 0 ? void 0 : _a.classList.remove('builder-component-selected');\n this.removeEventListener(document, 'keydown');\n }\n component.element.focus();\n component.element.classList.add('builder-component-selected');\n this.selectedComponent = component;\n this.addEventListener(document, 'keydown', this.moveHandler.bind(this));\n }\n updateComponentPlacement(direction) {\n const component = this.selectedComponent;\n let index, info;\n const step = direction ? -1 : 1;\n if (component) {\n const element = component.element;\n const sibling = direction ? element.previousElementSibling : element.nextElementSibling;\n const source = element.parentNode;\n const containerLength = source.formioContainer.length;\n if (containerLength && containerLength <= 1) {\n return;\n }\n if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n info = info[0];\n source.removeChild(element);\n }\n }\n const len = source.formioComponent.components.length;\n index = (index === -1) ? 0 : index + step;\n if (index === -1) {\n source.formioContainer.push(info);\n source.appendChild(element);\n }\n else if (index === len) {\n const key = source.formioContainer[0].key;\n index = lodash_1.default.findIndex(source.formioComponent.components, { key: key });\n const firstElement = source.formioComponent.components[index].element;\n source.formioContainer.splice(0, 0, info);\n source.insertBefore(element, firstElement);\n }\n else if (index !== -1) {\n source.formioContainer.splice(index, 0, info);\n direction\n ? source.insertBefore(element, sibling)\n : source.insertBefore(element, sibling.nextElementSibling);\n }\n element.focus();\n }\n }\n stopMoving(comp) {\n const parent = comp.element.parentNode;\n this.removeEventListener(document, 'keydown');\n parent.formioComponent.rebuild();\n this.selectedComponent = null;\n }\n addNewComponent(element) {\n var _a;\n const source = document.querySelector('.formio-builder-form');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const isNew = true;\n let info;\n if (key && group) {\n info = this.getComponentInfo(key, group);\n }\n if (isNew && !this.options.noNewEdit && !info.noNewEdit) {\n builder_1.default.uniquify(this.findNamespaceRoot(source.formioComponent), info);\n this.editComponent(info, source, isNew, null, null);\n }\n const firstComponent = (_a = source.formioComponent.components[0]) === null || _a === void 0 ? void 0 : _a.element;\n if (firstComponent) {\n source.formioContainer.splice(0, 0, info);\n }\n else {\n source.formioContainer.push(info);\n }\n source.formioComponent.rebuild().then(() => {\n this.isComponentCreated = true;\n });\n }\n /**\n * Creates copy of component schema and stores it under sessionStorage.\n * @param {Component} component\n * @return {*}\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\n * @return {*}\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(deleteFromGlobal) {\n if (this.webform.initialized) {\n this.webform.destroy(deleteFromGlobal);\n }\n super.destroy(deleteFromGlobal);\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?");
5577
+ 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 *\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 component\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.populateRecaptchaSettings(form);\n this.webform.setAlert(false);\n });\n return super.attach(element).then(() => {\n this.loadRefs(element, {\n form: 'single',\n sidebar: 'single',\n 'sidebar-search': 'single',\n 'sidebar-groups': 'single',\n 'container': 'multiple',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n 'sidebar-component': 'multiple',\n });\n if (this.sideBarScroll && Templates_1.default.current.handleBuilderSidebarScroll) {\n Templates_1.default.current.handleBuilderSidebarScroll.call(this, this);\n }\n // Add the paste status in form\n if (typeof window !== 'undefined' && window.sessionStorage) {\n const data = window.sessionStorage.getItem('formio.clipboard');\n if (data) {\n this.addClass(this.refs.form, 'builder-paste-mode');\n }\n }\n if (!(0, utils_1.bootstrapVersion)(this.options)) {\n const getAttribute = (anchor, attribute) => {\n let elem = anchor.getAttribute(`data-${attribute}`);\n if (!elem) {\n elem = anchor.getAttribute(`data-bs-${attribute}`);\n }\n return elem;\n };\n const hideShow = (group, show) => {\n if (show) {\n group.classList.add(['show']);\n group.style.display = 'inherit';\n }\n else {\n group.classList.remove(['show']);\n group.style.display = 'none';\n }\n };\n // Initialize\n this.refs['sidebar-group'].forEach((group) => {\n hideShow(group, getAttribute(group, 'default') === 'true');\n });\n // Click event\n this.refs['sidebar-anchor'].forEach((anchor, index) => {\n this.addEventListener(anchor, 'click', () => {\n const clickedParentId = getAttribute(anchor, 'parent').slice('#builder-sidebar-'.length);\n const clickedId = getAttribute(anchor, 'target').slice('#group-'.length);\n this.refs['sidebar-group'].forEach((group, groupIndex) => {\n const openByDefault = getAttribute(group, 'default') === 'true';\n const groupId = group.getAttribute('id').slice('group-'.length);\n const groupParent = getAttribute(group, 'parent').slice('#builder-sidebar-'.length);\n hideShow(group, ((openByDefault && groupParent === clickedId) || groupId === clickedParentId || groupIndex === index));\n });\n }, true);\n });\n }\n if (this.keyboardActionsEnabled) {\n this.refs['sidebar-component'].forEach((component) => {\n this.addEventListener(component, 'keydown', (event) => {\n if (event.keyCode === 13) {\n this.addNewComponent(component);\n }\n });\n });\n }\n this.addEventListener(this.refs['sidebar-search'], 'input', lodash_1.default.debounce((e) => {\n const searchString = e.target.value;\n this.searchFields(searchString);\n }, 300));\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n const drake = this.dragula;\n if (this.refs.form) {\n (0, dom_autoscroller_1.default)([window], {\n margin: 20,\n maxSpeed: 6,\n scrollWhenOutside: true,\n autoScroll: function () {\n return this.down && (drake === null || drake === void 0 ? void 0 : drake.dragging);\n }\n });\n return this.webform.attach(this.refs.form);\n }\n });\n }\n searchFields(searchString = '') {\n const searchValue = searchString.toLowerCase();\n const sidebar = this.refs['sidebar'];\n const sidebarGroups = this.refs['sidebar-groups'];\n if (!sidebar || !sidebarGroups) {\n return;\n }\n const filterGroupBy = (group, searchValue = '') => {\n const result = lodash_1.default.toPlainObject(group);\n const { subgroups = [], components } = result;\n const filteredComponents = [];\n for (const key in components) {\n const isMatchedToTitle = this.t(components[key].title).toLowerCase().match(searchValue);\n const isMatchedToKey = components[key].key.toLowerCase().match(searchValue);\n if (isMatchedToTitle || isMatchedToKey) {\n filteredComponents.push(components[key]);\n }\n }\n this.orderComponents(result, filteredComponents);\n if (searchValue) {\n result.default = true;\n }\n if (result.componentOrder.length || subgroups.length) {\n return result;\n }\n return null;\n };\n const filterGroupOrder = (groupOrder, searchValue) => {\n const result = lodash_1.default.cloneDeep(groupOrder);\n return result.filter(key => filterGroupBy(this.groups[key], searchValue));\n };\n const filterSubgroups = (groups, searchValue) => {\n const result = lodash_1.default.clone(groups);\n return result\n .map(subgroup => filterGroupBy(subgroup, searchValue))\n .filter(subgroup => !lodash_1.default.isNull(subgroup));\n };\n const toTemplate = groupKey => {\n return {\n group: filterGroupBy(this.groups[groupKey], searchValue),\n groupKey,\n groupId: sidebar.id || sidebarGroups.id,\n subgroups: filterSubgroups(this.groups[groupKey].subgroups, searchValue)\n .map((group) => this.renderTemplate('builderSidebarGroup', {\n group,\n groupKey: group.key,\n groupId: `group-container-${groupKey}`,\n subgroups: []\n })),\n };\n };\n sidebarGroups.innerHTML = filterGroupOrder(this.groupOrder, searchValue)\n .map(groupKey => this.renderTemplate('builderSidebarGroup', toTemplate(groupKey)))\n .join('');\n this.loadRefs(this.element, {\n 'sidebar-groups': 'single',\n 'sidebar-anchor': 'multiple',\n 'sidebar-group': 'multiple',\n 'sidebar-container': 'multiple',\n });\n this.updateDragAndDrop();\n if (searchValue === '') {\n this.triggerRedraw();\n }\n }\n orderComponents(groupInfo, foundComponents) {\n const components = foundComponents || groupInfo.components;\n const isResource = groupInfo.key.indexOf('resource-') === 0;\n if (components) {\n groupInfo.componentOrder = Object.keys(components)\n .map(key => components[key])\n .filter(component => component && !component.ignore && !component.ignoreForForm)\n .sort((a, b) => a.weight - b.weight)\n .map(component => isResource ? `component-${component.key}` : component.key);\n }\n }\n updateDragAndDrop() {\n if (this.dragDropEnabled) {\n this.initDragula();\n }\n if (this.refs.form) {\n return this.webform.attach(this.refs.form);\n }\n }\n initDragula() {\n const options = this.options;\n if (this.dragula) {\n this.dragula.destroy();\n }\n const containersArray = Array.prototype.slice.call(this.refs['sidebar-container']).filter(item => {\n return item.id !== 'group-container-resource';\n });\n if (!dragula_1.default) {\n return;\n }\n this.dragula = (0, dragula_1.default)(containersArray, {\n moves(el) {\n let moves = true;\n const list = Array.from(el.classList).filter(item => item.indexOf('formio-component-') === 0);\n list.forEach(item => {\n const key = item.slice('formio-component-'.length);\n if (options.disabled && options.disabled.includes(key)) {\n moves = false;\n }\n });\n if (el.classList.contains('no-drag')) {\n moves = false;\n }\n return moves;\n },\n copy(el) {\n return el.classList.contains('drag-copy');\n },\n accepts(el, target) {\n return !el.contains(target) && !target.classList.contains('no-drop');\n }\n }).on('drop', (element, target, source, sibling) => this.onDrop(element, target, source, sibling));\n }\n detach() {\n if (this.dragula) {\n this.dragula.destroy();\n }\n this.dragula = null;\n if (this.sideBarScroll && Templates_1.default.current.clearBuilderSidebarScroll) {\n Templates_1.default.current.clearBuilderSidebarScroll.call(this, this);\n }\n super.detach();\n }\n getComponentInfo(key, group) {\n let info;\n // Need to check in first order as resource component key can be the same as from webform default components\n if (group && group.slice(0, group.indexOf('-')) === 'resource') {\n // This is an existing resource field.\n const resourceGroups = this.groups.resource.subgroups;\n const resourceGroup = lodash_1.default.find(resourceGroups, { key: group });\n if (resourceGroup && resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n }\n }\n // This is a new component\n else if (this.schemas.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(this.schemas[key]);\n }\n else if (this.groups.hasOwnProperty(group)) {\n const groupComponents = this.groups[group].components;\n if (groupComponents.hasOwnProperty(key)) {\n info = (0, utils_1.fastCloneDeep)(groupComponents[key].schema);\n }\n }\n else if (group === 'searchFields') { //Search components go into this group\n const resourceGroups = this.groups.resource.subgroups;\n for (let ix = 0; ix < resourceGroups.length; ix++) {\n const resourceGroup = resourceGroups[ix];\n if (resourceGroup.components.hasOwnProperty(`component-${key}`)) {\n info = (0, utils_1.fastCloneDeep)(resourceGroup.components[`component-${key}`].schema);\n break;\n }\n }\n }\n if (info) {\n //if this is a custom component that was already assigned a key, don't stomp on it\n if (!Components_1.default.components.hasOwnProperty(info.type) && info.key) {\n return info;\n }\n info.key = this.generateKey(info);\n }\n return info;\n }\n getComponentsPath(component, parent) {\n // Get path to the component in the parent component.\n let path = 'components';\n let columnIndex = 0;\n let tableRowIndex = 0;\n let tableColumnIndex = 0;\n let tabIndex = 0;\n switch (parent.type) {\n case 'table':\n tableRowIndex = lodash_1.default.findIndex(parent.rows, row => row.some(column => column.components.some(comp => comp.key === component.key)));\n tableColumnIndex = lodash_1.default.findIndex(parent.rows[tableRowIndex], (column => column.components.some(comp => comp.key === component.key)));\n path = `rows[${tableRowIndex}][${tableColumnIndex}].components`;\n break;\n case 'columns':\n columnIndex = lodash_1.default.findIndex(parent.columns, column => column.components.some(comp => comp.key === component.key));\n path = `columns[${columnIndex}].components`;\n break;\n case 'tabs':\n tabIndex = lodash_1.default.findIndex(parent.components, tab => tab.components.some(comp => comp.key === component.key));\n path = `components[${tabIndex}].components`;\n break;\n }\n return path;\n }\n /* eslint-disable max-statements */\n onDrop(element, target, source, sibling) {\n var _a;\n if (!target) {\n return;\n }\n // If you try to drop within itself.\n if (element.contains(target)) {\n return;\n }\n const key = element.getAttribute('data-key');\n const type = element.getAttribute('data-type');\n const group = element.getAttribute('data-group');\n let info, isNew, path, index;\n if (key && group) {\n // This is a new component.\n info = this.getComponentInfo(key, group);\n if (!info && type) {\n info = this.getComponentInfo(type, group);\n }\n isNew = true;\n }\n else if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n // Grab and remove the component from the source container.\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n // Since splice returns an array of one object, we need to destructure it.\n info = info[0];\n }\n }\n // If we haven't found the component, stop.\n if (!info) {\n return;\n }\n // Show an error if siblings are disabled for a component and such a component already exists.\n const compKey = (group === 'resource') ? `component-${key}` : key;\n const draggableComponent = ((_a = this.groups[group]) === null || _a === void 0 ? void 0 : _a.components[compKey]) || {};\n if (draggableComponent.disableSiblings) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.type === draggableComponent.schema.type) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.key} component to one page.`);\n return;\n }\n }\n if (draggableComponent.uniqueComponent) {\n let isCompAlreadyExists = false;\n (0, formUtils_1.eachComponent)(this.webform.components, (component) => {\n if (component.key === draggableComponent.schema.key) {\n isCompAlreadyExists = true;\n return;\n }\n }, true);\n if (isCompAlreadyExists) {\n this.webform.redraw();\n this.webform.setAlert('danger', `You cannot add more than one ${draggableComponent.title} component to one page.`);\n return;\n }\n }\n if (target !== source) {\n // Ensure the key remains unique in its new container.\n builder_1.default.uniquify(this.findNamespaceRoot(target.formioComponent), info);\n }\n const parent = target.formioComponent;\n // Insert in the new container.\n if (target.formioContainer) {\n if (sibling) {\n if (!sibling.getAttribute('data-noattach')) {\n index = lodash_1.default.findIndex(target.formioContainer, { key: lodash_1.default.get(sibling, 'formioComponent.component.key') });\n index = (index === -1) ? 0 : index;\n }\n else {\n index = sibling.getAttribute('data-position');\n }\n if (index !== -1) {\n target.formioContainer.splice(index, 0, info);\n }\n }\n else {\n target.formioContainer.push(info);\n }\n path = this.getComponentsPath(info, parent.component);\n index = lodash_1.default.findIndex(lodash_1.default.get(parent.schema, path), { key: info.key });\n if (index === -1) {\n index = 0;\n }\n }\n if (parent && parent.addChildComponent) {\n parent.addChildComponent(info, element, target, source, sibling);\n }\n const componentInDataGrid = parent.type === 'datagrid';\n if (isNew && !this.options.noNewEdit && !info.noNewEdit && !(this.options.design && info.type === 'reviewpage')) {\n this.editComponent(info, target, isNew, null, null, { inDataGrid: componentInDataGrid });\n }\n // Only rebuild the parts needing to be rebuilt.\n let rebuild;\n if (target !== source) {\n if (source.formioContainer && source.contains(target)) {\n rebuild = source.formioComponent.rebuild();\n }\n else if (target.contains(source)) {\n rebuild = target.formioComponent.rebuild();\n }\n else {\n if (source.formioContainer) {\n rebuild = source.formioComponent.rebuild();\n }\n rebuild = target.formioComponent.rebuild();\n }\n }\n else {\n // If they are the same, only rebuild one.\n rebuild = target.formioComponent.rebuild();\n }\n if (!rebuild) {\n rebuild = Promise.resolve();\n }\n return rebuild.then(() => {\n this.emit('addComponent', info, parent, path, index, isNew && !this.options.noNewEdit && !info.noNewEdit);\n if (!isNew || this.options.noNewEdit || info.noNewEdit) {\n this.emit('change', this.form);\n }\n });\n }\n setForm(form) {\n var _a;\n if (!form.components) {\n form.components = [];\n }\n if (form && form.properties) {\n this.options.properties = form.properties;\n }\n this.keyboardActionsEnabled = lodash_1.default.get(this.options, 'keyboardBuilder', false) || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.keyboardBuilder);\n const isShowSubmitButton = !this.options.noDefaultSubmitButton\n && (!form.components.length || !form.components.find(comp => comp.key === 'submit'));\n // Ensure there is at least a submit button.\n if (isShowSubmitButton) {\n form.components.push({\n type: 'button',\n label: 'Submit',\n key: 'submit',\n size: 'md',\n block: false,\n action: 'submit',\n disableOnInvalid: true,\n theme: 'primary'\n });\n }\n if (this.webform) {\n const shouldRebuild = !this.webform.form.components ||\n (form.components.length !== this.webform.form.components.length);\n return this.webform.setForm(form, { keepAsReference: true }).then(() => {\n if (this.refs.form) {\n this.builderHeight = this.refs.form.offsetHeight;\n }\n if (!shouldRebuild) {\n return this.form;\n }\n return this.rebuild().then(() => this.form);\n });\n }\n return Promise.resolve(form);\n }\n populateRecaptchaSettings(form) {\n //populate isEnabled for recaptcha form settings\n let isRecaptchaEnabled = false;\n if (this.form.components) {\n (0, formUtils_1.eachComponent)(form.components, component => {\n if (isRecaptchaEnabled) {\n return;\n }\n if (component.type === 'recaptcha') {\n isRecaptchaEnabled = true;\n return false;\n }\n });\n if (isRecaptchaEnabled) {\n lodash_1.default.set(form, 'settings.recaptcha.isEnabled', true);\n }\n else if (lodash_1.default.get(form, 'settings.recaptcha.isEnabled')) {\n lodash_1.default.set(form, 'settings.recaptcha.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 && componentInstance.parent) {\n lodash_1.default.unset(componentInstance._data, componentInstance.key);\n }\n const rebuild = parent.formioComponent.rebuild() || Promise.resolve();\n rebuild.then(() => {\n this.emit('removeComponent', component, parent.formioComponent.schema, path, index);\n this.emit('change', this.form);\n });\n }\n return remove;\n }\n replaceDoubleQuotes(data, fieldsToRemoveDoubleQuotes = []) {\n if (data) {\n fieldsToRemoveDoubleQuotes.forEach((key) => {\n if (data[key]) {\n data[key] = data[key].replace(/\"/g, \"'\");\n }\n });\n return data;\n }\n }\n updateComponent(component, changed) {\n const sanitizeConfig = lodash_1.default.get(this.webform, 'form.settings.sanitizeConfig') || lodash_1.default.get(this.webform, 'form.globalSettings.sanitizeConfig');\n // Update the preview.\n if (this.preview) {\n this.preview.form = {\n components: [lodash_1.default.omit(Object.assign({}, component), [\n 'hidden',\n 'conditional',\n 'calculateValue',\n 'logic',\n 'autofocus',\n 'customConditional',\n ])],\n config: this.options.formConfig || {},\n sanitizeConfig,\n };\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.preview.form.components.forEach(component => this.replaceDoubleQuotes(component, fieldsToRemoveDoubleQuotes));\n const previewElement = this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"preview\"]`);\n if (previewElement) {\n this.setContent(previewElement, this.preview.render(), null, sanitizeConfig);\n this.preview.attach(previewElement);\n }\n }\n // Change the \"default value\" field to be reflective of this component.\n const defaultValueComponent = (0, formUtils_1.getComponent)(this.editForm.components, 'defaultValue', true);\n if (defaultValueComponent && component.type !== 'hidden') {\n const defaultChanged = changed && ((changed.component && changed.component.key === 'defaultValue')\n || (changed.instance && defaultValueComponent.hasComponent && defaultValueComponent.hasComponent(changed.instance)));\n if (!defaultChanged) {\n lodash_1.default.assign(defaultValueComponent.component, lodash_1.default.omit(Object.assign({}, component), [\n 'key',\n 'label',\n 'labelPosition',\n 'labelMargin',\n 'labelWidth',\n 'placeholder',\n 'tooltip',\n 'hidden',\n 'autofocus',\n 'validate',\n 'disabled',\n 'defaultValue',\n 'customDefaultValue',\n 'calculateValue',\n 'conditional',\n 'customConditional',\n 'id'\n ]));\n const parentComponent = defaultValueComponent.parent;\n let tabIndex = -1;\n let index = -1;\n parentComponent.tabs.some((tab, tIndex) => {\n tab.some((comp, compIndex) => {\n if (comp.id === defaultValueComponent.id) {\n tabIndex = tIndex;\n index = compIndex;\n return true;\n }\n return false;\n });\n });\n if (tabIndex !== -1 && index !== -1 && changed && !lodash_1.default.isNil(changed.value)) {\n const sibling = parentComponent.tabs[tabIndex][index + 1];\n parentComponent.removeComponent(defaultValueComponent);\n const newComp = parentComponent.addComponent(defaultValueComponent.component, defaultValueComponent.data, sibling);\n lodash_1.default.pull(newComp.validators, 'required');\n parentComponent.tabs[tabIndex].splice(index, 1, newComp);\n newComp.checkValidity = () => true;\n newComp.build(defaultValueComponent.element);\n }\n }\n else {\n let dataPath = changed.instance._data.key;\n const path = (0, utils_1.getArrayFromComponentPath)(changed.instance.path);\n path.shift();\n if (path.length) {\n path.unshift(component.key);\n dataPath = (0, utils_1.getStringFromComponentPath)(path);\n }\n lodash_1.default.set(this.preview._data, dataPath, changed.value);\n lodash_1.default.set(this.webform._data, dataPath, changed.value);\n }\n }\n // Called when we update a component.\n this.emit('updateComponent', component);\n }\n findRepeatablePaths() {\n const repeatablePaths = [];\n const keys = new Map();\n (0, formUtils_1.eachComponent)(this.form.components, (comp, path) => {\n if (!comp.key) {\n return;\n }\n if (keys.has(comp.key)) {\n if (keys.get(comp.key).includes(path)) {\n repeatablePaths.push(path);\n }\n else {\n keys.set(comp.key, [...keys.get(comp.key), path]);\n }\n }\n else {\n keys.set(comp.key, [path]);\n }\n }, true);\n return repeatablePaths;\n }\n highlightInvalidComponents() {\n const repeatablePaths = this.findRepeatablePaths();\n let hasInvalidComponents = false;\n this.webform.everyComponent((comp) => {\n var _a;\n const path = comp.path;\n const errors = comp.visibleErrors || [];\n if (repeatablePaths.includes(path)) {\n comp.setCustomValidity(`API Key is not unique: ${comp.key}`);\n hasInvalidComponents = true;\n }\n else if (errors.length && ((_a = errors[0].message) === null || _a === void 0 ? void 0 : _a.startsWith('API Key is not unique'))) {\n comp.setCustomValidity('');\n }\n });\n this.emit('builderFormValidityChange', hasInvalidComponents);\n }\n /**\n * Called when a new component is saved.\n *\n * @param parent\n * @param component\n * @return {boolean}\n */\n saveComponent(component, parent, isNew, original) {\n this.editForm.detach();\n const parentContainer = parent ? parent.formioContainer : this.container;\n const parentComponent = parent ? parent.formioComponent : this;\n this.dialog.close();\n const path = parentContainer ? this.getComponentsPath(component, parentComponent.component) : '';\n if (!original) {\n original = parent.formioContainer.find((comp) => comp.id === component.id);\n }\n const index = parentContainer ? parentContainer.indexOf(original) : 0;\n if (index !== -1) {\n let submissionData = this.editForm.submission.data;\n submissionData = submissionData.componentJson || submissionData;\n const fieldsToRemoveDoubleQuotes = ['label', 'tooltip'];\n this.replaceDoubleQuotes(submissionData, fieldsToRemoveDoubleQuotes);\n this.hook('beforeSaveComponentSettings', submissionData);\n let comp = null;\n parentComponent.getComponents().forEach((component) => {\n if (component.component.key === original.key) {\n comp = component;\n }\n });\n const originalComp = comp === null || comp === void 0 ? void 0 : comp.component;\n const originalComponentSchema = comp === null || comp === void 0 ? void 0 : comp.schema;\n const isParentSaveChildMethod = this.isParentSaveChildMethod(parent.formioComponent);\n if (parentContainer && !isParentSaveChildMethod) {\n parentContainer[index] = submissionData;\n if (comp) {\n comp.component = submissionData;\n }\n }\n else if (isParentSaveChildMethod) {\n parent.formioComponent.saveChildComponent(submissionData);\n }\n const rebuild = parentComponent.rebuild() || Promise.resolve();\n return rebuild.then(() => {\n const schema = parentContainer ? parentContainer[index] : (comp ? comp.schema : []);\n this.emitSaveComponentEvent(schema, originalComp, parentComponent.schema, path, index, isNew, originalComponentSchema);\n this.emit('change', this.form);\n this.highlightInvalidComponents();\n if (this.isComponentCreated) {\n const component = parent.formioComponent.components[0];\n this.moveComponent(component);\n this.isComponentCreated = false;\n }\n });\n }\n this.highlightInvalidComponents();\n return Promise.resolve();\n }\n emitSaveComponentEvent(schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema) {\n this.emit('saveComponent', schema, originalComp, parentComponentSchema, path, index, isNew, originalComponentSchema);\n }\n attachEditComponentControls(component, parent, isNew, original, ComponentClass) {\n const cancelButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"cancelButton\"]`);\n cancelButtons.forEach((cancelButton) => {\n this.editForm.addEventListener(cancelButton, 'click', (event) => {\n event.preventDefault();\n this.editForm.detach();\n this.emit('cancelComponent', component);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const removeButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"removeButton\"]`);\n removeButtons.forEach((removeButton) => {\n this.editForm.addEventListener(removeButton, 'click', (event) => {\n event.preventDefault();\n // Since we are already removing the component, don't trigger another remove.\n this.saved = true;\n this.editForm.detach();\n this.removeComponent(component, parent, original);\n this.dialog.close();\n this.highlightInvalidComponents();\n });\n });\n const saveButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"saveButton\"]`);\n saveButtons.forEach((saveButton) => {\n this.editForm.addEventListener(saveButton, 'click', (event) => {\n event.preventDefault();\n const errors = this.editForm.validate(this.editForm.data, {\n dirty: true\n });\n if (errors.length) {\n this.editForm.setPristine(false);\n this.editForm.showErrors(errors);\n return false;\n }\n this.saved = true;\n this.saveComponent(component, parent, isNew, original);\n });\n });\n const previewButtons = this.componentEdit.querySelectorAll(`[${this._referenceAttributeName}=\"previewButton\"]`);\n previewButtons.forEach((previewButton) => {\n this.editForm.addEventListener(previewButton, 'click', (event) => {\n event.preventDefault();\n this.showPreview = !this.showPreview;\n this.editForm.detach();\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks,\n }));\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n });\n });\n }\n editComponent(component, parent, isNew, isJsonEdit, original, flags = {}) {\n var _a, _b;\n if (!component.key) {\n return;\n }\n this.saved = false;\n const componentCopy = (0, utils_1.fastCloneDeep)(component);\n let ComponentClass = Components_1.default.components[componentCopy.type];\n const isCustom = ComponentClass === undefined;\n isJsonEdit = isJsonEdit || isCustom;\n ComponentClass = isCustom ? Components_1.default.components.unknown : ComponentClass;\n // Make sure we only have one dialog open at a time.\n if (this.dialog) {\n this.dialog.close();\n this.highlightInvalidComponents();\n }\n // This is the render step.\n const editFormOptions = lodash_1.default.clone(lodash_1.default.get(this, 'options.editForm', {}));\n if (this.editForm) {\n this.editForm.destroy();\n }\n // Allow editForm overrides per component.\n const overrides = lodash_1.default.get(this.options, `editForm.${componentCopy.type}`, {});\n // Pass along the form being edited.\n editFormOptions.editForm = this.form;\n editFormOptions.editComponent = component;\n editFormOptions.flags = flags;\n this.hook('editComponentParentInstance', editFormOptions, parent);\n this.editForm = new Webform_1.default(Object.assign(Object.assign(Object.assign(Object.assign({}, lodash_1.default.omit(this.options, ['hooks', 'builder', 'events', 'attachMode', 'skipInit'])), { language: this.options.language }), editFormOptions), { evalContext: Object.assign(Object.assign({}, ((editFormOptions === null || editFormOptions === void 0 ? void 0 : editFormOptions.evalContext) || ((_a = this.options) === null || _a === void 0 ? void 0 : _a.evalContext) || {})), { buildingForm: this.form }) }));\n this.hook('editFormProperties', parent);\n this.editForm.form = (isJsonEdit && !isCustom) ? {\n components: [\n {\n type: 'textarea',\n as: 'json',\n editor: 'ace',\n weight: 10,\n input: true,\n key: 'componentJson',\n label: 'Component JSON',\n tooltip: 'Edit the JSON for this component.'\n },\n {\n type: 'checkbox',\n key: 'showFullSchema',\n label: 'Full Schema'\n }\n ]\n } : ComponentClass.editForm(lodash_1.default.cloneDeep(overrides));\n const instanceOptions = {\n inFormBuilder: true,\n };\n this.hook('instanceOptionsPreview', instanceOptions);\n const instance = new ComponentClass(componentCopy, instanceOptions);\n const schema = this.hook('builderComponentSchema', component, instance);\n this.editForm.submission = isJsonEdit ? {\n data: {\n componentJson: schema,\n showFullSchema: this.options.showFullJsonSchema\n },\n } : {\n data: instance.component,\n };\n if (this.preview) {\n this.preview.destroy();\n }\n if (!ComponentClass.builderInfo.hasOwnProperty('preview') || ComponentClass.builderInfo.preview) {\n this.preview = new Webform_1.default(lodash_1.default.omit(Object.assign(Object.assign({}, this.options), { preview: true }), [\n 'hooks',\n 'builder',\n 'events',\n 'attachMode',\n 'calculateValue'\n ]));\n this.hook('previewFormSettitngs', schema, isJsonEdit);\n }\n this.showPreview = (_b = ComponentClass.builderInfo.showPreview) !== null && _b !== void 0 ? _b : true;\n this.componentEdit = this.ce('div', { 'class': 'component-edit-container' });\n this.setContent(this.componentEdit, this.renderTemplate('builderEditForm', {\n componentInfo: ComponentClass.builderInfo,\n editForm: this.editForm.render(),\n preview: this.preview ? this.preview.render() : false,\n showPreview: this.showPreview,\n helplinks: this.helplinks\n }));\n this.dialog = this.createModal(this.componentEdit, lodash_1.default.get(this.options, 'dialogAttr', {}));\n // This is the attach step.\n this.editForm.attach(this.componentEdit.querySelector(`[${this._referenceAttributeName}=\"editForm\"]`));\n this.hook('editFormWrapper');\n this.updateComponent(componentCopy);\n this.editForm.on('change', (event) => {\n if (event.changed) {\n if (event.changed.component && event.changed.component.key === 'showFullSchema') {\n const { value } = event.changed;\n this.editForm.submission = {\n data: {\n componentJson: value ? instance.component : component,\n showFullSchema: value\n },\n };\n return;\n }\n // See if this is a manually modified key. Treat custom component keys as manually modified\n if ((event.changed.component && (event.changed.component.key === 'key')) || isJsonEdit) {\n componentCopy.keyModified = true;\n }\n let isComponentLabelChanged = false;\n if (event.changed.instance) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.instance.path);\n }\n else if (event.changed.component) {\n isComponentLabelChanged = ['label', 'title'].includes(event.changed.component.key);\n }\n if (isComponentLabelChanged) {\n // Ensure this component has a key.\n if (isNew) {\n if (!event.data.keyModified) {\n this.editForm.everyComponent(component => {\n if (component.key === 'key' && component.parent.component.key === 'tabs') {\n component.setValue(this.updateComponentKey(event.data));\n return false;\n }\n });\n }\n if (this.form) {\n let formComponents = this.findNamespaceRoot(parent.formioComponent);\n // excluding component which key uniqueness is to be checked to prevent the comparing of the same keys\n formComponents = formComponents.filter(comp => editFormOptions.editComponent.id !== comp.id);\n // Set a unique key for this component.\n builder_1.default.uniquify(formComponents, event.data);\n }\n }\n }\n // If the edit form has any nested form inside, we get a partial data (nested form's data) in the\n // event.data property\n let editFormData;\n if (event.changed.instance && event.changed.instance.root && event.changed.instance.root.id !== this.editForm.id) {\n editFormData = this.editForm.data;\n }\n // Update the component.\n this.updateComponent(event.data.componentJson || editFormData || event.data, event.changed);\n }\n });\n this.attachEditComponentControls(component, parent, isNew, original, ComponentClass);\n const dialogClose = () => {\n this.editForm.destroy(true);\n if (this.preview) {\n this.preview.destroy(true);\n this.preview = null;\n }\n if (isNew && !this.saved) {\n this.removeComponent(component, parent, original);\n this.highlightInvalidComponents();\n }\n // Clean up.\n this.removeEventListener(this.dialog, 'close', dialogClose);\n this.dialog = null;\n };\n this.addEventListener(this.dialog, 'close', dialogClose);\n // Called when we edit a component.\n this.emit('editComponent', component);\n }\n updateComponentKey(data) {\n return lodash_1.default.camelCase(data.title ||\n data.label ||\n data.placeholder ||\n data.type).replace(/^[0-9]*/, '');\n }\n moveComponent(component) {\n var _a;\n if (this.selectedComponent) {\n const prevSelected = this.selectedComponent;\n (_a = prevSelected.element) === null || _a === void 0 ? void 0 : _a.classList.remove('builder-component-selected');\n this.removeEventListener(document, 'keydown');\n }\n component.element.focus();\n component.element.classList.add('builder-component-selected');\n this.selectedComponent = component;\n this.addEventListener(document, 'keydown', this.moveHandler.bind(this));\n }\n updateComponentPlacement(direction) {\n const component = this.selectedComponent;\n let index, info;\n const step = direction ? -1 : 1;\n if (component) {\n const element = component.element;\n const sibling = direction ? element.previousElementSibling : element.nextElementSibling;\n const source = element.parentNode;\n const containerLength = source.formioContainer.length;\n if (containerLength && containerLength <= 1) {\n return;\n }\n if (source.formioContainer) {\n index = lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key });\n if (index !== -1) {\n info = source.formioContainer.splice(lodash_1.default.findIndex(source.formioContainer, { key: element.formioComponent.component.key }), 1);\n info = info[0];\n source.removeChild(element);\n }\n }\n const len = source.formioComponent.components.length;\n index = (index === -1) ? 0 : index + step;\n if (index === -1) {\n source.formioContainer.push(info);\n source.appendChild(element);\n }\n else if (index === len) {\n const key = source.formioContainer[0].key;\n index = lodash_1.default.findIndex(source.formioComponent.components, { key: key });\n const firstElement = source.formioComponent.components[index].element;\n source.formioContainer.splice(0, 0, info);\n source.insertBefore(element, firstElement);\n }\n else if (index !== -1) {\n source.formioContainer.splice(index, 0, info);\n direction\n ? source.insertBefore(element, sibling)\n : source.insertBefore(element, sibling.nextElementSibling);\n }\n element.focus();\n }\n }\n stopMoving(comp) {\n const parent = comp.element.parentNode;\n this.removeEventListener(document, 'keydown');\n parent.formioComponent.rebuild();\n this.selectedComponent = null;\n }\n addNewComponent(element) {\n var _a;\n const source = document.querySelector('.formio-builder-form');\n const key = element.getAttribute('data-key');\n const group = element.getAttribute('data-group');\n const isNew = true;\n let info;\n if (key && group) {\n info = this.getComponentInfo(key, group);\n }\n if (isNew && !this.options.noNewEdit && !info.noNewEdit) {\n builder_1.default.uniquify(this.findNamespaceRoot(source.formioComponent), info);\n this.editComponent(info, source, isNew, null, null);\n }\n const firstComponent = (_a = source.formioComponent.components[0]) === null || _a === void 0 ? void 0 : _a.element;\n if (firstComponent) {\n source.formioContainer.splice(0, 0, info);\n }\n else {\n source.formioContainer.push(info);\n }\n source.formioComponent.rebuild().then(() => {\n this.isComponentCreated = true;\n });\n }\n /**\n * Creates copy of component schema and stores it under sessionStorage.\n * @param {Component} component\n * @return {*}\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\n * @return {*}\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?");
5568
5578
 
5569
5579
  /***/ }),
5570
5580
 
@@ -5575,7 +5585,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5575
5585
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5576
5586
 
5577
5587
  "use strict";
5578
- 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 Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass Wizard extends Webform_1.default {\n /**\n * Constructor for wizard based forms\n * @param element Dom element to place this wizard.\n * @param {Object} options Options object, supported options are:\n * - breadcrumbSettings.clickable: true (default) determines if the breadcrumb bar is clickable or not\n * - buttonSettings.show*(Previous, Next, Cancel): true (default) determines if the button is shown or not\n * - allowPrevious: false (default) determines if the breadcrumb bar is clickable or not for visited tabs\n */\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 options.display = 'wizard';\n super(element, options);\n this.pages = [];\n this.prefixComps = [];\n this.suffixComps = [];\n this.components = [];\n this.originalComponents = [];\n this.page = 0;\n this.currentPanel = null;\n this.currentPanels = null;\n this.currentNextPage = 0;\n this._seenPages = [0];\n this.subWizards = [];\n this.allPages = [];\n this.lastPromise = Promise.resolve();\n this.enabledIndex = 0;\n this.editMode = false;\n this.originalOptions = lodash_1.default.cloneDeep(this.options);\n }\n isLastPage() {\n const next = this.getNextPage();\n if (lodash_1.default.isNumber(next)) {\n return next === -1;\n }\n return lodash_1.default.isNull(next);\n }\n getPages(args = {}) {\n const { all = false } = args;\n const pages = this.hasExtraPages ? this.components : this.pages;\n const filteredPages = pages\n .filter(all ? lodash_1.default.identity : (p, index) => this._seenPages.includes(index));\n return filteredPages;\n }\n get hasExtraPages() {\n return !lodash_1.default.isEmpty(this.subWizards);\n }\n get data() {\n return super.data;\n }\n get localData() {\n var _a, _b;\n return ((_b = (_a = this.pages[this.page]) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.submission.data) || this.submission.data;\n }\n checkConditions(data, flags, row) {\n const visible = super.checkConditions(data, flags, row);\n this.establishPages(data);\n return visible;\n }\n set data(value) {\n this._data = value;\n lodash_1.default.each(this.getPages({ all: true }), (component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.submitting\n ? this.getPages({ all: this.isLastPage() })\n : super.getComponents();\n }\n resetValue() {\n this.getPages({ all: true }).forEach((page) => page.resetValue());\n this.setPristine(true);\n }\n init() {\n var _a, _b, _c;\n // Check for and initlize button settings object\n this.options.buttonSettings = lodash_1.default.defaults(this.options.buttonSettings, {\n showPrevious: true,\n showNext: true,\n showSubmit: true,\n showCancel: !this.options.readOnly\n });\n if (!this.isSecondInit) {\n this.isClickableDefined = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.breadcrumbSettings) === null || _b === void 0 ? void 0 : _b.hasOwnProperty('clickable');\n this.isSecondInit = true;\n }\n this.options.breadcrumbSettings = lodash_1.default.defaults(this.options.breadcrumbSettings, {\n clickable: true\n });\n this.options.allowPrevious = this.options.allowPrevious || false;\n this.page = 0;\n const onReady = super.init();\n this.setComponentSchema();\n if ((_c = this.pages) === null || _c === void 0 ? void 0 : _c[this.page]) {\n this.component = this.pages[this.page].component;\n }\n this.on('subWizardsUpdated', (subForm) => {\n const subWizard = this.subWizards.find(subWizard => { var _a; return (subForm === null || subForm === void 0 ? void 0 : subForm.id) && ((_a = subWizard.subForm) === null || _a === void 0 ? void 0 : _a.id) === (subForm === null || subForm === void 0 ? void 0 : subForm.id); });\n if (this.subWizards.length && subWizard) {\n subWizard.subForm.setValue(subForm._submission, {}, true);\n this.establishPages();\n this.redraw();\n }\n });\n return onReady;\n }\n get wizardKey() {\n return `wizard-${this.id}`;\n }\n get wizard() {\n return this.form;\n }\n set wizard(form) {\n this.setForm(form);\n }\n get buttons() {\n const buttons = {};\n [\n { name: 'cancel', method: 'cancel' },\n { name: 'previous', method: 'prevPage' },\n { name: 'next', method: 'nextPage' },\n { name: 'submit', method: 'submit' }\n ].forEach((button) => {\n if (this.hasButton(button.name)) {\n buttons[button.name] = button;\n }\n });\n return buttons;\n }\n get buttonOrder() {\n var _a, _b, _c;\n const defaultButtonOrder = [\n 'cancel',\n 'previous',\n 'next',\n 'submit'\n ];\n return (_c = (_b = (_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.wizardButtonOrder) === null || _b === void 0 ? void 0 : _b.toLowerCase().split(', ')) !== null && _c !== void 0 ? _c : defaultButtonOrder;\n }\n get renderContext() {\n var _a, _b;\n return {\n disableWizardSubmit: this.form.disableWizardSubmit,\n wizardKey: this.wizardKey,\n isBreadcrumbClickable: this.isBreadcrumbClickable(),\n isSubForm: !!this.parent && !((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.type) === 'wizard',\n panels: this.allPages.length ? this.allPages.map(page => page.component) : this.pages.map(page => page.component),\n buttons: this.buttons,\n currentPage: this.page,\n buttonOrder: this.buttonOrder,\n };\n }\n prepareNavigationSettings(ctx) {\n const currentPanel = this.currentPanel;\n if (currentPanel && currentPanel.buttonSettings) {\n Object.keys(currentPanel.buttonSettings).forEach(() => {\n Object.keys(ctx.buttons).forEach(key => {\n if (typeof currentPanel.buttonSettings[key] !== 'undefined' && !currentPanel.buttonSettings[key] || ctx.isSubForm) {\n ctx.buttons[key] = null;\n }\n });\n });\n }\n return this.renderTemplate('wizardNav', ctx);\n }\n prepareHeaderSettings(ctx, headerType) {\n var _a;\n const shouldHideBreadcrumbs = ((_a = this.currentPanel) === null || _a === void 0 ? void 0 : _a.breadcrumb) === 'none' ||\n lodash_1.default.get(this.form, 'settings.wizardBreadcrumbsType', '') === 'none';\n if (shouldHideBreadcrumbs || ctx.isSubForm) {\n return null;\n }\n return this.renderTemplate(headerType, ctx);\n }\n render() {\n const ctx = this.renderContext;\n if (this.component.key) {\n ctx.panels.map(panel => {\n if (panel.key === this.component.key) {\n this.currentPanel = panel;\n ctx.wizardPageTooltip = this.getFormattedTooltip(panel.tooltip);\n }\n });\n }\n const wizardNav = this.prepareNavigationSettings(ctx);\n const wizardHeaderType = `wizardHeader${lodash_1.default.get(this.form, 'settings.wizardHeaderType', '')}`;\n const wizardHeaderLocation = lodash_1.default.get(this.form, 'settings.wizardHeaderLocation', 'left');\n const wizardHeader = this.prepareHeaderSettings(ctx, wizardHeaderType);\n return this.renderTemplate('wizard', Object.assign(Object.assign({}, ctx), { className: super.getClassName(), wizardHeader,\n wizardHeaderType,\n wizardHeaderLocation,\n wizardNav, components: this.renderComponents([\n ...this.prefixComps,\n ...this.currentPage.components,\n ...this.suffixComps\n ]) }), this.builderMode ? 'builder' : 'form');\n }\n redrawNavigation() {\n if (this.element) {\n let navElement = this.element.querySelector(`#${this.wizardKey}-nav`);\n if (navElement) {\n this.detachNav();\n navElement.outerHTML = this.renderTemplate('wizardNav', this.renderContext);\n navElement = this.element.querySelector(`#${this.wizardKey}-nav`);\n this.loadRefs(navElement, {\n [`${this.wizardKey}-cancel`]: 'single',\n [`${this.wizardKey}-previous`]: 'single',\n [`${this.wizardKey}-next`]: 'single',\n [`${this.wizardKey}-submit`]: 'single',\n });\n this.attachNav();\n }\n }\n }\n redrawHeader() {\n if (this.element) {\n let headerElement = this.element.querySelector(`#${this.wizardKey}-header`);\n if (headerElement) {\n this.detachHeader();\n headerElement.outerHTML = this.renderTemplate(`wizardHeader${lodash_1.default.get(this.form, 'settings.wizardHeaderType', '')}`, this.renderContext);\n headerElement = this.element.querySelector(`#${this.wizardKey}-header`);\n this.loadRefs(headerElement, {\n [`${this.wizardKey}-link`]: 'multiple',\n [`${this.wizardKey}-tooltip`]: 'multiple'\n });\n this.attachHeader();\n }\n }\n }\n attach(element) {\n var _a;\n this.element = element;\n this.loadRefs(element, {\n [this.wizardKey]: 'single',\n [`${this.wizardKey}-header`]: 'single',\n [`${this.wizardKey}-cancel`]: 'single',\n [`${this.wizardKey}-previous`]: 'single',\n [`${this.wizardKey}-next`]: 'single',\n [`${this.wizardKey}-submit`]: 'single',\n [`${this.wizardKey}-link`]: 'multiple',\n [`${this.wizardKey}-tooltip`]: 'multiple'\n });\n if ((this.options.readOnly || this.editMode) && !this.enabledIndex) {\n this.enabledIndex = ((_a = this.pages) === null || _a === void 0 ? void 0 : _a.length) - 1;\n }\n this.hook('attachWebform', element, this);\n const promises = this.attachComponents(this.refs[this.wizardKey], [\n ...this.prefixComps,\n ...this.currentPage.components,\n ...this.suffixComps,\n ]);\n this.attachNav();\n this.attachHeader();\n return promises.then(() => {\n this.emit('render', { component: this.currentPage, page: this.page });\n if (this.component.scrollToTop) {\n this.scrollPageToTop();\n }\n });\n }\n scrollPageToTop() {\n var _a;\n const pageTop = (_a = this.refs[`${this.wizardKey}-header`]) !== null && _a !== void 0 ? _a : this.refs[this.wizardKey];\n if (!pageTop) {\n return;\n }\n if ('scrollIntoView' in pageTop) {\n pageTop.scrollIntoView(true);\n }\n else {\n this.scrollIntoView(pageTop);\n }\n }\n isBreadcrumbClickable() {\n let currentPage = null;\n this.pages.map(page => {\n if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {\n currentPage = page;\n }\n });\n return this.isClickableDefined ? this.options.breadcrumbSettings.clickable : lodash_1.default.get(currentPage, 'component.breadcrumbClickable', true);\n }\n isAllowPrevious() {\n let currentPage = null;\n this.pages.map(page => {\n if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {\n currentPage = page;\n }\n });\n return lodash_1.default.get(currentPage.component, 'allowPrevious', this.options.allowPrevious);\n }\n handleNaviageteOnEnter(event) {\n if (event.keyCode === 13) {\n const clickEvent = new CustomEvent('click');\n const buttonElement = this.refs[`${this.wizardKey}-${this.buttons.next.name}`];\n if (buttonElement) {\n buttonElement.dispatchEvent(clickEvent);\n }\n }\n }\n handleSaveOnEnter(event) {\n if (event.keyCode === 13) {\n const clickEvent = new CustomEvent('click');\n const buttonElement = this.refs[`${this.wizardKey}-${this.buttons.submit.name}`];\n if (buttonElement) {\n buttonElement.dispatchEvent(clickEvent);\n }\n }\n }\n attachNav() {\n if (this.component.navigateOnEnter) {\n this.addEventListener(document, 'keyup', this.handleNaviageteOnEnter.bind(this));\n }\n if (this.component.saveOnEnter) {\n this.addEventListener(document, 'keyup', this.handleSaveOnEnter.bind(this));\n }\n lodash_1.default.each(this.buttons, (button) => {\n const buttonElement = this.refs[`${this.wizardKey}-${button.name}`];\n this.addEventListener(buttonElement, 'click', (event) => {\n event.preventDefault();\n // Disable the button until done.\n buttonElement.setAttribute('disabled', 'disabled');\n this.setLoading(buttonElement, true);\n // Call the button method, then re-enable the button.\n this[button.method]().then(() => {\n buttonElement.removeAttribute('disabled');\n this.setLoading(buttonElement, false);\n }).catch(() => {\n buttonElement.removeAttribute('disabled');\n this.setLoading(buttonElement, false);\n });\n });\n });\n }\n emitWizardPageSelected(index) {\n this.emit('wizardPageSelected', this.pages[index], index);\n }\n attachHeader() {\n var _a;\n const isAllowPrevious = this.isAllowPrevious();\n this.attachTooltips(this.refs[`${this.wizardKey}-tooltip`], this.currentPanel.tooltip);\n if (this.isBreadcrumbClickable() || isAllowPrevious) {\n (_a = this.refs[`${this.wizardKey}-link`]) === null || _a === void 0 ? void 0 : _a.forEach((link, index) => {\n if (!isAllowPrevious || index <= this.enabledIndex) {\n this.addEventListener(link, 'click', (event) => {\n this.emit('wizardNavigationClicked', this.pages[index]);\n event.preventDefault();\n return this.setPage(index).then(() => {\n this.emitWizardPageSelected(index);\n });\n });\n }\n });\n }\n }\n detachNav() {\n if (this.component.navigateOnEnter) {\n this.removeEventListener(document, 'keyup', this.handleNaviageteOnEnter.bind(this));\n }\n if (this.component.saveOnEnter) {\n this.removeEventListener(document, 'keyup', this.handleSaveOnEnter.bind(this));\n }\n lodash_1.default.each(this.buttons, (button) => {\n this.removeEventListener(this.refs[`${this.wizardKey}-${button.name}`], 'click');\n });\n }\n detachHeader() {\n if (this.refs[`${this.wizardKey}-link`]) {\n this.refs[`${this.wizardKey}-link`].forEach((link) => {\n this.removeEventListener(link, 'click');\n });\n }\n }\n transformPages() {\n const allComponents = [];\n const components = this.getSortedComponents(this);\n let defferedComponents = [];\n this.allPages = [];\n // Get all components including all nested components and line up in the correct order\n const getAllComponents = (nestedComp, compsArr, pushAllowed = true) => {\n const nestedPages = [];\n const dataArrayComponents = ['datagrid', 'editgrid', 'dynamicWizard'];\n const currentComponents = (nestedComp === null || nestedComp === void 0 ? void 0 : nestedComp.subForm) ? this.getSortedComponents(nestedComp.subForm) : (nestedComp === null || nestedComp === void 0 ? void 0 : nestedComp.components) || [];\n const visibleComponents = currentComponents.filter(comp => comp._visible);\n const filteredComponents = visibleComponents.filter(comp => !dataArrayComponents.includes(comp.component.type) && (comp.type !== 'form' || comp.isNestedWizard));\n const additionalComponents = currentComponents.filter(comp => { var _a; return ((_a = comp.subForm) === null || _a === void 0 ? void 0 : _a._form.display) !== 'wizard'; });\n let hasNested = false;\n (0, utils_1.eachComponent)(filteredComponents, (comp) => {\n if (comp && comp.component) {\n if (comp.component.type === 'panel' && (comp === null || comp === void 0 ? void 0 : comp.parent.wizard) && !getAllComponents(comp, compsArr, false)) {\n if (pushAllowed) {\n this.setRootPanelId(comp);\n nestedPages.push(comp);\n }\n hasNested = true;\n }\n if (comp.isNestedWizard && comp.subForm) {\n const hasNestedForm = getAllComponents(comp, nestedPages, pushAllowed);\n if (!hasNested) {\n hasNested = hasNestedForm;\n }\n }\n }\n }, true);\n if (nestedComp.component.type === 'panel') {\n if (!hasNested && pushAllowed) {\n this.setRootPanelId(nestedComp);\n compsArr.push(nestedComp);\n }\n if (hasNested && additionalComponents.length) {\n const newComp = lodash_1.default.clone(nestedComp);\n newComp.components = additionalComponents;\n this.setRootPanelId(newComp);\n defferedComponents.push(newComp);\n }\n }\n if (pushAllowed) {\n compsArr.push(...defferedComponents, ...nestedPages);\n defferedComponents = [];\n }\n return hasNested;\n };\n components.forEach((component) => {\n if (component.visible) {\n getAllComponents(component, allComponents);\n }\n }, []);\n // recalculate pages only for root wizards, including the situation when the wizard is in a wrapper\n if (this.localRoot && this.id === this.localRoot.id) {\n allComponents.forEach((comp, index) => {\n comp.eachComponent((component) => {\n component.page = index;\n });\n });\n }\n this.allPages = allComponents;\n }\n getSortedComponents({ components, originalComponents }) {\n const currentComponents = [];\n const currentPages = [];\n if (components && components.length) {\n components.map(page => {\n if (page.component.type === 'panel') {\n currentPages[page.component.key || page.component.title] = page;\n }\n });\n }\n originalComponents === null || originalComponents === void 0 ? void 0 : originalComponents.forEach((item) => {\n if (!item.key) {\n item.key = item.title;\n }\n if (currentPages[item.key]) {\n currentComponents.push(currentPages[item.key]);\n }\n });\n return currentComponents;\n }\n findRootPanel(component) {\n var _a;\n return ((_a = component.parent) === null || _a === void 0 ? void 0 : _a.parent) ? this.findRootPanel(component.parent) : component;\n }\n setRootPanelId(component) {\n var _a;\n if (component.rootPanelId && component.rootPanelId !== component.id) {\n return;\n }\n const parent = ((_a = component.parent) === null || _a === void 0 ? void 0 : _a.parent) ? this.findRootPanel(component.parent) : component;\n component.rootPanelId = parent.id;\n }\n establishPages(data = this.data) {\n this.pages = [];\n this.prefixComps = [];\n this.suffixComps = [];\n const visible = [];\n const currentPages = {};\n const pageOptions = Object.assign(Object.assign({}, (lodash_1.default.clone(this.options))), (this.parent ? { root: this } : {}));\n if (this.components && this.components.length) {\n this.components.forEach(page => {\n if (page.component.type === 'panel') {\n currentPages[page.component.key || page.component.title] = page;\n }\n });\n }\n if (this.originalComponents) {\n this.originalComponents.forEach((item) => {\n if (item.type === 'panel') {\n if (!item.key) {\n item.key = item.title;\n }\n let page = currentPages[item.key];\n const forceShow = this.shouldForceShow(item);\n const forceHide = this.shouldForceHide(item);\n let isVisible = !page\n ? (0, utils_1.checkCondition)(item, data, data, this.component, this) && !item.hidden\n : page.visible;\n if (forceShow) {\n isVisible = true;\n }\n else if (forceHide) {\n isVisible = false;\n }\n if (isVisible) {\n visible.push(item);\n if (page) {\n this.pages.push(page);\n }\n }\n if (!page && isVisible) {\n page = this.createComponent(item, pageOptions);\n page.visible = isVisible;\n this.pages.push(page);\n page.eachComponent((component) => {\n component.page = (this.pages.length - 1);\n });\n }\n }\n else if (item.type !== 'button') {\n if (!this.pages.length) {\n this.prefixComps.push(this.createComponent(item, pageOptions));\n }\n else {\n this.suffixComps.push(this.createComponent(item, pageOptions));\n }\n }\n });\n }\n if (this.pages.length) {\n this.emit('pagesChanged');\n }\n this.transformPages();\n if (this.allPages && this.allPages.length) {\n this.updatePages();\n }\n return visible;\n }\n updatePages() {\n this.pages = this.allPages;\n }\n addComponents() {\n this.establishPages();\n }\n setPage(num) {\n if (num === this.page) {\n return Promise.resolve();\n }\n if (num >= 0 && num < this.pages.length) {\n this.page = num;\n this.pageFieldLogic(num);\n this.getNextPage();\n let parentNum = num;\n if (this.hasExtraPages) {\n const pageFromPages = this.pages[num];\n const pageFromComponents = this.components[num];\n if (!pageFromComponents || (pageFromPages === null || pageFromPages === void 0 ? void 0 : pageFromPages.id) !== pageFromComponents.id) {\n parentNum = this.components.findIndex(comp => {\n var _a, _b;\n return comp.id === ((_b = (_a = this.pages) === null || _a === void 0 ? void 0 : _a[parentNum]) === null || _b === void 0 ? void 0 : _b.rootPanelId);\n });\n }\n }\n if (!this._seenPages.includes(parentNum)) {\n this._seenPages = this._seenPages.concat(parentNum);\n }\n this.redraw().then(() => {\n this.checkData(this.submission.data);\n this.validateCurrentPage();\n });\n return Promise.resolve();\n }\n else if (!this.pages.length) {\n this.redraw();\n return Promise.resolve();\n }\n return Promise.reject('Page not found');\n }\n pageFieldLogic(page) {\n var _a;\n if ((_a = this.pages) === null || _a === void 0 ? void 0 : _a[page]) {\n // Handle field logic on pages.\n this.component = this.pages[page].component;\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n this.fieldLogic(this.data);\n // If disabled changed, be sure to distribute the setting.\n this.disabled = this.shouldDisabled;\n }\n }\n get currentPage() {\n return (this.pages && (this.pages.length >= this.page)) ? this.pages[this.page] : { components: [] };\n }\n getNextPage() {\n var _a;\n if ((_a = this.pages) === null || _a === void 0 ? void 0 : _a[this.page]) {\n const data = this.submission.data;\n const form = this.pages[this.page].component;\n // Check conditional nextPage\n if (form) {\n const page = this.pages.length > (this.page + 1) && !this.showAllErrors ? this.page + 1 : -1;\n if (form.nextPage) {\n const next = this.evaluate(form.nextPage, {\n next: page,\n data,\n page,\n form\n }, 'next');\n if (next === null) {\n this.currentNextPage = null;\n return null;\n }\n const pageNum = parseInt(next, 10);\n if (!isNaN(parseInt(pageNum, 10)) && isFinite(pageNum)) {\n this.currentNextPage = pageNum;\n return pageNum;\n }\n this.currentNextPage = this.getPageIndexByKey(next);\n return this.currentNextPage;\n }\n this.currentNextPage = page;\n return page;\n }\n this.currentNextPage = null;\n }\n return null;\n }\n getPreviousPage() {\n return this.page - 1;\n }\n beforeSubmit() {\n const pages = this.getPages();\n return Promise.all(pages.map((page) => {\n page.options.beforeSubmit = true;\n return page.beforeSubmit();\n }));\n }\n beforePage(next) {\n return new Promise((resolve, reject) => {\n this.hook(next ? 'beforeNext' : 'beforePrev', this.currentPage, this.submission, (err) => {\n if (err) {\n this.showErrors(err, true);\n reject(err);\n }\n const form = this.currentPage;\n if (form) {\n form.beforePage(next).then(resolve).catch(reject);\n }\n else {\n resolve();\n }\n });\n });\n }\n emitNextPage() {\n this.emit('nextPage', { page: this.page, submission: this.submission });\n }\n nextPage() {\n // Read-only forms should not worry about validation before going to next page, nor should they submit.\n if (this.options.readOnly) {\n return this.beforePage(true).then(() => {\n return this.setPage(this.getNextPage()).then(() => {\n this.emitNextPage();\n });\n });\n }\n // Validate the form, before go to the next page\n const errors = this.validateCurrentPage({ dirty: true });\n if (errors.length === 0) {\n this.checkData(this.submission.data);\n return this.beforePage(true).then(() => {\n return this.setPage(this.getNextPage()).then(() => {\n if (!(this.options.readOnly || this.editMode) && this.enabledIndex < this.page) {\n this.enabledIndex = this.page;\n this.redraw();\n }\n this.emitNextPage();\n });\n });\n }\n else {\n this.currentPage.components.forEach((comp) => comp.setPristine(false));\n this.scrollIntoView(this.element);\n return Promise.reject(this.showErrors(errors, true));\n }\n }\n validateCurrentPage(flags = {}) {\n var _a;\n // Accessing the parent ensures the right instance (whether it's the parent Wizard or a nested Wizard) performs its validation\n return (_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.parent.validateComponents(this.currentPage.component.components, this.currentPage.parent.data, flags);\n }\n emitPrevPage() {\n this.emit('prevPage', { page: this.page, submission: this.submission });\n }\n prevPage() {\n return this.beforePage().then(() => {\n return this.setPage(this.getPreviousPage()).then(() => {\n this.emitPrevPage();\n });\n });\n }\n cancel(noconfirm) {\n if (this.options.readOnly) {\n return Promise.resolve();\n }\n if (super.cancel(noconfirm)) {\n this.setPristine(true);\n return this.setPage(0).then(() => {\n if (this.enabledIndex) {\n this.enabledIndex = 0;\n }\n this.onChange({ resetValue: true });\n this.redraw();\n return this.page;\n });\n }\n return Promise.resolve();\n }\n getPageIndexByKey(key) {\n let pageIndex = this.page;\n this.pages.forEach((page, index) => {\n if (page.component.key === key) {\n pageIndex = index;\n return false;\n }\n });\n return pageIndex;\n }\n get schema() {\n return this.wizard;\n }\n setComponentSchema() {\n const pageKeys = {};\n this.originalComponents = [];\n this.component.components.map((item) => {\n if (item.type === 'panel') {\n item.key = (0, utils_1.uniqueKey)(pageKeys, (item.key || 'panel'));\n pageKeys[item.key] = true;\n if (this.wizard.full) {\n this.options.show = this.options.show || {};\n this.options.show[item.key] = true;\n }\n else if (this.wizard.hasOwnProperty('full') && !lodash_1.default.isEqual(this.originalOptions.show, this.options.show)) {\n this.options.show = Object.assign({}, (this.originalOptions.show || {}));\n }\n }\n this.originalComponents.push(lodash_1.default.clone(item));\n });\n if (!Object.keys(pageKeys).length) {\n const newPage = {\n type: 'panel',\n title: 'Page 1',\n label: 'Page 1',\n key: 'page1',\n components: this.component.components\n };\n this.component.components = [newPage];\n this.originalComponents.push(lodash_1.default.clone(newPage));\n }\n }\n setForm(form, flags) {\n if (!form) {\n return;\n }\n return super.setForm(form, flags);\n }\n onSetForm(clonedForm, initialForm) {\n this.component.components = (this.parent ? initialForm.components : clonedForm.components) || [];\n this.setComponentSchema();\n }\n setEditMode(submission) {\n if (!this.editMode && submission._id && !this.options.readOnly) {\n this.editMode = true;\n this.redraw();\n }\n }\n setValue(submission, flags = {}, ignoreEstablishment) {\n const changed = this.getPages({ all: true }).reduce((changed, page) => {\n return this.setNestedValue(page, submission.data, flags, changed) || changed;\n }, false);\n this.mergeData(this.data, submission.data);\n if (changed) {\n this.pageFieldLogic(this.page);\n }\n submission.data = this.data;\n this._submission = submission;\n if (!ignoreEstablishment) {\n this.establishPages(submission.data);\n }\n this.setEditMode(submission);\n return changed;\n }\n isClickable(page, index) {\n return this.page !== index && (0, utils_1.firstNonNil)([\n lodash_1.default.get(page, 'breadcrumbClickable'),\n this.options.breadcrumbSettings.clickable\n ]);\n }\n hasButton(name, nextPage = this.getNextPage()) {\n // get page options with global options as default values\n const { previous = this.options.buttonSettings.showPrevious, cancel = this.options.buttonSettings.showCancel, submit = this.options.buttonSettings.showSubmit, next = this.options.buttonSettings.showNext } = lodash_1.default.get(this.currentPage, 'component.buttonSettings', {});\n switch (name) {\n case 'previous':\n return previous && (this.getPreviousPage() > -1);\n case 'next':\n return next && (nextPage !== null) && (nextPage !== -1);\n case 'cancel':\n return cancel && !this.options.readOnly;\n case 'submit':\n return submit && !this.options.readOnly && ((nextPage === null) || (this.page === (this.pages.length - 1)));\n default:\n return true;\n }\n }\n pageId(page) {\n if (page.key) {\n // Some panels have the same key....\n return `${page.key}-${page.title}`;\n }\n else if (page.components &&\n page.components.length > 0) {\n return this.pageId(page.components[0]);\n }\n else {\n return page.title;\n }\n }\n onChange(flags, changed, modified, changes) {\n var _a, _b;\n super.onChange(flags, changed, modified, changes);\n const errors = this.validate(this.localData, { dirty: false });\n if (this.alert) {\n this.showErrors(errors, true, true);\n }\n // If the pages change, need to redraw the header.\n let currentPanels;\n let panels;\n const currentNextPage = this.currentNextPage;\n if (this.hasExtraPages) {\n currentPanels = this.pages.map(page => page.component.key);\n this.establishPages();\n panels = this.pages.map(page => page.component.key);\n }\n else {\n currentPanels = this.currentPanels || this.pages.map(page => page.component.key);\n panels = this.establishPages().map(panel => panel.key);\n this.currentPanels = panels;\n if (((_a = this.currentPanel) === null || _a === void 0 ? void 0 : _a.key) && ((_b = this.currentPanels) === null || _b === void 0 ? void 0 : _b.length)) {\n this.setPage(this.currentPanels.findIndex(panel => panel === this.currentPanel.key));\n }\n }\n if (!lodash_1.default.isEqual(panels, currentPanels) || (flags && flags.fromSubmission)) {\n this.redrawHeader();\n }\n // If the next page changes, then make sure to redraw navigation.\n if (currentNextPage !== this.getNextPage()) {\n this.redrawNavigation();\n }\n if (this.options.readOnly && (this.prefixComps.length || this.suffixComps.length)) {\n this.redraw();\n }\n }\n redraw() {\n var _a, _b;\n if ((_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.modalEdit) {\n return this.parent.redraw();\n }\n return super.redraw();\n }\n rebuild() {\n const currentPage = this.page;\n const setCurrentPage = () => this.setPage(currentPage);\n return super.rebuild().then(setCurrentPage);\n }\n checkValidity(data, dirty, row, currentPageOnly, childErrors = []) {\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n const components = !currentPageOnly || this.isLastPage()\n ? this.getComponents()\n : this.currentPage.components;\n return components.reduce((check, comp) => comp.checkValidity(data, dirty, row, childErrors) && check, true);\n }\n get errors() {\n if (!this.isLastPage()) {\n return this.currentPage.errors;\n }\n return super.errors;\n }\n focusOnComponent(key) {\n const component = this.getComponent(key);\n if (component) {\n let topPanel = component.parent;\n while (!(topPanel.parent instanceof Wizard)) {\n topPanel = topPanel.parent;\n }\n const pageIndex = this.pages.findIndex(page => page === topPanel);\n if (pageIndex >= 0) {\n const page = this.pages[pageIndex];\n if (page && page !== this.currentPage) {\n return this.setPage(pageIndex).then(() => {\n this.showErrors(this.validate(this.localData, { dirty: true }));\n super.focusOnComponent(key);\n });\n }\n }\n }\n return super.focusOnComponent(key);\n }\n}\nexports[\"default\"] = Wizard;\nWizard.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWizard.setApiUrl = Formio_1.Formio.setApiUrl;\nWizard.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Wizard.js?");
5588
+ 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 Webform_1 = __importDefault(__webpack_require__(/*! ./Webform */ \"./lib/cjs/Webform.js\"));\nconst Formio_1 = __webpack_require__(/*! ./Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ./utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass Wizard extends Webform_1.default {\n /**\n * Constructor for wizard based forms\n * @param element Dom element to place this wizard.\n * @param {Object} options Options object, supported options are:\n * - breadcrumbSettings.clickable: true (default) determines if the breadcrumb bar is clickable or not\n * - buttonSettings.show*(Previous, Next, Cancel): true (default) determines if the button is shown or not\n * - allowPrevious: false (default) determines if the breadcrumb bar is clickable or not for visited tabs\n */\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 options.display = 'wizard';\n super(element, options);\n this.pages = [];\n this.prefixComps = [];\n this.suffixComps = [];\n this.components = [];\n this.originalComponents = [];\n this.page = 0;\n this.currentPanel = null;\n this.currentPanels = null;\n this.currentNextPage = 0;\n this._seenPages = [0];\n this.subWizards = [];\n this.allPages = [];\n this.lastPromise = Promise.resolve();\n this.enabledIndex = 0;\n this.editMode = false;\n this.originalOptions = lodash_1.default.cloneDeep(this.options);\n }\n isLastPage() {\n const next = this.getNextPage();\n if (lodash_1.default.isNumber(next)) {\n return next === -1;\n }\n return lodash_1.default.isNull(next);\n }\n getPages(args = {}) {\n const { all = false } = args;\n const pages = this.hasExtraPages ? this.components : this.pages;\n const filteredPages = pages\n .filter(all ? lodash_1.default.identity : (p, index) => this._seenPages.includes(index));\n return filteredPages;\n }\n get hasExtraPages() {\n return !lodash_1.default.isEmpty(this.subWizards);\n }\n get data() {\n return super.data;\n }\n get localData() {\n var _a, _b;\n return ((_b = (_a = this.pages[this.page]) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.submission.data) || this.submission.data;\n }\n checkConditions(data, flags, row) {\n const visible = super.checkConditions(data, flags, row);\n this.establishPages(data);\n return visible;\n }\n set data(value) {\n this._data = value;\n lodash_1.default.each(this.getPages({ all: true }), (component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.submitting\n ? this.getPages({ all: this.isLastPage() })\n : super.getComponents();\n }\n resetValue() {\n this.getPages({ all: true }).forEach((page) => page.resetValue());\n this.setPristine(true);\n }\n init() {\n var _a, _b, _c;\n // Check for and initlize button settings object\n this.options.buttonSettings = lodash_1.default.defaults(this.options.buttonSettings, {\n showPrevious: true,\n showNext: true,\n showSubmit: true,\n showCancel: !this.options.readOnly\n });\n if (!this.isSecondInit) {\n this.isClickableDefined = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.breadcrumbSettings) === null || _b === void 0 ? void 0 : _b.hasOwnProperty('clickable');\n this.isSecondInit = true;\n }\n this.options.breadcrumbSettings = lodash_1.default.defaults(this.options.breadcrumbSettings, {\n clickable: true\n });\n this.options.allowPrevious = this.options.allowPrevious || false;\n this.page = 0;\n const onReady = super.init();\n this.setComponentSchema();\n if ((_c = this.pages) === null || _c === void 0 ? void 0 : _c[this.page]) {\n this.component = this.pages[this.page].component;\n }\n this.on('subWizardsUpdated', (subForm) => {\n const subWizard = this.subWizards.find(subWizard => { var _a; return (subForm === null || subForm === void 0 ? void 0 : subForm.id) && ((_a = subWizard.subForm) === null || _a === void 0 ? void 0 : _a.id) === (subForm === null || subForm === void 0 ? void 0 : subForm.id); });\n if (this.subWizards.length && subWizard) {\n subWizard.subForm.setValue(subForm._submission, {}, true);\n this.establishPages();\n this.redraw();\n }\n });\n return onReady;\n }\n get wizardKey() {\n return `wizard-${this.id}`;\n }\n get wizard() {\n return this.form;\n }\n set wizard(form) {\n this.setForm(form);\n }\n get buttons() {\n const buttons = {};\n [\n { name: 'cancel', method: 'cancel' },\n { name: 'previous', method: 'prevPage' },\n { name: 'next', method: 'nextPage' },\n { name: 'submit', method: 'submit' }\n ].forEach((button) => {\n if (this.hasButton(button.name)) {\n buttons[button.name] = button;\n }\n });\n return buttons;\n }\n get buttonOrder() {\n var _a, _b, _c;\n const defaultButtonOrder = [\n 'cancel',\n 'previous',\n 'next',\n 'submit'\n ];\n return (_c = (_b = (_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.wizardButtonOrder) === null || _b === void 0 ? void 0 : _b.toLowerCase().split(', ')) !== null && _c !== void 0 ? _c : defaultButtonOrder;\n }\n get renderContext() {\n var _a, _b;\n return {\n disableWizardSubmit: this.form.disableWizardSubmit,\n wizardKey: this.wizardKey,\n isBreadcrumbClickable: this.isBreadcrumbClickable(),\n isSubForm: !!this.parent && !((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.type) === 'wizard',\n panels: this.allPages.length ? this.allPages.map(page => page.component) : this.pages.map(page => page.component),\n buttons: this.buttons,\n currentPage: this.page,\n buttonOrder: this.buttonOrder,\n };\n }\n prepareNavigationSettings(ctx) {\n const currentPanel = this.currentPanel;\n if (currentPanel && currentPanel.buttonSettings) {\n Object.keys(currentPanel.buttonSettings).forEach(() => {\n Object.keys(ctx.buttons).forEach(key => {\n if (typeof currentPanel.buttonSettings[key] !== 'undefined' && !currentPanel.buttonSettings[key] || ctx.isSubForm) {\n ctx.buttons[key] = null;\n }\n });\n });\n }\n return this.renderTemplate('wizardNav', ctx);\n }\n prepareHeaderSettings(ctx, headerType) {\n var _a;\n const shouldHideBreadcrumbs = ((_a = this.currentPanel) === null || _a === void 0 ? void 0 : _a.breadcrumb) === 'none' ||\n lodash_1.default.get(this.form, 'settings.wizardBreadcrumbsType', '') === 'none';\n if (shouldHideBreadcrumbs || ctx.isSubForm) {\n return null;\n }\n return this.renderTemplate(headerType, ctx);\n }\n render() {\n const ctx = this.renderContext;\n if (this.component.key) {\n ctx.panels.map(panel => {\n if (panel.key === this.component.key) {\n this.currentPanel = panel;\n ctx.wizardPageTooltip = this.getFormattedTooltip(panel.tooltip);\n }\n });\n }\n const wizardNav = this.prepareNavigationSettings(ctx);\n const wizardHeaderType = `wizardHeader${lodash_1.default.get(this.form, 'settings.wizardHeaderType', '')}`;\n const wizardHeaderLocation = lodash_1.default.get(this.form, 'settings.wizardHeaderLocation', 'left');\n const wizardHeader = this.prepareHeaderSettings(ctx, wizardHeaderType);\n return this.renderTemplate('wizard', Object.assign(Object.assign({}, ctx), { className: super.getClassName(), wizardHeader,\n wizardHeaderType,\n wizardHeaderLocation,\n wizardNav, components: this.renderComponents([\n ...this.prefixComps,\n ...this.currentPage.components,\n ...this.suffixComps\n ]) }), this.builderMode ? 'builder' : 'form');\n }\n redrawNavigation() {\n if (this.element) {\n let navElement = this.element.querySelector(`#${this.wizardKey}-nav`);\n if (navElement) {\n this.detachNav();\n navElement.outerHTML = this.renderTemplate('wizardNav', this.renderContext);\n navElement = this.element.querySelector(`#${this.wizardKey}-nav`);\n this.loadRefs(navElement, {\n [`${this.wizardKey}-cancel`]: 'single',\n [`${this.wizardKey}-previous`]: 'single',\n [`${this.wizardKey}-next`]: 'single',\n [`${this.wizardKey}-submit`]: 'single',\n });\n this.attachNav();\n }\n }\n }\n redrawHeader() {\n if (this.element) {\n let headerElement = this.element.querySelector(`#${this.wizardKey}-header`);\n if (headerElement) {\n this.detachHeader();\n headerElement.outerHTML = this.renderTemplate(`wizardHeader${lodash_1.default.get(this.form, 'settings.wizardHeaderType', '')}`, this.renderContext);\n headerElement = this.element.querySelector(`#${this.wizardKey}-header`);\n this.loadRefs(headerElement, {\n [`${this.wizardKey}-link`]: 'multiple',\n [`${this.wizardKey}-tooltip`]: 'multiple'\n });\n this.attachHeader();\n }\n }\n }\n attach(element) {\n var _a;\n this.setElement(element);\n this.loadRefs(element, {\n [this.wizardKey]: 'single',\n [`${this.wizardKey}-header`]: 'single',\n [`${this.wizardKey}-cancel`]: 'single',\n [`${this.wizardKey}-previous`]: 'single',\n [`${this.wizardKey}-next`]: 'single',\n [`${this.wizardKey}-submit`]: 'single',\n [`${this.wizardKey}-link`]: 'multiple',\n [`${this.wizardKey}-tooltip`]: 'multiple'\n });\n if ((this.options.readOnly || this.editMode) && !this.enabledIndex) {\n this.enabledIndex = ((_a = this.pages) === null || _a === void 0 ? void 0 : _a.length) - 1;\n }\n this.hook('attachWebform', element, this);\n const promises = this.attachComponents(this.refs[this.wizardKey], [\n ...this.prefixComps,\n ...this.currentPage.components,\n ...this.suffixComps,\n ]);\n this.attachNav();\n this.attachHeader();\n return promises.then(() => {\n this.emit('render', { component: this.currentPage, page: this.page });\n if (this.component.scrollToTop) {\n this.scrollPageToTop();\n }\n });\n }\n scrollPageToTop() {\n var _a;\n const pageTop = (_a = this.refs[`${this.wizardKey}-header`]) !== null && _a !== void 0 ? _a : this.refs[this.wizardKey];\n if (!pageTop) {\n return;\n }\n if ('scrollIntoView' in pageTop) {\n pageTop.scrollIntoView(true);\n }\n else {\n this.scrollIntoView(pageTop);\n }\n }\n isBreadcrumbClickable() {\n let currentPage = null;\n this.pages.map(page => {\n if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {\n currentPage = page;\n }\n });\n return this.isClickableDefined ? this.options.breadcrumbSettings.clickable : lodash_1.default.get(currentPage, 'component.breadcrumbClickable', true);\n }\n isAllowPrevious() {\n let currentPage = null;\n this.pages.map(page => {\n if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {\n currentPage = page;\n }\n });\n return lodash_1.default.get(currentPage.component, 'allowPrevious', this.options.allowPrevious);\n }\n handleNaviageteOnEnter(event) {\n if (event.keyCode === 13) {\n const clickEvent = new CustomEvent('click');\n const buttonElement = this.refs[`${this.wizardKey}-${this.buttons.next.name}`];\n if (buttonElement) {\n buttonElement.dispatchEvent(clickEvent);\n }\n }\n }\n handleSaveOnEnter(event) {\n if (event.keyCode === 13) {\n const clickEvent = new CustomEvent('click');\n const buttonElement = this.refs[`${this.wizardKey}-${this.buttons.submit.name}`];\n if (buttonElement) {\n buttonElement.dispatchEvent(clickEvent);\n }\n }\n }\n attachNav() {\n if (this.component.navigateOnEnter) {\n this.addEventListener(document, 'keyup', this.handleNaviageteOnEnter.bind(this));\n }\n if (this.component.saveOnEnter) {\n this.addEventListener(document, 'keyup', this.handleSaveOnEnter.bind(this));\n }\n lodash_1.default.each(this.buttons, (button) => {\n const buttonElement = this.refs[`${this.wizardKey}-${button.name}`];\n this.addEventListener(buttonElement, 'click', (event) => {\n event.preventDefault();\n // Disable the button until done.\n buttonElement.setAttribute('disabled', 'disabled');\n this.setLoading(buttonElement, true);\n // Call the button method, then re-enable the button.\n this[button.method]().then(() => {\n buttonElement.removeAttribute('disabled');\n this.setLoading(buttonElement, false);\n }).catch(() => {\n buttonElement.removeAttribute('disabled');\n this.setLoading(buttonElement, false);\n });\n });\n });\n }\n emitWizardPageSelected(index) {\n this.emit('wizardPageSelected', this.pages[index], index);\n }\n attachHeader() {\n var _a;\n const isAllowPrevious = this.isAllowPrevious();\n this.attachTooltips(this.refs[`${this.wizardKey}-tooltip`], this.currentPanel.tooltip);\n if (this.isBreadcrumbClickable() || isAllowPrevious) {\n (_a = this.refs[`${this.wizardKey}-link`]) === null || _a === void 0 ? void 0 : _a.forEach((link, index) => {\n if (!isAllowPrevious || index <= this.enabledIndex) {\n this.addEventListener(link, 'click', (event) => {\n this.emit('wizardNavigationClicked', this.pages[index]);\n event.preventDefault();\n return this.setPage(index).then(() => {\n this.emitWizardPageSelected(index);\n });\n });\n }\n });\n }\n }\n detachNav() {\n if (this.component.navigateOnEnter) {\n this.removeEventListener(document, 'keyup', this.handleNaviageteOnEnter.bind(this));\n }\n if (this.component.saveOnEnter) {\n this.removeEventListener(document, 'keyup', this.handleSaveOnEnter.bind(this));\n }\n lodash_1.default.each(this.buttons, (button) => {\n this.removeEventListener(this.refs[`${this.wizardKey}-${button.name}`], 'click');\n });\n }\n detachHeader() {\n if (this.refs[`${this.wizardKey}-link`]) {\n this.refs[`${this.wizardKey}-link`].forEach((link) => {\n this.removeEventListener(link, 'click');\n });\n }\n }\n transformPages() {\n const allComponents = [];\n const components = this.getSortedComponents(this);\n let defferedComponents = [];\n this.allPages = [];\n // Get all components including all nested components and line up in the correct order\n const getAllComponents = (nestedComp, compsArr, pushAllowed = true) => {\n const nestedPages = [];\n const dataArrayComponents = ['datagrid', 'editgrid', 'dynamicWizard'];\n const currentComponents = (nestedComp === null || nestedComp === void 0 ? void 0 : nestedComp.subForm) ? this.getSortedComponents(nestedComp.subForm) : (nestedComp === null || nestedComp === void 0 ? void 0 : nestedComp.components) || [];\n const visibleComponents = currentComponents.filter(comp => comp._visible);\n const filteredComponents = visibleComponents.filter(comp => !dataArrayComponents.includes(comp.component.type) && (comp.type !== 'form' || comp.isNestedWizard));\n const additionalComponents = currentComponents.filter(comp => { var _a; return ((_a = comp.subForm) === null || _a === void 0 ? void 0 : _a._form.display) !== 'wizard'; });\n let hasNested = false;\n (0, utils_1.eachComponent)(filteredComponents, (comp) => {\n if (comp && comp.component) {\n if (comp.component.type === 'panel' && (comp === null || comp === void 0 ? void 0 : comp.parent.wizard) && !getAllComponents(comp, compsArr, false)) {\n if (pushAllowed) {\n this.setRootPanelId(comp);\n nestedPages.push(comp);\n }\n hasNested = true;\n }\n if (comp.isNestedWizard && comp.subForm) {\n const hasNestedForm = getAllComponents(comp, nestedPages, pushAllowed);\n if (!hasNested) {\n hasNested = hasNestedForm;\n }\n }\n }\n }, true);\n if (nestedComp.component.type === 'panel') {\n if (!hasNested && pushAllowed) {\n this.setRootPanelId(nestedComp);\n compsArr.push(nestedComp);\n }\n if (hasNested && additionalComponents.length) {\n const newComp = lodash_1.default.clone(nestedComp);\n newComp.components = additionalComponents;\n this.setRootPanelId(newComp);\n defferedComponents.push(newComp);\n }\n }\n if (pushAllowed) {\n compsArr.push(...defferedComponents, ...nestedPages);\n defferedComponents = [];\n }\n return hasNested;\n };\n components.forEach((component) => {\n if (component.visible) {\n getAllComponents(component, allComponents);\n }\n }, []);\n // recalculate pages only for root wizards, including the situation when the wizard is in a wrapper\n if (this.localRoot && this.id === this.localRoot.id) {\n allComponents.forEach((comp, index) => {\n comp.eachComponent((component) => {\n component.page = index;\n });\n });\n }\n this.allPages = allComponents;\n }\n getSortedComponents({ components, originalComponents }) {\n const currentComponents = [];\n const currentPages = [];\n if (components && components.length) {\n components.map(page => {\n if (page.component.type === 'panel') {\n currentPages[page.component.key || page.component.title] = page;\n }\n });\n }\n originalComponents === null || originalComponents === void 0 ? void 0 : originalComponents.forEach((item) => {\n if (!item.key) {\n item.key = item.title;\n }\n if (currentPages[item.key]) {\n currentComponents.push(currentPages[item.key]);\n }\n });\n return currentComponents;\n }\n findRootPanel(component) {\n var _a;\n return ((_a = component.parent) === null || _a === void 0 ? void 0 : _a.parent) ? this.findRootPanel(component.parent) : component;\n }\n setRootPanelId(component) {\n var _a;\n if (component.rootPanelId && component.rootPanelId !== component.id) {\n return;\n }\n const parent = ((_a = component.parent) === null || _a === void 0 ? void 0 : _a.parent) ? this.findRootPanel(component.parent) : component;\n component.rootPanelId = parent.id;\n }\n establishPages(data = this.data) {\n this.pages = [];\n this.prefixComps = [];\n this.suffixComps = [];\n const visible = [];\n const currentPages = {};\n const pageOptions = Object.assign(Object.assign({}, (lodash_1.default.clone(this.options))), (this.parent ? { root: this } : {}));\n if (this.components && this.components.length) {\n this.components.forEach(page => {\n if (page.component.type === 'panel') {\n currentPages[page.component.key || page.component.title] = page;\n }\n });\n }\n if (this.originalComponents) {\n this.originalComponents.forEach((item) => {\n if (item.type === 'panel') {\n if (!item.key) {\n item.key = item.title;\n }\n let page = currentPages[item.key];\n const forceShow = this.shouldForceShow(item);\n const forceHide = this.shouldForceHide(item);\n let isVisible = !page\n ? (0, utils_1.checkCondition)(item, data, data, this.component, this) && !item.hidden\n : page.visible;\n if (forceShow) {\n isVisible = true;\n }\n else if (forceHide) {\n isVisible = false;\n }\n if (isVisible) {\n visible.push(item);\n if (page) {\n this.pages.push(page);\n }\n }\n if (!page && isVisible) {\n page = this.createComponent(item, pageOptions);\n page.visible = isVisible;\n this.pages.push(page);\n page.eachComponent((component) => {\n component.page = (this.pages.length - 1);\n });\n }\n }\n else if (item.type !== 'button') {\n if (!this.pages.length) {\n this.prefixComps.push(this.createComponent(item, pageOptions));\n }\n else {\n this.suffixComps.push(this.createComponent(item, pageOptions));\n }\n }\n });\n }\n if (this.pages.length) {\n this.emit('pagesChanged');\n }\n this.transformPages();\n if (this.allPages && this.allPages.length) {\n this.updatePages();\n }\n return visible;\n }\n updatePages() {\n this.pages = this.allPages;\n }\n addComponents() {\n this.establishPages();\n }\n setPage(num) {\n if (num === this.page) {\n return Promise.resolve();\n }\n if (num >= 0 && num < this.pages.length) {\n this.page = num;\n this.pageFieldLogic(num);\n this.getNextPage();\n let parentNum = num;\n if (this.hasExtraPages) {\n const pageFromPages = this.pages[num];\n const pageFromComponents = this.components[num];\n if (!pageFromComponents || (pageFromPages === null || pageFromPages === void 0 ? void 0 : pageFromPages.id) !== pageFromComponents.id) {\n parentNum = this.components.findIndex(comp => {\n var _a, _b;\n return comp.id === ((_b = (_a = this.pages) === null || _a === void 0 ? void 0 : _a[parentNum]) === null || _b === void 0 ? void 0 : _b.rootPanelId);\n });\n }\n }\n if (!this._seenPages.includes(parentNum)) {\n this._seenPages = this._seenPages.concat(parentNum);\n }\n this.redraw().then(() => {\n this.checkData(this.submission.data);\n this.validateCurrentPage();\n });\n return Promise.resolve();\n }\n else if (!this.pages.length) {\n this.redraw();\n return Promise.resolve();\n }\n return Promise.reject('Page not found');\n }\n pageFieldLogic(page) {\n var _a;\n if ((_a = this.pages) === null || _a === void 0 ? void 0 : _a[page]) {\n // Handle field logic on pages.\n this.component = this.pages[page].component;\n this.originalComponent = (0, utils_1.fastCloneDeep)(this.component);\n this.fieldLogic(this.data);\n // If disabled changed, be sure to distribute the setting.\n this.disabled = this.shouldDisabled;\n }\n }\n get currentPage() {\n return (this.pages && (this.pages.length >= this.page)) ? this.pages[this.page] : { components: [] };\n }\n getNextPage() {\n var _a;\n if ((_a = this.pages) === null || _a === void 0 ? void 0 : _a[this.page]) {\n const data = this.submission.data;\n const form = this.pages[this.page].component;\n // Check conditional nextPage\n if (form) {\n const page = this.pages.length > (this.page + 1) && !this.showAllErrors ? this.page + 1 : -1;\n if (form.nextPage) {\n const next = this.evaluate(form.nextPage, {\n next: page,\n data,\n page,\n form\n }, 'next');\n if (next === null) {\n this.currentNextPage = null;\n return null;\n }\n const pageNum = parseInt(next, 10);\n if (!isNaN(parseInt(pageNum, 10)) && isFinite(pageNum)) {\n this.currentNextPage = pageNum;\n return pageNum;\n }\n this.currentNextPage = this.getPageIndexByKey(next);\n return this.currentNextPage;\n }\n this.currentNextPage = page;\n return page;\n }\n this.currentNextPage = null;\n }\n return null;\n }\n getPreviousPage() {\n return this.page - 1;\n }\n beforeSubmit() {\n const pages = this.getPages();\n return Promise.all(pages.map((page) => {\n page.options.beforeSubmit = true;\n return page.beforeSubmit();\n }));\n }\n beforePage(next) {\n return new Promise((resolve, reject) => {\n this.hook(next ? 'beforeNext' : 'beforePrev', this.currentPage, this.submission, (err) => {\n if (err) {\n this.showErrors(err, true);\n reject(err);\n }\n const form = this.currentPage;\n if (form) {\n form.beforePage(next).then(resolve).catch(reject);\n }\n else {\n resolve();\n }\n });\n });\n }\n emitNextPage() {\n this.emit('nextPage', { page: this.page, submission: this.submission });\n }\n nextPage() {\n // Read-only forms should not worry about validation before going to next page, nor should they submit.\n if (this.options.readOnly) {\n return this.beforePage(true).then(() => {\n return this.setPage(this.getNextPage()).then(() => {\n this.emitNextPage();\n });\n });\n }\n // Validate the form, before go to the next page\n const errors = this.validateCurrentPage({ dirty: true });\n if (errors.length === 0) {\n this.checkData(this.submission.data);\n return this.beforePage(true).then(() => {\n return this.setPage(this.getNextPage()).then(() => {\n if (!(this.options.readOnly || this.editMode) && this.enabledIndex < this.page) {\n this.enabledIndex = this.page;\n this.redraw();\n }\n this.emitNextPage();\n });\n });\n }\n else {\n this.currentPage.components.forEach((comp) => comp.setPristine(false));\n this.scrollIntoView(this.element);\n return Promise.reject(this.showErrors(errors, true));\n }\n }\n validateCurrentPage(flags = {}) {\n var _a;\n // Accessing the parent ensures the right instance (whether it's the parent Wizard or a nested Wizard) performs its validation\n return (_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.parent.validateComponents(this.currentPage.component.components, this.currentPage.parent.data, flags);\n }\n emitPrevPage() {\n this.emit('prevPage', { page: this.page, submission: this.submission });\n }\n prevPage() {\n return this.beforePage().then(() => {\n return this.setPage(this.getPreviousPage()).then(() => {\n this.emitPrevPage();\n });\n });\n }\n cancel(noconfirm) {\n if (this.options.readOnly) {\n return Promise.resolve();\n }\n if (super.cancel(noconfirm)) {\n this.setPristine(true);\n return this.setPage(0).then(() => {\n if (this.enabledIndex) {\n this.enabledIndex = 0;\n }\n this.onChange({ resetValue: true });\n this.redraw();\n return this.page;\n });\n }\n return Promise.resolve();\n }\n getPageIndexByKey(key) {\n let pageIndex = this.page;\n this.pages.forEach((page, index) => {\n if (page.component.key === key) {\n pageIndex = index;\n return false;\n }\n });\n return pageIndex;\n }\n get schema() {\n return this.wizard;\n }\n setComponentSchema() {\n const pageKeys = {};\n this.originalComponents = [];\n this.component.components.map((item) => {\n if (item.type === 'panel') {\n item.key = (0, utils_1.uniqueKey)(pageKeys, (item.key || 'panel'));\n pageKeys[item.key] = true;\n if (this.wizard.full) {\n this.options.show = this.options.show || {};\n this.options.show[item.key] = true;\n }\n else if (this.wizard.hasOwnProperty('full') && !lodash_1.default.isEqual(this.originalOptions.show, this.options.show)) {\n this.options.show = Object.assign({}, (this.originalOptions.show || {}));\n }\n }\n this.originalComponents.push(lodash_1.default.clone(item));\n });\n if (!Object.keys(pageKeys).length) {\n const newPage = {\n type: 'panel',\n title: 'Page 1',\n label: 'Page 1',\n key: 'page1',\n components: this.component.components\n };\n this.component.components = [newPage];\n this.originalComponents.push(lodash_1.default.clone(newPage));\n }\n }\n setForm(form, flags) {\n if (!form) {\n return;\n }\n return super.setForm(form, flags);\n }\n onSetForm(clonedForm, initialForm) {\n this.component.components = (this.parent ? initialForm.components : clonedForm.components) || [];\n this.setComponentSchema();\n }\n setEditMode(submission) {\n if (!this.editMode && submission._id && !this.options.readOnly) {\n this.editMode = true;\n this.redraw();\n }\n }\n setValue(submission, flags = {}, ignoreEstablishment) {\n const changed = this.getPages({ all: true }).reduce((changed, page) => {\n return this.setNestedValue(page, submission.data, flags, changed) || changed;\n }, false);\n this.mergeData(this.data, submission.data);\n if (changed) {\n this.pageFieldLogic(this.page);\n }\n submission.data = this.data;\n this._submission = submission;\n if (!ignoreEstablishment) {\n this.establishPages(submission.data);\n }\n this.setEditMode(submission);\n return changed;\n }\n isClickable(page, index) {\n return this.page !== index && (0, utils_1.firstNonNil)([\n lodash_1.default.get(page, 'breadcrumbClickable'),\n this.options.breadcrumbSettings.clickable\n ]);\n }\n hasButton(name, nextPage = this.getNextPage()) {\n // get page options with global options as default values\n const { previous = this.options.buttonSettings.showPrevious, cancel = this.options.buttonSettings.showCancel, submit = this.options.buttonSettings.showSubmit, next = this.options.buttonSettings.showNext } = lodash_1.default.get(this.currentPage, 'component.buttonSettings', {});\n switch (name) {\n case 'previous':\n return previous && (this.getPreviousPage() > -1);\n case 'next':\n return next && (nextPage !== null) && (nextPage !== -1);\n case 'cancel':\n return cancel && !this.options.readOnly;\n case 'submit':\n return submit && !this.options.readOnly && ((nextPage === null) || (this.page === (this.pages.length - 1)));\n default:\n return true;\n }\n }\n pageId(page) {\n if (page.key) {\n // Some panels have the same key....\n return `${page.key}-${page.title}`;\n }\n else if (page.components &&\n page.components.length > 0) {\n return this.pageId(page.components[0]);\n }\n else {\n return page.title;\n }\n }\n onChange(flags, changed, modified, changes) {\n var _a, _b;\n super.onChange(flags, changed, modified, changes);\n const errors = this.validate(this.localData, { dirty: false });\n if (this.alert) {\n this.showErrors(errors, true, true);\n }\n // If the pages change, need to redraw the header.\n let currentPanels;\n let panels;\n const currentNextPage = this.currentNextPage;\n if (this.hasExtraPages) {\n currentPanels = this.pages.map(page => page.component.key);\n this.establishPages();\n panels = this.pages.map(page => page.component.key);\n }\n else {\n currentPanels = this.currentPanels || this.pages.map(page => page.component.key);\n panels = this.establishPages().map(panel => panel.key);\n this.currentPanels = panels;\n if (((_a = this.currentPanel) === null || _a === void 0 ? void 0 : _a.key) && ((_b = this.currentPanels) === null || _b === void 0 ? void 0 : _b.length)) {\n this.setPage(this.currentPanels.findIndex(panel => panel === this.currentPanel.key));\n }\n }\n if (!lodash_1.default.isEqual(panels, currentPanels) || (flags && flags.fromSubmission)) {\n this.redrawHeader();\n }\n // If the next page changes, then make sure to redraw navigation.\n if (currentNextPage !== this.getNextPage()) {\n this.redrawNavigation();\n }\n if (this.options.readOnly && (this.prefixComps.length || this.suffixComps.length)) {\n this.redraw();\n }\n }\n redraw() {\n var _a, _b;\n if ((_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.modalEdit) {\n return this.parent.redraw();\n }\n return super.redraw();\n }\n rebuild() {\n const currentPage = this.page;\n const setCurrentPage = () => this.setPage(currentPage);\n return super.rebuild().then(setCurrentPage);\n }\n checkValidity(data, dirty, row, currentPageOnly, childErrors = []) {\n if (!this.checkCondition(row, data)) {\n this.setCustomValidity('');\n return true;\n }\n const components = !currentPageOnly || this.isLastPage()\n ? this.getComponents()\n : this.currentPage.components;\n return components.reduce((check, comp) => comp.checkValidity(data, dirty, row, childErrors) && check, true);\n }\n get errors() {\n if (!this.isLastPage()) {\n return this.currentPage.errors;\n }\n return super.errors;\n }\n focusOnComponent(key) {\n const component = this.getComponent(key);\n if (component) {\n let topPanel = component.parent;\n while (!(topPanel.parent instanceof Wizard)) {\n topPanel = topPanel.parent;\n }\n const pageIndex = this.pages.findIndex(page => page === topPanel);\n if (pageIndex >= 0) {\n const page = this.pages[pageIndex];\n if (page && page !== this.currentPage) {\n return this.setPage(pageIndex).then(() => {\n this.showErrors(this.validate(this.localData, { dirty: true }));\n super.focusOnComponent(key);\n });\n }\n }\n }\n return super.focusOnComponent(key);\n }\n}\nexports[\"default\"] = Wizard;\nWizard.setBaseUrl = Formio_1.Formio.setBaseUrl;\nWizard.setApiUrl = Formio_1.Formio.setApiUrl;\nWizard.setAppUrl = Formio_1.Formio.setAppUrl;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/Wizard.js?");
5579
5589
 
5580
5590
  /***/ }),
5581
5591
 
@@ -5685,7 +5695,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5685
5695
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5686
5696
 
5687
5697
  "use strict";
5688
- 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 *\n * @return {Object}\n *\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n *\n * @param schema\n * @return {Array}\n *\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n *\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n *\n * @param {Object} component - The component JSON you wish to initialize.\n * @param {Object} options - The options for this component.\n * @param {Object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * The data path to this specific component instance.\n *\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 *\n * @type {Object}\n */\n this.childComponentsMap = {};\n /**\n * Determines if this component is disabled, or not.\n *\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n *\n * @type {Component}\n */\n this.root = this.options.root || this;\n this.localRoot = this.options.localRoot || this;\n /**\n * If this input has been input and provided value.\n *\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n *\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n 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 *\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 destroy() {\n super.destroy();\n this.detach();\n this.addons.forEach((addon) => addon.destroy());\n }\n get shouldDisabled() {\n return this.options.readOnly || this.component.disabled || (this.options.hasOwnProperty('disabled') && this.options.disabled[this.key]);\n }\n get isInputComponent() {\n return !this.component.hasOwnProperty('input') || this.component.input;\n }\n get allowData() {\n return this.hasInput;\n }\n get hasInput() {\n return this.isInputComponent || (this.refs.input && this.refs.input.length);\n }\n get defaultSchema() {\n return Component.schema();\n }\n get key() {\n return lodash_1.default.get(this.component, 'key', '');\n }\n set parentVisible(value) {\n this._parentVisible = value;\n }\n get parentVisible() {\n return this._parentVisible;\n }\n set parentDisabled(value) {\n this._parentDisabled = value;\n }\n get parentDisabled() {\n return this._parentDisabled;\n }\n shouldForceVisibility(component, visibility) {\n if (!this.options[visibility]) {\n return false;\n }\n if (!component) {\n component = this.component;\n }\n if (lodash_1.default.isArray(this.options[visibility])) {\n return this.options[visibility].includes(component.key);\n }\n return this.options[visibility][component.key];\n }\n shouldForceHide(component) {\n return this.shouldForceVisibility(component, 'hide');\n }\n shouldForceShow(component) {\n return this.shouldForceVisibility(component, 'show');\n }\n /**\n *\n * @param value {boolean}\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n *\n * @returns {boolean}\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n *\n * @param schema\n * @param defaultSchema\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = 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 *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize, options) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n *\n * @param template\n * @param data\n * @param actions\n *\n * @return {HTMLElement|String} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n performInputMapping(input) {\n return input;\n }\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components\n * to perform special functions.\n *\n * @return {*}\n */\n beforePage() {\n return Promise.resolve(true);\n }\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components\n * to perform special async functions.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n *\n * @return {*}\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n get timezone() {\n return this.getTimezone(this.component);\n }\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n /**\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 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 setOpenModalElement(template) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n 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 build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\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.element = element;\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n *\n * @param value\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n *\n * @param component\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n createViewOnlyElement() {\n this.element = this.ce('dl', {\n id: this.id\n });\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n *\n * @param value\n * @return {*}\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * @param {*} data\n * @param {boolean} [forceUseValue=false] - if true, return 'value' property of the data\n * @return {*}\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @return {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement}\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n *\n * @param pristine {boolean} - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n get isPristine() {\n return this.pristine;\n }\n setDirty(dirty) {\n this.dirty = dirty;\n }\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n get visibleErrors() {\n return this._visibleErrors;\n }\n get errors() {\n return this._errors;\n }\n /**\n * Returns the error label for this component.\n * @return {*}\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param type\n * @return {*}\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.element = parent.children[index];\n return this.attach(this.element);\n }\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n *\n * @return {null}\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n *\n * @param data\n * @return {boolean}\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n *\n * @param row - The row contextual data.\n * @param data - The global data object.\n * @return {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param args\n * @return {boolean}\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n *\n * @param data\n */\n fieldLogic(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n *\n * @param message\n * @param dirty\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n if (message.message && typeof message.message === 'string') {\n message.message = message.message.replaceAll('<', '&lt;').replaceAll('>', '&gt;');\n }\n return this.renderTemplate('message', Object.assign({}, message));\n }).join(''));\n }\n }\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n // do not set error classes for hidden components\n if (!this.visible) {\n return;\n }\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root && this.root.triggerChange) {\n this.root.triggerChange(...args);\n }\n }\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur') {\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 *\n * @return {null}\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n *\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n *\n * @return {*}\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @return {*}\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n *\n * @param value\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n *\n * @param index\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n *\n * @return {*}\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n *\n * @param index\n * @returns {*}\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n *\n * @return {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n *\n * @param index\n * @param value\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && !Array.isArray(value)) {\n value = value ? [value] : [];\n }\n return value;\n }\n /**\n * Update a value of this component.\n *\n * @param flags\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n *\n * @param args\n * @return {boolean}\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n *\n * @param newValue\n * @param oldValue\n * @return {boolean}\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n *\n * @param flags\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n 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 /**\n * Perform a calculated value operation.\n *\n * @param data - The global data object.\n *\n * @return {boolean} - If the value changed during calculation.\n */\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set or in builder mode\n if (this.builderMode || lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n this.calculatedValue = null;\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n *\n * @param args\n * @return {boolean}\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n *\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n *\n * @param value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n *\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n 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 *\n * @param data\n * @param dirty\n * @return {boolean}\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 {*} errors\n * @returns\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\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\n */\n validateComponent(data, row, 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 *\n * @param data\n * @param dirty\n * @param row\n * @return {boolean}\n */\n checkComponentValidity(data, dirty, row, 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) => err.component.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) => err.component.key === this.component.key);\n }\n }\n return errors.length === 0;\n }\n }\n /**\n * Checks the validity of the component.\n * @param {*} data\n * @param {*} dirty\n * @param {*} row\n * @param {*} silentCheck\n * @returns\n */\n checkValidity(data, dirty, row, silentCheck, errors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n console.log('Deprecation warning: Component.checkValidity() will be deprecated in 6.x version of renderer. Use Component.validateComponent instead.');\n return this.checkComponentValidity(data, dirty, row, { silentCheck }, errors);\n }\n checkAsyncValidity(data, dirty, row, silentCheck, errors = []) {\n console.log('Deprecation warning: Component.checkAsyncValidity() will be deprecated in 6.x version of renderer. Use Component.validateComponent instead.');\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 *\n * @param data - The root data of the change event.\n * @param flags - The flags from this change event.\n *\n * @return boolean - If component is valid or not.\n */\n checkData(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n }\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 *\n * @return {boolean}\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 *\n * @return {boolean|*}\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, 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 */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @return {boolean}\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n *\n * @param {boolean} disabled\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = typeof index === 'number' && this.refs.input[index]\n ? this.refs.input[index]\n : this.refs.input[this.refs.input.length - 1];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n src = Array.isArray(src) ? src : [src];\n src.forEach((lib) => {\n let attrs = {};\n let elementType = '';\n if (typeof lib === 'string') {\n lib = {\n type: 'script',\n src: lib\n };\n }\n switch (lib.type) {\n case 'script':\n elementType = 'script';\n attrs = {\n src: lib.src,\n type: 'text/javascript',\n defer: true,\n async: true\n };\n break;\n case 'styles':\n elementType = 'link';\n attrs = {\n href: lib.src,\n rel: 'stylesheet'\n };\n break;\n }\n // Add the script to the top page.\n const script = document.createElement(elementType);\n for (const attr in attrs) {\n script.setAttribute(attr, attrs[attr]);\n }\n document.getElementsByTagName('head')[0].appendChild(script);\n });\n // if no callback is provided, then check periodically for the script.\n if (polling) {\n setTimeout(function checkLibrary() {\n const plugin = lodash_1.default.get(window, property);\n if (plugin) {\n Component.externalLibraries[name].resolve(plugin);\n }\n else {\n // check again after 200 ms.\n setTimeout(checkLibrary, 200);\n }\n }, 200);\n }\n }\n }\n return Component.externalLibraries[name].ready;\n};\nComponent.libraryReady = function (name) {\n if (Component.externalLibraries.hasOwnProperty(name) &&\n Component.externalLibraries[name].ready) {\n return Component.externalLibraries[name].ready;\n }\n return Promise.reject(`${name} library was not required.`);\n};\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/component/Component.js?");
5698
+ 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 *\n * @return {Object}\n *\n */\n static get conditionOperatorsSettings() {\n return {\n operators: ['isEqual', 'isNotEqual', 'isEmpty', 'isNotEmpty'],\n valueComponent() {\n return {\n type: 'textfield',\n widget: {\n type: 'input'\n }\n };\n }\n };\n }\n /**\n * Return the array of possible types of component value absed on its schema.\n *\n * @param schema\n * @return {Array}\n *\n */\n static savedValueTypes(schema) {\n schema = schema || {};\n return FormioUtils.getComponentSavedTypes(schema) || [FormioUtils.componentValueTypes.any];\n }\n /**\n * Provides a table view for this component. Override if you wish to do something different than using getView\n * method of your instance.\n *\n * @param value\n * @param options\n */\n /* eslint-disable no-unused-vars */\n static tableView(value, options) { }\n /* eslint-enable no-unused-vars */\n /**\n * Initialize a new Component.\n *\n * @param {Object} component - The component JSON you wish to initialize.\n * @param {Object} options - The options for this component.\n * @param {Object} data - The global data submission object this component will belong.\n */\n /* eslint-disable max-statements */\n constructor(component, options, data) {\n super(Object.assign({\n renderMode: 'form',\n attachMode: 'full',\n noDefaults: false\n }, options || {}));\n // Restore the component id.\n if (component && component.id) {\n this.id = component.id;\n }\n /**\n * Determines if this component has a condition assigned to it.\n * @type {null}\n * @private\n */\n this._hasCondition = null;\n /**\n * References to dom elements\n */\n this.refs = {};\n // Allow global override for any component JSON.\n if (component &&\n this.options.components &&\n this.options.components[component.type]) {\n lodash_1.default.merge(component, this.options.components[component.type]);\n }\n /**\n * The data path to this specific component instance.\n *\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 *\n * @type {Object}\n */\n this.childComponentsMap = {};\n /**\n * Determines if this component is disabled, or not.\n *\n * @type {boolean}\n */\n this._disabled = (0, utils_1.boolValue)(this.component.disabled) ? this.component.disabled : false;\n /**\n * Points to the root component, usually the FormComponent.\n *\n * @type {Component}\n */\n this.root = this.options.root || this;\n this.localRoot = this.options.localRoot || this;\n /**\n * If this input has been input and provided value.\n *\n * @type {boolean}\n */\n this.pristine = true;\n /**\n * Points to the parent component.\n *\n * @type {Component}\n */\n this.parent = this.options.parent;\n this.options.name = this.options.name || 'data';\n 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 *\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 *\n * @param value {boolean}\n */\n set visible(value) {\n if (this._visible !== value) {\n // Skip if this component is set to visible and is supposed to be hidden.\n if (value && this.shouldForceHide()) {\n return;\n }\n // Skip if this component is set to hidden and is supposed to be shown.\n if (!value && this.shouldForceShow()) {\n return;\n }\n this._visible = value;\n this.clearOnHide();\n this.redraw();\n }\n }\n /**\n *\n * @returns {boolean}\n */\n get visible() {\n // Show only if visibility changes or if we are in builder mode or if hidden fields should be shown.\n if (this.builderMode || this.previewMode || this.options.showHiddenFields) {\n return true;\n }\n if (this.shouldForceHide()) {\n return false;\n }\n if (this.shouldForceShow()) {\n return true;\n }\n return this._visible && this._parentVisible;\n }\n get currentForm() {\n return this._currentForm;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n }\n get fullMode() {\n return this.options.attachMode === 'full';\n }\n get builderMode() {\n return this.options.attachMode === 'builder';\n }\n get calculatedPath() {\n console.error('component.calculatedPath was deprecated, use component.path instead.');\n return this.path;\n }\n get labelPosition() {\n return this.component.labelPosition;\n }\n get labelWidth() {\n const width = this.component.labelWidth;\n return width >= 0 ? width : 30;\n }\n get labelMargin() {\n const margin = this.component.labelMargin;\n return margin >= 0 ? margin : 3;\n }\n get isAdvancedLabel() {\n return [\n 'left-left',\n 'left-right',\n 'right-left',\n 'right-right'\n ].includes(this.labelPosition);\n }\n get labelPositions() {\n return this.labelPosition.split('-');\n }\n get skipInEmail() {\n return false;\n }\n rightDirection(direction) {\n if (this.options.condensedMode) {\n return false;\n }\n return direction === 'right';\n }\n getLabelInfo(isCondensed = false) {\n const isRightPosition = this.rightDirection(this.labelPositions[0]);\n const isLeftPosition = this.labelPositions[0] === 'left' || isCondensed;\n const isRightAlign = this.rightDirection(this.labelPositions[1]);\n let contentMargin = '';\n if (this.component.hideLabel) {\n const margin = isCondensed ? 0 : this.labelWidth + this.labelMargin;\n contentMargin = isRightPosition ? `margin-right: ${margin}%` : '';\n contentMargin = isLeftPosition ? `margin-left: ${margin}%` : '';\n }\n const labelStyles = `\n flex: ${this.labelWidth};\n ${isRightPosition ? 'margin-left' : 'margin-right'}: ${this.labelMargin}%;\n `;\n const contentStyles = `\n flex: ${100 - this.labelWidth - this.labelMargin};\n ${contentMargin};\n ${this.component.hideLabel ? `max-width: ${100 - this.labelWidth - this.labelMargin}` : ''};\n `;\n return {\n isRightPosition,\n isRightAlign,\n labelStyles,\n contentStyles\n };\n }\n /**\n * Returns only the schema that is different from the default.\n *\n * @param schema\n * @param defaultSchema\n */\n getModifiedSchema(schema, defaultSchema, recursion) {\n const modified = {};\n if (!defaultSchema) {\n return schema;\n }\n lodash_1.default.each(schema, (val, key) => {\n if (!lodash_1.default.isArray(val) && lodash_1.default.isObject(val) && defaultSchema.hasOwnProperty(key)) {\n const subModified = this.getModifiedSchema(val, defaultSchema[key], true);\n if (!lodash_1.default.isEmpty(subModified)) {\n modified[key] = subModified;\n }\n }\n else if (lodash_1.default.isArray(val)) {\n if (val.length !== 0 && !lodash_1.default.isEqual(val, defaultSchema[key])) {\n modified[key] = val;\n }\n }\n else if ((!recursion && (key === 'type')) ||\n (!recursion && (key === 'key')) ||\n (!recursion && (key === 'label')) ||\n (!recursion && (key === 'input')) ||\n (!recursion && (key === 'tableView')) ||\n (val !== '' && !defaultSchema.hasOwnProperty(key)) ||\n (val !== '' && val !== defaultSchema[key]) ||\n (defaultSchema[key] && val !== defaultSchema[key])) {\n modified[key] = val;\n }\n });\n return modified;\n }\n /**\n * Returns the JSON schema for this component.\n */\n get schema() {\n return (0, utils_1.fastCloneDeep)(this.getModifiedSchema(lodash_1.default.omit(this.component, 'id'), this.defaultSchema));\n }\n /**\n * Returns true if component is inside DataGrid\n */\n get isInDataGrid() {\n return this.inDataGrid;\n }\n /**\n * Translate a text using the i18n system.\n *\n * @param {string} text - The i18n identifier.\n * @param {Object} params - The i18n parameters to use for translation.\n */\n t(text, params = {}, ...args) {\n if (!text) {\n return '';\n }\n // Use _userInput: true to ignore translations from defaults\n if (text in en_1.default && params._userInput) {\n return text;\n }\n params.data = 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 *\n * @param string\n * @returns {*}\n */\n sanitize(dirty, forceSanitize, options) {\n var _a;\n if (!this.shouldSanitizeValue && !forceSanitize) {\n return dirty;\n }\n return FormioUtils.sanitize(dirty, {\n sanitizeConfig: lodash_1.default.merge(((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitizeConfig) || {}, options || {}),\n });\n }\n /**\n * Render a template string into html.\n *\n * @param template\n * @param data\n * @param actions\n *\n * @return {HTMLElement|String} - The created element or an empty string if template is not specified.\n */\n renderString(template, data) {\n if (!template) {\n return '';\n }\n // Interpolate the template and populate\n return this.interpolate(template, data);\n }\n performInputMapping(input) {\n return input;\n }\n get widget() {\n var _a;\n const settings = this.component.widget;\n if (settings && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot)) {\n settings.shadowRoot = this.root.shadowRoot;\n }\n const widget = settings && widgets_1.default[settings.type] ? new widgets_1.default[settings.type](settings, this.component, this) : null;\n return widget;\n }\n getBrowserLanguage() {\n const nav = window.navigator;\n const browserLanguagePropertyKeys = ['language', 'browserLanguage', 'systemLanguage', 'userLanguage'];\n let language;\n // support for HTML 5.1 \"navigator.languages\"\n if (Array.isArray(nav.languages)) {\n for (let i = 0; i < nav.languages.length; i++) {\n language = nav.languages[i];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n }\n // support for other well known properties in browsers\n for (let i = 0; i < browserLanguagePropertyKeys.length; i++) {\n language = nav[browserLanguagePropertyKeys[i]];\n if (language && language.length) {\n return language.split(';')[0];\n }\n }\n return null;\n }\n /**\n * Called before a next and previous page is triggered allowing the components\n * to perform special functions.\n *\n * @return {*}\n */\n beforePage() {\n return Promise.resolve(true);\n }\n beforeNext() {\n return this.beforePage(true);\n }\n /**\n * Called before a submission is triggered allowing the components\n * to perform special async functions.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.resolve(true);\n }\n /**\n * Return the submission timezone.\n *\n * @return {*}\n */\n get submissionTimezone() {\n this.options.submissionTimezone = this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');\n return this.options.submissionTimezone;\n }\n get timezone() {\n return this.getTimezone(this.component);\n }\n getTimezone(settings) {\n if (settings.timezone) {\n return settings.timezone;\n }\n if (settings.displayInTimezone === 'utc') {\n return 'UTC';\n }\n const submissionTimezone = this.submissionTimezone;\n if (submissionTimezone &&\n ((settings.displayInTimezone === 'submission') ||\n ((this.options.pdf || this.options.server) && (settings.displayInTimezone === 'viewer')))) {\n return submissionTimezone;\n }\n // Return current timezone if none are provided.\n return (0, utils_1.currentTimezone)();\n }\n /**\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 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 setOpenModalElement(template) {\n this.componentModal.setOpenModalElement(template || this.getModalPreviewTemplate());\n }\n getModalPreviewTemplate() {\n var _a;\n const dataValue = this.component.type === 'password' ? this.dataValue.replace(/./g, '•') : this.dataValue;\n 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 build(element) {\n element = element || this.element;\n this.empty(element);\n this.setContent(element, this.render());\n return this.attach(element);\n }\n get hasModalSaveButton() {\n return true;\n }\n render(children = `Unknown component: ${this.component.type}`, topLevel = false) {\n const isVisible = this.visible;\n this.rendered = true;\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n return ComponentModal_1.default.render(this, {\n visible: isVisible,\n showSaveButton: this.hasModalSaveButton,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n else {\n return this.renderTemplate('component', {\n visible: isVisible,\n id: this.id,\n classes: this.className,\n styles: this.customStyle,\n children\n }, topLevel);\n }\n }\n attachTooltips(toolTipsRefs) {\n toolTipsRefs === null || toolTipsRefs === void 0 ? void 0 : toolTipsRefs.forEach((tooltip, index) => {\n if (tooltip) {\n const tooltipAttribute = tooltip.getAttribute('data-tooltip');\n const tooltipDataTitle = tooltip.getAttribute('data-title');\n const tooltipText = this.interpolate(tooltipDataTitle || tooltipAttribute)\n .replace(/(?:\\r\\n|\\r|\\n)/g, '<br />');\n this.tooltips[index] = (0, tippy_js_1.default)(tooltip, {\n allowHTML: true,\n trigger: 'mouseenter click focus',\n placement: 'right',\n zIndex: 10000,\n interactive: true,\n content: this.t(this.sanitize(tooltipText), { _userInput: true }),\n });\n }\n });\n }\n createComponentModal(element, modalShouldBeOpened, currentValue) {\n return new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\n }\n attach(element) {\n if (!this.builderMode && !this.previewMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n const openModalTemplate = this.componentModal && modalShouldBeOpened\n ? this.componentModal.openModalTemplate\n : null;\n this.componentModal = this.createComponentModal(element, modalShouldBeOpened, currentValue);\n this.setOpenModalElement(openModalTemplate);\n }\n this.attached = true;\n this.setElement(element);\n element.component = this;\n // If this already has an id, get it from the dom. If SSR, it could be different from the initiated id.\n if (this.element.id) {\n this.id = this.element.id;\n this.component.id = this.id;\n }\n this.loadRefs(element, {\n messageContainer: 'single',\n tooltip: 'multiple'\n });\n this.attachTooltips(this.refs.tooltip);\n // Attach logic.\n this.attachLogic();\n this.autofocus();\n // Allow global attach.\n this.hook('attachComponent', element, this);\n // Allow attach per component type.\n const type = this.component.type;\n if (type) {\n this.hook(`attach${type.charAt(0).toUpperCase() + type.substring(1, type.length)}`, element, this);\n }\n this.restoreFocus();\n this.addons.forEach((addon) => addon.attach(element));\n return Promise.resolve();\n }\n restoreFocus() {\n var _a, _b, _c;\n const isFocused = ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.path) === this.path;\n if (isFocused) {\n this.loadRefs(this.element, { input: 'multiple' });\n this.focus((_c = this.root.currentSelection) === null || _c === void 0 ? void 0 : _c.index);\n this.restoreCaretPosition();\n }\n }\n addShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || !this.root || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.addShortcut(element, shortcut);\n }\n removeShortcut(element, shortcut) {\n // Avoid infinite recursion.\n if (!element || (this.root === this)) {\n return;\n }\n if (!shortcut) {\n shortcut = this.component.shortcut;\n }\n this.root.removeShortcut(element, shortcut);\n }\n /**\n * Remove all event handlers.\n */\n detach() {\n // First iterate through each ref and delete the component so there are no dangling component references.\n lodash_1.default.each(this.refs, (ref) => {\n if (typeof ref === NodeList) {\n ref.forEach((elem) => {\n delete elem.component;\n });\n }\n else if (ref) {\n delete ref.component;\n }\n });\n this.refs = {};\n this.removeEventListeners();\n this.detachLogic();\n if (this.tooltip) {\n this.tooltip.destroy();\n }\n }\n checkRefresh(refreshData, changed, flags) {\n const changePath = lodash_1.default.get(changed, 'instance.path', false);\n // Don't let components change themselves.\n if (changePath && this.path === changePath) {\n return;\n }\n if (refreshData === 'data') {\n this.refresh(this.data, changed, flags);\n }\n else if ((changePath && (0, utils_1.getComponentPath)(changed.instance) === refreshData) && changed && changed.instance &&\n // Make sure the changed component is not in a different \"context\". Solves issues where refreshOn being set\n // in fields inside EditGrids could alter their state from other rows (which is bad).\n this.inContext(changed.instance)) {\n this.refresh(changed.value, changed, flags);\n }\n }\n checkRefreshOn(changes, flags = {}) {\n changes = changes || [];\n if (flags.noRefresh) {\n return;\n }\n if (!changes.length && flags.changed) {\n changes = [flags.changed];\n }\n const refreshOn = flags.fromBlur ? this.component.refreshOnBlur : this.component.refreshOn || this.component.redrawOn;\n // If they wish to refresh on a value, then add that here.\n if (refreshOn) {\n if (Array.isArray(refreshOn)) {\n refreshOn.forEach(refreshData => changes.forEach(changed => this.checkRefresh(refreshData, changed, flags)));\n }\n else {\n changes.forEach(changed => this.checkRefresh(refreshOn, changed, flags));\n }\n }\n }\n /**\n * Refreshes the component with a new value.\n *\n * @param value\n */\n refresh(value) {\n if (this.hasOwnProperty('refreshOnValue')) {\n this.refreshOnChanged = !lodash_1.default.isEqual(value, this.refreshOnValue);\n }\n else {\n this.refreshOnChanged = true;\n }\n this.refreshOnValue = (0, utils_1.fastCloneDeep)(value);\n if (this.refreshOnChanged) {\n if (this.component.clearOnRefresh) {\n this.setValue(null);\n }\n this.triggerRedraw();\n }\n }\n /**\n * Checks to see if a separate component is in the \"context\" of this component. This is determined by first checking\n * if they share the same \"data\" object. It will then walk up the parent tree and compare its parents data objects\n * with the components data and returns true if they are in the same context.\n *\n * Different rows of the same EditGrid, for example, are in different contexts.\n *\n * @param component\n */\n inContext(component) {\n if (component.data === this.data) {\n return true;\n }\n let parent = this.parent;\n while (parent) {\n if (parent.data === component.data) {\n return true;\n }\n parent = parent.parent;\n }\n return false;\n }\n get viewOnly() {\n return this.options.readOnly && this.options.viewAsHtml;\n }\n setElement(element) {\n if (this.element) {\n delete this.element.component;\n delete this.element;\n }\n this.element = element;\n }\n createViewOnlyElement() {\n this.setElement(this.ce('dl', {\n id: this.id\n }));\n if (this.element) {\n // Ensure you can get the component info from the element.\n this.element.component = this;\n }\n return this.element;\n }\n get defaultViewOnlyValue() {\n return '-';\n }\n /**\n * Uses the widget to determine the output string.\n *\n * @param value\n * @return {*}\n */\n getWidgetValueAsString(value, options) {\n const noInputWidget = !this.refs.input || !this.refs.input[0] || !this.refs.input[0].widget;\n if (!value || noInputWidget) {\n if (!this.widget || !value) {\n return value;\n }\n else {\n return this.widget.getValueAsString(value);\n }\n }\n if (Array.isArray(value)) {\n const values = [];\n value.forEach((val, index) => {\n const widget = this.refs.input[index] && this.refs.input[index].widget;\n if (widget) {\n values.push(widget.getValueAsString(val, options));\n }\n });\n return values;\n }\n const widget = this.refs.input[0].widget;\n return widget.getValueAsString(value, options);\n }\n getValueAsString(value, options) {\n if (!value) {\n return '';\n }\n value = this.getWidgetValueAsString(value, options);\n if (Array.isArray(value)) {\n return value.join(', ');\n }\n if (lodash_1.default.isPlainObject(value)) {\n return JSON.stringify(value);\n }\n if (value === null || value === undefined) {\n return '';\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue);\n }\n getView(value, options) {\n if (this.component.protected) {\n return '--- PROTECTED ---';\n }\n return this.getValueAsString(value, options);\n }\n updateItems(...args) {\n this.restoreValue();\n this.onChange(...args);\n }\n /**\n * @param {*} data\n * @param {boolean} [forceUseValue=false] - if true, return 'value' property of the data\n * @return {*}\n */\n itemValue(data, forceUseValue = false) {\n if (lodash_1.default.isObject(data) && !lodash_1.default.isArray(data)) {\n if (this.valueProperty) {\n return lodash_1.default.get(data, this.valueProperty);\n }\n if (forceUseValue) {\n return data.value;\n }\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item) ? this.itemValueForHTMLMode(item) : this.itemValue(item));\n return values.join(', ');\n }\n return this.itemValue(value);\n }\n createModal(element, attr, confirm) {\n const dialog = this.ce('div', attr || {});\n this.setContent(dialog, this.renderTemplate('dialog'));\n // Add refs to dialog, not \"this\".\n dialog.refs = {};\n this.loadRefs.call(dialog, dialog, {\n dialogOverlay: 'single',\n dialogContents: 'single',\n dialogClose: 'single',\n });\n dialog.refs.dialogContents.appendChild(element);\n document.body.appendChild(dialog);\n document.body.classList.add('modal-open');\n dialog.close = () => {\n document.body.classList.remove('modal-open');\n dialog.dispatchEvent(new CustomEvent('close'));\n };\n this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n const handleCloseClick = (e) => {\n if (confirm) {\n confirm().then(() => close(e))\n .catch(() => { });\n }\n else {\n close(e);\n }\n };\n this.addEventListener(dialog.refs.dialogOverlay, 'click', handleCloseClick);\n this.addEventListener(dialog.refs.dialogClose, 'click', handleCloseClick);\n return dialog;\n }\n get optimizeRedraw() {\n if (this.options.optimizeRedraw && this.element && !this.visible) {\n this.addClass(this.element, 'formio-removed');\n return true;\n }\n return false;\n }\n /**\n * Retrieves the CSS class name of this component.\n * @returns {string} - The class name of this component.\n */\n get className() {\n let className = this.hasInput ? `${this.transform('class', 'form-group')} has-feedback ` : '';\n className += `formio-component formio-component-${this.component.type} `;\n // TODO: find proper way to avoid overriding of default type-based component styles\n if (this.key && this.key !== 'form') {\n className += `formio-component-${this.key} `;\n }\n if (this.component.multiple) {\n className += 'formio-component-multiple ';\n }\n if (this.component.customClass) {\n className += this.component.customClass;\n }\n if (this.hasInput && this.component.validate && (0, utils_1.boolValue)(this.component.validate.required)) {\n className += ' required';\n }\n if (this.labelIsHidden()) {\n className += ' formio-component-label-hidden';\n }\n if (!this.visible) {\n className += ' formio-hidden';\n }\n return className;\n }\n /**\n * Build the custom style from the layout values\n * @return {string} - The custom style\n */\n get customStyle() {\n let customCSS = '';\n lodash_1.default.each(this.component.style, (value, key) => {\n if (value !== '') {\n customCSS += `${key}:${value};`;\n }\n });\n return customCSS;\n }\n static get serverConditionSettings() {\n return Component.conditionOperatorsSettings;\n }\n get isMobile() {\n return (0, ismobilejs_1.default)();\n }\n /**\n * Returns the outside wrapping element of this component.\n * @returns {HTMLElement}\n */\n getElement() {\n return this.element;\n }\n /**\n * Create an evaluation context for all script executions and interpolations.\n *\n * @param additional\n * @return {*}\n */\n evalContext(additional) {\n return super.evalContext(Object.assign({\n component: this.component,\n row: this.data,\n rowIndex: this.rowIndex,\n data: this.rootValue,\n iconClass: this.iconClass.bind(this),\n // Bind the translate function to the data context of any interpolated string.\n // It is useful to translate strings in different scenarions (eg: custom edit grid templates, custom error messages etc.)\n // and desirable to be publicly available rather than calling the internal {instance.t} function in the template string.\n t: this.t.bind(this),\n submission: (this.root ? this.root._submission : {\n data: this.rootValue\n }),\n form: this.root ? this.root._form : {},\n options: this.options,\n }, additional));\n }\n /**\n * Sets the pristine flag for this component.\n *\n * @param pristine {boolean} - TRUE to make pristine, FALSE not pristine.\n */\n setPristine(pristine) {\n this.pristine = pristine;\n }\n get isPristine() {\n return this.pristine;\n }\n setDirty(dirty) {\n this.dirty = dirty;\n }\n get isDirty() {\n return this.dirty;\n }\n /**\n * Removes a value out of the data array and rebuild the rows.\n * @param {number} index - The index of the data element to remove.\n */\n removeValue(index) {\n this.splice(index);\n this.redraw();\n this.restoreValue();\n this.triggerRootChange();\n }\n iconClass(name, spinning) {\n const iconset = this.options.iconset || Templates_1.default.current.defaultIconset || 'fa';\n return Templates_1.default.current.hasOwnProperty('iconClass')\n ? Templates_1.default.current.iconClass(iconset, name, spinning)\n : this.options.iconset === 'fa' ? Templates_1.default.defaultTemplates.iconClass(iconset, name, spinning) : name;\n }\n size(size) {\n return Templates_1.default.current.hasOwnProperty('size')\n ? Templates_1.default.current.size(size)\n : size;\n }\n /**\n * The readible name for this component.\n * @returns {string} - The name of the component.\n */\n get name() {\n return this.t(this.component.label || this.component.placeholder || this.key, { _userInput: true });\n }\n get visibleErrors() {\n return this._visibleErrors;\n }\n get errors() {\n return this._errors;\n }\n /**\n * Returns the error label for this component.\n * @return {*}\n */\n get errorLabel() {\n return this.t(this.component.errorLabel\n || this.component.label\n || this.component.placeholder\n || this.key);\n }\n /**\n * Get the error message provided a certain type of error.\n * @param type\n * @return {*}\n */\n errorMessage(type) {\n return (this.component.errors && this.component.errors[type]) ? this.component.errors[type] : type;\n }\n setContent(element, content, forceSanitize, sanitizeOptions) {\n if (element instanceof HTMLElement) {\n element.innerHTML = this.sanitize(content, forceSanitize, sanitizeOptions);\n return true;\n }\n return false;\n }\n restoreCaretPosition() {\n var _a, _b, _c;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.currentSelection) {\n if ((_b = this.refs.input) === null || _b === void 0 ? void 0 : _b.length) {\n const { selection, index } = this.root.currentSelection;\n let input = this.refs.input[index];\n const isInputRangeSelectable = (i) => /text|search|password|tel|url/i.test((i === null || i === void 0 ? void 0 : i.type) || '');\n if (input) {\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(...selection);\n }\n }\n else {\n input = this.refs.input[this.refs.input.length];\n const lastCharacter = ((_c = input.value) === null || _c === void 0 ? void 0 : _c.length) || 0;\n if (isInputRangeSelectable(input)) {\n input.setSelectionRange(lastCharacter, lastCharacter);\n }\n }\n }\n }\n }\n redraw() {\n // Don't bother if we have not built yet.\n if (!this.element || !this.element.parentNode || this.optimizeRedraw) {\n // Return a non-resolving promise.\n return Promise.resolve();\n }\n this.detach();\n this.emit('redraw');\n // Since we are going to replace the element, we need to know it's position so we can find it in the parent's children.\n const parent = this.element.parentNode;\n const index = Array.prototype.indexOf.call(parent.children, this.element);\n this.element.outerHTML = this.sanitize(this.render());\n this.setElement(parent.children[index]);\n return this.attach(this.element);\n }\n rebuild() {\n this.destroy();\n this.init();\n this.visible = this.conditionallyVisible(null, null);\n return this.redraw();\n }\n removeEventListeners() {\n super.removeEventListeners();\n this.tooltips.forEach(tooltip => tooltip.destroy());\n this.tooltips = [];\n }\n hasClass(element, className) {\n if (!element) {\n return;\n }\n return super.hasClass(element, this.transform('class', className));\n }\n addClass(element, className) {\n if (!element) {\n return;\n }\n return super.addClass(element, this.transform('class', className));\n }\n removeClass(element, className) {\n if (!element) {\n return;\n }\n return super.removeClass(element, this.transform('class', className));\n }\n /**\n * Determines if this component has a condition defined.\n *\n * @return {null}\n */\n hasCondition() {\n if (this._hasCondition !== null) {\n return this._hasCondition;\n }\n this._hasCondition = FormioUtils.hasCondition(this.component);\n return this._hasCondition;\n }\n /**\n * Check if this component is conditionally visible.\n *\n * @param data\n * @return {boolean}\n */\n conditionallyVisible(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n if (this.builderMode || this.previewMode || !this.hasCondition()) {\n return !this.component.hidden;\n }\n data = data || (this.root ? this.root.data : {});\n return this.checkCondition(row, data);\n }\n /**\n * Checks the condition of this component.\n *\n * TODO: Switch row and data parameters to be consistent with other methods.\n *\n * @param row - The row contextual data.\n * @param data - The global data object.\n * @return {boolean} - True if the condition applies to this component.\n */\n checkCondition(row, data) {\n return FormioUtils.checkCondition(this.component, row || this.data, data || this.rootValue, this.root ? this.root._form : {}, this);\n }\n /**\n * Check for conditionals and hide/show the element based on those conditions.\n */\n checkComponentConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n if (!this.builderMode & !this.previewMode && this.fieldLogic(data, row)) {\n this.redraw();\n }\n // Check advanced conditions\n const visible = this.conditionallyVisible(data, row);\n if (this.visible !== visible) {\n this.visible = visible;\n }\n return visible;\n }\n /**\n * Checks conditions for this component and any sub components.\n * @param args\n * @return {boolean}\n */\n checkConditions(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.checkComponentConditions(data, flags, row);\n }\n get logic() {\n return this.component.logic || [];\n }\n /**\n * Check all triggers and apply necessary actions.\n *\n * @param data\n */\n fieldLogic(data, row) {\n data = data || this.rootValue;\n row = row || this.data;\n const logics = this.logic;\n // If there aren't logic, don't go further.\n if (logics.length === 0) {\n return;\n }\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n let changed = logics.reduce((changed, logic) => {\n const result = FormioUtils.checkTrigger(newComponent, logic.trigger, row, data, this.root ? this.root._form : {}, this);\n return (result ? this.applyActions(newComponent, logic.actions, result, row, data) : false) || changed;\n }, false);\n // If component definition changed, replace and mark as changed.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n changed = true;\n const disabled = this.shouldDisabled;\n // Change disabled state if it has changed\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n }\n return changed;\n }\n isIE() {\n if (typeof window === 'undefined') {\n return false;\n }\n const userAgent = window.navigator.userAgent;\n const msie = userAgent.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);\n }\n const trident = userAgent.indexOf('Trident/');\n if (trident > 0) {\n // IE 11 => return version number\n const rv = userAgent.indexOf('rv:');\n return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);\n }\n const edge = userAgent.indexOf('Edge/');\n if (edge > 0) {\n // IE 12 (aka Edge) => return version number\n return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);\n }\n // other browser\n return false;\n }\n defineActionValue(action, argsObject) {\n return this.evaluate(action.value, argsObject, 'value');\n }\n applyActions(newComponent, actions, result, row, data) {\n data = data || this.rootValue;\n row = row || this.data;\n return actions.reduce((changed, action) => {\n switch (action.type) {\n case 'property': {\n FormioUtils.setActionProperty(newComponent, action, result, row, data, this);\n const property = action.property.value;\n if (!lodash_1.default.isEqual(lodash_1.default.get(this.component, property), lodash_1.default.get(newComponent, property))) {\n changed = true;\n }\n break;\n }\n case 'value': {\n const oldValue = this.getValue();\n const newValue = this.defineActionValue(action, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n component: newComponent,\n result,\n });\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n case 'mergeComponentSchema': {\n const schema = this.evaluate(action.schemaDefinition, {\n value: lodash_1.default.clone(this.getValue()),\n data,\n row,\n component: newComponent,\n result,\n }, 'schema');\n lodash_1.default.assign(newComponent, schema);\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n changed = true;\n }\n break;\n }\n case 'customAction': {\n const oldValue = this.getValue();\n const newValue = this.evaluate(action.customAction, {\n value: lodash_1.default.clone(oldValue),\n data,\n row,\n input: oldValue,\n component: newComponent,\n result,\n }, 'value');\n if (!lodash_1.default.isEqual(oldValue, newValue) && !(this.component.clearOnHide && !this.visible)) {\n this.setValue(newValue);\n if (this.viewOnly) {\n this.dataValue = newValue;\n }\n changed = true;\n }\n break;\n }\n }\n return changed;\n }, false);\n }\n // Deprecated\n addInputError(message, dirty, elements) {\n this.addMessages(message);\n this.setErrorClasses(elements, dirty, !!message);\n }\n // Deprecated\n removeInputError(elements) {\n this.setErrorClasses(elements, true, false);\n }\n /**\n * Add a new input error to this element.\n *\n * @param message\n * @param dirty\n */\n addMessages(messages) {\n if (!messages) {\n return;\n }\n // Standardize on array of objects for message.\n if (typeof messages === 'string') {\n messages = {\n messages,\n level: 'error',\n };\n }\n if (!Array.isArray(messages)) {\n messages = [messages];\n }\n messages = lodash_1.default.uniqBy(messages, message => message.message);\n if (this.refs.messageContainer) {\n this.setContent(this.refs.messageContainer, messages.map((message) => {\n if (message.message && typeof message.message === 'string') {\n message.message = message.message.replaceAll('<', '&lt;').replaceAll('>', '&gt;');\n }\n return this.renderTemplate('message', Object.assign({}, message));\n }).join(''));\n }\n }\n setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {\n this.clearErrorClasses();\n elements.forEach((element) => {\n this.setElementInvalid(this.performInputMapping(element), false);\n });\n this.setInputWidgetErrorClasses(elements, hasErrors);\n // do not set error classes for hidden components\n if (!this.visible) {\n return;\n }\n if (hasErrors) {\n // Add error classes\n elements.forEach((input) => {\n this.setElementInvalid(this.performInputMapping(input), true);\n });\n if (dirty && this.options.highlightErrors) {\n this.addClass(element, this.options.componentErrorClass);\n }\n else {\n this.addClass(element, 'has-error');\n }\n }\n if (hasMessages) {\n this.addClass(element, 'has-message');\n }\n }\n setElementInvalid(element, invalid) {\n if (!element)\n return;\n if (invalid) {\n this.addClass(element, 'is-invalid');\n }\n else {\n this.removeClass(element, 'is-invalid');\n }\n element.setAttribute('aria-invalid', invalid ? 'true' : 'false');\n }\n clearOnHide() {\n // clearOnHide defaults to true for old forms (without the value set) so only trigger if the value is false.\n if (\n // if change happens inside EditGrid's row, it doesn't trigger change on the root level, so rootPristine will be true\n (!this.rootPristine || this.options.server || (0, utils_1.isInsideScopingComponent)(this)) &&\n this.component.clearOnHide !== false &&\n !this.options.readOnly &&\n !this.options.showHiddenFields) {\n if (!this.visible) {\n this.deleteValue();\n }\n else if (!this.hasValue() && this.shouldAddDefaultValue) {\n // If shown, ensure the default is set.\n this.setValue(this.defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n }\n triggerRootChange(...args) {\n if (this.options.onChange) {\n this.options.onChange(...args);\n }\n else if (this.root && this.root.triggerChange) {\n this.root.triggerChange(...args);\n }\n }\n onChange(flags, fromRoot) {\n flags = flags || {};\n if (flags.modified) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n this.addClass(this.getElement(), 'formio-modified');\n }\n // If we are supposed to validate on blur, then don't trigger validation yet.\n if (this.component.validateOn === 'blur') {\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 *\n * @return {null}\n */\n get emptyValue() {\n return null;\n }\n /**\n * Returns if this component has a value set.\n *\n */\n hasValue(data) {\n return !lodash_1.default.isUndefined(lodash_1.default.get(data || this.data, this.key));\n }\n /**\n * Get the data value at the root level.\n *\n * @return {*}\n */\n get rootValue() {\n return this.root ? this.root.data : this.data;\n }\n get rootPristine() {\n return lodash_1.default.get(this, 'root.pristine', false);\n }\n /**\n * Get the static value of this component.\n * @return {*}\n */\n get dataValue() {\n if (!this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return this.emptyValue;\n }\n if (!this.hasValue() && this.shouldAddDefaultValue) {\n const empty = this.component.multiple ? [] : this.emptyValue;\n if (!this.rootPristine) {\n this.dataValue = empty;\n }\n return empty;\n }\n return lodash_1.default.get(this._data, this.key);\n }\n /**\n * Sets the static value of this component.\n *\n * @param value\n */\n set dataValue(value) {\n if (!this.allowData ||\n !this.key ||\n (!this.visible && this.component.clearOnHide && !this.rootPristine)) {\n return;\n }\n if ((value !== null) && (value !== undefined)) {\n value = this.hook('setDataValue', value, this.key, this._data);\n }\n if ((value === null) || (value === undefined)) {\n this.unset();\n return;\n }\n lodash_1.default.set(this._data, this.key, value);\n return;\n }\n /**\n * Splice a value from the dataValue.\n *\n * @param index\n */\n splice(index, flags = {}) {\n if (this.hasValue()) {\n const dataValue = this.dataValue || [];\n if (lodash_1.default.isArray(dataValue) && dataValue.hasOwnProperty(index)) {\n dataValue.splice(index, 1);\n this.dataValue = dataValue;\n this.triggerChange(flags);\n }\n }\n }\n unset() {\n lodash_1.default.unset(this._data, this.key);\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n getCustomDefaultValue(defaultValue) {\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n get shouldAddDefaultValue() {\n return !this.options.noDefaults || (this.component.defaultValue && !this.isEmpty(this.component.defaultValue)) || this.component.customDefaultValue;\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (this.component.defaultValue) {\n defaultValue = this.component.defaultValue;\n }\n defaultValue = this.getCustomDefaultValue(defaultValue);\n const checkMask = (value) => {\n if (typeof value === 'string') {\n if (this.component.type !== 'textfield') {\n const placeholderChar = this.placeholderChar;\n value = (0, vanilla_text_mask_1.conformToMask)(value, this.defaultMask, { placeholderChar }).conformedValue;\n if (!FormioUtils.matchInputMask(value, this.defaultMask)) {\n value = '';\n }\n }\n }\n else {\n value = '';\n }\n return value;\n };\n if (this.defaultMask) {\n if (Array.isArray(defaultValue)) {\n defaultValue = defaultValue.map(checkMask);\n }\n else {\n defaultValue = checkMask(defaultValue);\n }\n }\n // Clone so that it creates a new instance.\n return lodash_1.default.cloneDeep(defaultValue);\n }\n /**\n * Get the input value of this component.\n *\n * @return {*}\n */\n getValue() {\n if (!this.hasInput || this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const values = [];\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n if (!this.component.multiple) {\n return this.getValueAt(i);\n }\n values.push(this.getValueAt(i));\n }\n }\n if (values.length === 0 && !this.component.multiple) {\n return '';\n }\n return values;\n }\n /**\n * Get the value at a specific index.\n *\n * @param index\n * @returns {*}\n */\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n return input ? input.value : undefined;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n *\n * @return {boolean} - If the value changed.\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (!this.hasInput) {\n return changed;\n }\n const isArray = Array.isArray(value);\n const valueInput = this.refs.fileLink || this.refs.input;\n if (isArray &&\n Array.isArray(this.defaultValue) &&\n this.refs.hasOwnProperty('input') &&\n valueInput &&\n (valueInput.length !== value.length) &&\n this.visible) {\n this.redraw();\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.redraw();\n return changed;\n }\n for (const i in this.refs.input) {\n if (this.refs.input.hasOwnProperty(i)) {\n this.setValueAt(i, isArray ? value[i] : value, flags);\n }\n }\n return changed;\n }\n /**\n * Set the value at a specific index.\n *\n * @param index\n * @param value\n */\n setValueAt(index, value, flags = {}) {\n if (!flags.noDefault && (value === null || value === undefined) && !this.component.multiple) {\n value = this.defaultValue;\n }\n const input = this.performInputMapping(this.refs.input[index]);\n const valueMaskInput = this.refs.valueMaskInput;\n if ((valueMaskInput === null || valueMaskInput === void 0 ? void 0 : valueMaskInput.mask) && valueMaskInput.mask.textMaskInputElement) {\n valueMaskInput.mask.textMaskInputElement.update(value);\n }\n if (input.mask && input.mask.textMaskInputElement) {\n input.mask.textMaskInputElement.update(value);\n }\n else if (input.widget && input.widget.setValue) {\n input.widget.setValue(value);\n }\n else {\n input.value = value;\n }\n }\n get hasSetValue() {\n return this.hasValue() && !this.isEmpty(this.dataValue);\n }\n setDefaultValue() {\n if (this.defaultValue && this.shouldAddDefaultValue) {\n const defaultValue = (this.component.multiple && !this.dataValue.length) ? [] : this.defaultValue;\n this.setValue(defaultValue, {\n noUpdateEvent: true\n });\n }\n }\n /**\n * Restore the value of a control.\n */\n restoreValue() {\n if (this.hasSetValue) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else {\n this.setDefaultValue();\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && !Array.isArray(value)) {\n value = value ? [value] : [];\n }\n return value;\n }\n /**\n * Update a value of this component.\n *\n * @param flags\n */\n updateComponentValue(value, flags = {}) {\n let newValue = (!flags.resetValue && (value === undefined || value === null)) ? this.getValue() : value;\n newValue = this.normalizeValue(newValue, flags);\n const oldValue = this.dataValue;\n let changed = ((newValue !== undefined) ? this.hasChanged(newValue, oldValue) : false);\n if (changed) {\n this.dataValue = newValue;\n changed = this.dataValue !== oldValue;\n this.updateOnChange(flags, changed);\n }\n if (this.componentModal && flags && flags.fromSubmission) {\n this.componentModal.setValue(value);\n }\n return changed;\n }\n /**\n * Updates the value of this component plus all sub-components.\n *\n * @param args\n * @return {boolean}\n */\n updateValue(...args) {\n return this.updateComponentValue(...args);\n }\n getIcon(name, content, styles, ref = 'icon') {\n return this.renderTemplate('icon', {\n className: this.iconClass(name),\n ref,\n styles,\n content\n });\n }\n /**\n * Resets the value of this component.\n */\n resetValue() {\n this.unset();\n this.setValue(this.emptyValue, {\n noUpdateEvent: true,\n noValidate: true,\n resetValue: true\n });\n }\n /**\n * Determine if the value of this component has changed.\n *\n * @param newValue\n * @param oldValue\n * @return {boolean}\n */\n hasChanged(newValue, oldValue) {\n if (((newValue === undefined) || (newValue === null)) &&\n ((oldValue === undefined) || (oldValue === null) || this.isEmpty(oldValue))) {\n return false;\n }\n // If we do not have a value and are getting set to anything other than undefined or null, then we changed.\n if (newValue !== undefined &&\n newValue !== null &&\n this.allowData &&\n !this.hasValue()) {\n return true;\n }\n return !lodash_1.default.isEqual(newValue, oldValue);\n }\n /**\n * Update the value on change.\n *\n * @param flags\n */\n updateOnChange(flags = {}, changed = false) {\n if (!flags.noUpdateEvent && changed) {\n 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 /**\n * Perform a calculated value operation.\n *\n * @param data - The global data object.\n *\n * @return {boolean} - If the value changed during calculation.\n */\n convertNumberOrBoolToString(value) {\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value.toString();\n }\n return value;\n }\n doValueCalculation(dataValue, data, row) {\n var _a;\n return this.evaluate(this.component.calculateValue, {\n value: dataValue,\n data,\n row: row || this.data,\n submission: ((_a = this.root) === null || _a === void 0 ? void 0 : _a._submission) || {\n data: this.rootValue\n }\n }, 'value');\n }\n /* eslint-disable max-statements */\n calculateComponentValue(data, flags, row) {\n // Skip value calculation for the component if we don't have entire form data set or in builder mode\n if (this.builderMode || lodash_1.default.isUndefined(lodash_1.default.get(this, 'root.data'))) {\n return false;\n }\n // If no calculated value or\n // hidden and set to clearOnHide (Don't calculate a value for a hidden field set to clear when hidden)\n const { clearOnHide } = this.component;\n const shouldBeCleared = !this.visible && clearOnHide;\n const allowOverride = lodash_1.default.get(this.component, 'allowCalculateOverride', false);\n if (shouldBeCleared) {\n // remove calculated value so that the value is recalculated once component becomes visible\n if (this.hasOwnProperty('calculatedValue') && allowOverride) {\n lodash_1.default.unset(this, 'calculatedValue');\n }\n return false;\n }\n // Handle all cases when calculated values should not fire.\n if ((this.options.readOnly && !this.options.pdf && !this.component.calculateValue) ||\n !(this.component.calculateValue || this.component.calculateValueVariable) ||\n (this.options.server && !this.component.calculateServer) ||\n (flags.dataSourceInitialLoading && allowOverride)) {\n return false;\n }\n const dataValue = this.dataValue;\n // Calculate the new value.\n let calculatedValue = this.doValueCalculation(dataValue, data, row, flags);\n if (this.options.readOnly && dataValue && !calculatedValue) {\n return false;\n }\n if (lodash_1.default.isNil(calculatedValue)) {\n calculatedValue = this.emptyValue;\n }\n const changed = !lodash_1.default.isEqual(dataValue, calculatedValue);\n // Do not override calculations on server if they have calculateServer set.\n if (allowOverride) {\n // The value is considered locked if it is not empty and comes from a submission value.\n const fromSubmission = (flags.fromSubmission && this.component.persistent === true);\n if (this.isEmpty(dataValue)) {\n // Reset the calculation lock if ever the data is cleared.\n this.calculationLocked = false;\n }\n else if (this.calculationLocked || fromSubmission) {\n this.calculationLocked = true;\n return false;\n }\n const firstPass = (this.calculatedValue === undefined) || flags.resetValue;\n if (firstPass) {\n this.calculatedValue = null;\n }\n const newCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(calculatedValue));\n const previousCalculatedValue = this.normalizeValue(this.convertNumberOrBoolToString(this.calculatedValue));\n const normalizedDataValue = this.normalizeValue(this.convertNumberOrBoolToString(dataValue));\n const calculationChanged = !lodash_1.default.isEqual(previousCalculatedValue, newCalculatedValue);\n const previousChanged = !lodash_1.default.isEqual(normalizedDataValue, previousCalculatedValue);\n if (calculationChanged && previousChanged && !firstPass) {\n return false;\n }\n // Check to ensure that the calculated value is different than the previously calculated value.\n if (previousCalculatedValue && previousChanged && !calculationChanged) {\n this.calculatedValue = null;\n return false;\n }\n if (flags.isReordered || !calculationChanged) {\n return false;\n }\n if (fromSubmission) {\n // If we set value from submission and it differs from calculated one, set the calculated value to prevent overriding dataValue in the next pass\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n return false;\n }\n // If this is the firstPass, and the dataValue is different than to the calculatedValue.\n if (firstPass && !this.isEmpty(dataValue) && changed && calculationChanged) {\n // Return that we have a change so it will perform another pass.\n return true;\n }\n }\n this.calculatedValue = (0, utils_1.fastCloneDeep)(calculatedValue);\n if (changed) {\n if (!flags.noPristineChangeOnModified) {\n this.pristine = false;\n }\n flags.triggeredComponentId = this.id;\n return this.setValue(calculatedValue, flags);\n }\n return false;\n }\n /* eslint-enable max-statements */\n /**\n * Performs calculations in this component plus any child components.\n *\n * @param args\n * @return {boolean}\n */\n calculateValue(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n return this.calculateComponentValue(data, flags, row);\n }\n /**\n * Get this component's label text.\n *\n */\n get label() {\n return this.component.label;\n }\n /**\n * Set this component's label text and render it.\n *\n * @param value - The new label text.\n */\n set label(value) {\n this.component.label = value;\n if (this.labelElement) {\n this.labelElement.innerText = value;\n }\n }\n /**\n * Get FormioForm element at the root of this component tree.\n *\n */\n getRoot() {\n return this.root;\n }\n /**\n * Returns the invalid message, or empty string if the component is valid.\n *\n * @param data\n * @param dirty\n * @return {*}\n */\n invalidMessage(data, dirty, ignoreCondition, row) {\n if (!ignoreCondition && !this.checkCondition(row, data)) {\n return '';\n }\n // See if this is forced invalid.\n if (this.invalid) {\n return this.invalid;\n }\n // No need to check for errors if there is no input or if it is pristine.\n if (!this.hasInput || (!dirty && this.pristine)) {\n return '';\n }\n 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 *\n * @param data\n * @param dirty\n * @return {boolean}\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 {*} errors\n * @returns\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\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\n */\n validateComponent(data, row, 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 *\n * @param data\n * @param dirty\n * @param row\n * @return {boolean}\n */\n checkComponentValidity(data, dirty, row, 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) => err.component.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) => err.component.key === this.component.key);\n }\n }\n return errors.length === 0;\n }\n }\n /**\n * Checks the validity of the component.\n * @param {*} data\n * @param {*} dirty\n * @param {*} row\n * @param {*} silentCheck\n * @returns\n */\n checkValidity(data, dirty, row, silentCheck, errors = []) {\n data = data || this.rootValue;\n row = row || this.data;\n console.log('Deprecation warning: Component.checkValidity() will be deprecated in 6.x version of renderer. Use Component.validateComponent instead.');\n return this.checkComponentValidity(data, dirty, row, { silentCheck }, errors);\n }\n checkAsyncValidity(data, dirty, row, silentCheck, errors = []) {\n console.log('Deprecation warning: Component.checkAsyncValidity() will be deprecated in 6.x version of renderer. Use Component.validateComponent instead.');\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 *\n * @param data - The root data of the change event.\n * @param flags - The flags from this change event.\n *\n * @return boolean - If component is valid or not.\n */\n checkData(data, flags, row) {\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n // Needs for Nextgen Rules Engine\n this.resetCaches();\n // Do not trigger refresh if change was triggered on blur event since components with Refresh on Blur have their own listeners\n if (!flags.fromBlur) {\n this.checkRefreshOn(flags.changes, flags);\n }\n if (flags.noCheck) {\n return true;\n }\n this.checkComponentConditions(data, flags, row);\n if (this.id !== flags.triggeredComponentId) {\n this.calculateComponentValue(data, flags, row);\n }\n }\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 *\n * @return {boolean}\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 *\n * @return {boolean|*}\n */\n isValueHidden() {\n if (this.component.protected && this.root.editing) {\n return false;\n }\n if (!this.root || !this.root.hasOwnProperty('editing')) {\n return false;\n }\n if (!this.root || !this.root.editing) {\n return false;\n }\n return (this.component.protected || !this.component.persistent || (this.component.persistent === 'client-only'));\n }\n shouldSkipValidation(data, 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 */\n asString(value) {\n value = value || this.getValue();\n return (Array.isArray(value) ? value : [value]).map(lodash_1.default.toString).join(', ');\n }\n /**\n * Return if the component is disabled.\n * @return {boolean}\n */\n get disabled() {\n return this._disabled || this.parentDisabled;\n }\n /**\n * Disable this component.\n *\n * @param {boolean} disabled\n */\n set disabled(disabled) {\n this._disabled = disabled;\n }\n setDisabled(element, disabled) {\n if (!element) {\n return;\n }\n element.disabled = disabled;\n if (disabled) {\n element.setAttribute('disabled', 'disabled');\n }\n else {\n element.removeAttribute('disabled');\n }\n }\n setLoading(element, loading) {\n if (!element || (element.loading === loading)) {\n return;\n }\n element.loading = loading;\n if (!element.loader && loading) {\n element.loader = this.ce('i', {\n class: `${this.iconClass('refresh', true)} button-icon-right`\n });\n }\n if (element.loader) {\n if (loading) {\n this.appendTo(element.loader, element);\n }\n else {\n this.removeChildFrom(element.loader, element);\n }\n }\n }\n selectOptions(select, tag, options, defaultValue) {\n lodash_1.default.each(options, (option) => {\n const attrs = {\n value: option.value\n };\n if (defaultValue !== undefined && (option.value === defaultValue)) {\n attrs.selected = 'selected';\n }\n const optionElement = this.ce('option', attrs);\n optionElement.appendChild(this.text(option.label));\n select.appendChild(optionElement);\n });\n }\n setSelectValue(select, value) {\n const options = select.querySelectorAll('option');\n lodash_1.default.each(options, (option) => {\n if (option.value === value) {\n option.setAttribute('selected', 'selected');\n }\n else {\n option.removeAttribute('selected');\n }\n });\n if (select.onchange) {\n select.onchange();\n }\n if (select.onselect) {\n select.onselect();\n }\n }\n getRelativePath(path) {\n const keyPart = `.${this.key}`;\n const thisPath = this.isInputComponent ? this.path\n : this.path.slice(0).replace(keyPart, '');\n return path.replace(thisPath, '');\n }\n clear() {\n this.detach();\n this.empty(this.getElement());\n }\n append(element) {\n this.appendTo(element, this.element);\n }\n prepend(element) {\n this.prependTo(element, this.element);\n }\n removeChild(element) {\n this.removeChildFrom(element, this.element);\n }\n detachLogic() {\n this.logic.forEach(logic => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.off(event); // only applies to callbacks on this component\n }\n });\n }\n attachLogic() {\n // Do not attach logic during builder mode.\n if (this.builderMode) {\n return;\n }\n this.logic.forEach((logic) => {\n if (logic.trigger.type === 'event') {\n const event = this.interpolate(logic.trigger.event);\n this.on(event, (...args) => {\n const newComponent = (0, utils_1.fastCloneDeep)(this.originalComponent);\n if (this.applyActions(newComponent, logic.actions, args)) {\n // If component definition changed, replace it.\n if (!lodash_1.default.isEqual(this.component, newComponent)) {\n this.component = newComponent;\n const visible = this.conditionallyVisible(null, null);\n const disabled = this.shouldDisabled;\n // Change states which won't be recalculated during redrawing\n if (this.visible !== visible) {\n this.visible = visible;\n }\n if (this.disabled !== disabled) {\n this.disabled = disabled;\n }\n this.redraw();\n }\n }\n }, true);\n }\n });\n }\n /**\n * Get the element information.\n */\n elementInfo() {\n const attributes = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.component.placeholder) {\n attributes.placeholder = this.t(this.component.placeholder, { _userInput: true });\n }\n if (this.component.tabindex) {\n attributes.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attributes.disabled = 'disabled';\n }\n lodash_1.default.defaults(attributes, this.component.attributes);\n return {\n type: 'input',\n component: this.component,\n changeEvent: 'change',\n attr: attributes\n };\n }\n autofocus() {\n const hasAutofocus = this.component.autofocus && !this.builderMode && !this.options.preview;\n if (hasAutofocus) {\n this.on('render', () => this.focus(), true);\n }\n }\n scrollIntoView(element = this.element) {\n if (!element) {\n return;\n }\n const { left, top } = element.getBoundingClientRect();\n window.scrollTo(left + window.scrollX, top + window.scrollY);\n }\n focus(index) {\n var _a, _b;\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if ((_a = this.refs.input) === null || _a === void 0 ? void 0 : _a.length) {\n const focusingInput = typeof index === 'number' && this.refs.input[index]\n ? this.refs.input[index]\n : this.refs.input[this.refs.input.length - 1];\n if (((_b = this.component.widget) === null || _b === void 0 ? void 0 : _b.type) === 'calendar') {\n const sibling = focusingInput.nextSibling;\n if (sibling) {\n sibling.focus();\n }\n }\n else {\n focusingInput.focus();\n }\n }\n if (this.refs.openModal) {\n this.refs.openModal.focus();\n }\n if (this.parent.refs.openModal) {\n this.parent.refs.openModal.focus();\n }\n }\n /**\n * Get `Formio` instance for working with files\n */\n get fileService() {\n if (this.options.fileService) {\n return this.options.fileService;\n }\n if (this.options.formio) {\n return this.options.formio;\n }\n if (this.root && this.root.formio) {\n return this.root.formio;\n }\n const formio = new Formio_1.Formio();\n // If a form is loaded, then make sure to set the correct formUrl.\n if (this.root && this.root._form && this.root._form._id) {\n formio.formUrl = `${formio.projectUrl}/form/${this.root._form._id}`;\n }\n return formio;\n }\n resetCaches() { }\n get previewMode() {\n return false;\n }\n}\nexports[\"default\"] = Component;\nComponent.externalLibraries = {};\nComponent.requireLibrary = function (name, property, src, polling) {\n if (!Component.externalLibraries.hasOwnProperty(name)) {\n Component.externalLibraries[name] = {};\n Component.externalLibraries[name].ready = new Promise((resolve, reject) => {\n Component.externalLibraries[name].resolve = resolve;\n Component.externalLibraries[name].reject = reject;\n });\n const callbackName = `${name}Callback`;\n if (!polling && !window[callbackName]) {\n window[callbackName] = function () {\n this.resolve();\n }.bind(Component.externalLibraries[name]);\n }\n // See if the plugin already exists.\n const plugin = (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?");
5689
5699
 
5690
5700
  /***/ }),
5691
5701
 
@@ -5806,7 +5816,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5806
5816
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5807
5817
 
5808
5818
  "use strict";
5809
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Multivalue_1 = __importDefault(__webpack_require__(/*! ../multivalue/Multivalue */ \"./lib/cjs/components/_classes/multivalue/Multivalue.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass Input extends Multivalue_1.default {\n constructor(component, options, data) {\n super(component, options, data);\n this.triggerUpdateValueAt = lodash_1.default.debounce(this.updateValueAt.bind(this), 100);\n }\n static schema(...extend) {\n return Multivalue_1.default.schema({\n widget: {\n type: 'input'\n }\n }, ...extend);\n }\n get inputInfo() {\n const attr = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.options.attachMode === 'builder' || this.options.building || lodash_1.default.get(this.root, 'form.settings.disableAutocomplete')) {\n attr.autocomplete = this.autocompleteDisableAttrName;\n }\n if (this.component.inputMode) {\n attr.inputmode = this.component.inputMode;\n }\n if (this.component.placeholder) {\n attr.placeholder = this.getFormattedAttribute(this.component.placeholder);\n }\n if (this.component.tabindex) {\n attr.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attr.disabled = 'disabled';\n }\n if (this.component.autocomplete) {\n attr.autocomplete = this.component.autocomplete;\n }\n lodash_1.default.defaults(attr, this.component.attributes);\n return {\n id: this.key,\n type: 'input',\n changeEvent: 'input',\n content: '',\n attr\n };\n }\n get autocompleteDisableAttrName() {\n return 'off';\n }\n get maskOptions() {\n return lodash_1.default.map(this.component.inputMasks, mask => {\n return {\n label: mask.label,\n value: mask.label\n };\n });\n }\n get isMultipleMasksField() {\n return this.component.allowMultipleMasks && !!this.component.inputMasks && !!this.component.inputMasks.length;\n }\n getMaskByName(maskName) {\n const inputMask = lodash_1.default.find(this.component.inputMasks, (inputMask) => {\n return inputMask.label === maskName;\n });\n return inputMask ? inputMask.mask : undefined;\n }\n setInputMask(input, inputMask) {\n const mask = inputMask || this.component.displayMask || this.component.inputMask;\n return super.setInputMask(input, mask, !this.component.placeholder);\n }\n getMaskOptions() {\n return this.component.inputMasks\n .map(mask => ({\n label: mask.label,\n value: mask.label,\n }));\n }\n getWordCount(value) {\n return !value ? 0 : value.trim().split(/\\s+/).length;\n }\n get remainingWords() {\n const maxWords = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxWords'), 10);\n const wordCount = this.getWordCount(this.dataValue);\n return maxWords - wordCount;\n }\n get prefix() {\n return this.component.prefix;\n }\n get suffix() {\n if (this.component.widget && this.component.widget.type === 'calendar') {\n const calendarIcon = this.renderTemplate('icon', {\n ref: 'icon',\n // After font-awesome would be updated to v5.x, \"clock-o\" should be replaced with \"clock\"\n className: this.iconClass(this.component.enableDate || this.component.widget.enableDate ? 'calendar' : 'clock-o'),\n styles: '',\n content: ''\n }).trim();\n if (this.component.prefix !== calendarIcon) {\n // converting string to HTML markup to render correctly DateTime component in portal.form.io\n return (0, utils_1.convertStringToHTMLElement)(calendarIcon, `[${this._referenceAttributeName}=\"icon\"]`);\n }\n }\n return this.component.suffix;\n }\n renderElement(value, index) {\n // Double quotes cause the input value to close so replace them with html quote char.\n if (value && typeof value === 'string') {\n value = value.replace(/\"/g, '&quot;');\n }\n const info = this.inputInfo;\n info.attr = info.attr || {};\n info.attr.value = this.getValueAsString(this.formatValue(this.parseValue(value)))\n .replace(/\"/g, '&quot;');\n const valueMask = this.component.inputMask;\n const displayMask = this.component.displayMask;\n const hasDifferentDisplayAndSaveFormats = valueMask && displayMask && valueMask !== displayMask;\n if (this.isMultipleMasksField) {\n info.attr.class += ' formio-multiple-mask-input';\n }\n return this.isMultipleMasksField\n ? this.renderTemplate('multipleMasksInput', {\n input: info,\n value,\n index,\n selectOptions: this.getMaskOptions() || [],\n }, this.isHtmlRenderMode() ? 'html' : null)\n : this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: info,\n value: this.formatValue(this.parseValue(value)),\n hasValueMaskInput: hasDifferentDisplayAndSaveFormats,\n index\n }, this.isHtmlRenderMode() ? 'html' : null);\n }\n setCounter(type, element, count, max) {\n if (max) {\n const remaining = max - count;\n if (remaining > 0) {\n this.removeClass(element, 'text-danger');\n }\n else {\n this.addClass(element, 'text-danger');\n }\n this.setContent(element, this.t(`{{ remaining }} ${type} remaining.`, {\n remaining: remaining\n }));\n }\n else {\n this.setContent(element, this.t(`{{ count }} ${type}`, {\n count: count\n }));\n }\n }\n updateValueAt(value, flags, index) {\n flags = flags || {};\n if (lodash_1.default.get(this.component, 'showWordCount', false)) {\n if (this.refs.wordcount && this.refs.wordcount[index]) {\n const maxWords = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxWords', 0), 10);\n this.setCounter(this.t('words'), this.refs.wordcount[index], this.getWordCount(value), maxWords);\n }\n }\n if (lodash_1.default.get(this.component, 'showCharCount', false)) {\n if (this.refs.charcount && this.refs.charcount[index]) {\n const maxChars = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxLength', 0), 10);\n this.setCounter(this.t('characters'), this.refs.charcount[index], value.length, maxChars);\n }\n }\n }\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n if (input && input.widget) {\n return input.widget.getValue();\n }\n return input ? input.value : undefined;\n }\n updateValue(value, flags, index) {\n flags = flags || {};\n const changed = super.updateValue(value, flags);\n this.triggerUpdateValueAt(this.dataValue, flags, index);\n return changed;\n }\n parseValue(value) {\n return value;\n }\n formatValue(value) {\n return value;\n }\n attach(element) {\n this.loadRefs(element, {\n charcount: 'multiple',\n wordcount: 'multiple',\n prefix: 'multiple',\n suffix: 'multiple'\n });\n return super.attach(element);\n }\n getWidget(index) {\n index = index || 0;\n if (this.refs.input && this.refs.input[index]) {\n return this.refs.input[index].widget;\n }\n return null;\n }\n attachElement(element, index) {\n super.attachElement(element, index);\n if (element.widget) {\n element.widget.destroy();\n }\n // Attach the widget.\n let promise = Promise.resolve();\n element.widget = this.createWidget(index);\n if (element.widget) {\n promise = element.widget.attach(element);\n if (this.refs.prefix && this.refs.prefix[index]) {\n element.widget.addPrefix(this.refs.prefix[index]);\n }\n if (this.refs.suffix && this.refs.suffix[index]) {\n element.widget.addSuffix(this.refs.suffix[index]);\n }\n }\n // Add focus and blur events.\n this.addFocusBlurEvents(element);\n if (this.options.submitOnEnter) {\n this.addEventListener(element, 'keypress', (event) => {\n const key = event.keyCode || event.which;\n if (key === 13) {\n event.preventDefault();\n event.stopPropagation();\n this.emit('submitButton');\n }\n });\n }\n return promise;\n }\n /**\n * Creates an instance of a widget for this component.\n *\n * @return {null}\n */\n createWidget(index) {\n var _a, _b;\n // Return null if no widget is found.\n if (!this.component.widget) {\n return null;\n }\n // Get the widget settings.\n const settings = (typeof this.component.widget === 'string') ? {\n type: this.component.widget\n } : this.component.widget;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot) {\n settings.shadowRoot = (_b = this.root) === null || _b === void 0 ? void 0 : _b.shadowRoot;\n }\n // Make sure we have a widget.\n if (!widgets_1.default.hasOwnProperty(settings.type)) {\n return null;\n }\n // Create the widget.\n const widget = new widgets_1.default[settings.type](settings, this.component, this, index);\n widget.on('update', () => this.updateValue(this.getValue(), {\n modified: true\n }, index), true);\n widget.on('redraw', () => this.redraw(), true);\n return widget;\n }\n detach() {\n super.detach();\n if (this.refs && this.refs.input) {\n for (let i = 0; i <= this.refs.input.length; i++) {\n const widget = this.getWidget(i);\n if (widget) {\n widget.destroy();\n }\n }\n }\n this.refs.input = [];\n }\n}\nexports[\"default\"] = Input;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/input/Input.js?");
5819
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Multivalue_1 = __importDefault(__webpack_require__(/*! ../multivalue/Multivalue */ \"./lib/cjs/components/_classes/multivalue/Multivalue.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst widgets_1 = __importDefault(__webpack_require__(/*! ../../../widgets */ \"./lib/cjs/widgets/index.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nclass Input extends Multivalue_1.default {\n constructor(component, options, data) {\n super(component, options, data);\n this.triggerUpdateValueAt = lodash_1.default.debounce(this.updateValueAt.bind(this), 100);\n }\n static schema(...extend) {\n return Multivalue_1.default.schema({\n widget: {\n type: 'input'\n }\n }, ...extend);\n }\n get inputInfo() {\n const attr = {\n name: this.options.name,\n type: this.component.inputType || 'text',\n class: 'form-control',\n lang: this.options.language\n };\n if (this.options.attachMode === 'builder' || this.options.building || lodash_1.default.get(this.root, 'form.settings.disableAutocomplete')) {\n attr.autocomplete = this.autocompleteDisableAttrName;\n }\n if (this.component.inputMode) {\n attr.inputmode = this.component.inputMode;\n }\n if (this.component.placeholder) {\n attr.placeholder = this.getFormattedAttribute(this.component.placeholder);\n }\n if (this.component.tabindex) {\n attr.tabindex = this.component.tabindex;\n }\n if (this.disabled) {\n attr.disabled = 'disabled';\n }\n if (this.component.autocomplete) {\n attr.autocomplete = this.component.autocomplete;\n }\n lodash_1.default.defaults(attr, this.component.attributes);\n return {\n id: this.key,\n type: 'input',\n changeEvent: 'input',\n content: '',\n attr\n };\n }\n get autocompleteDisableAttrName() {\n return 'off';\n }\n get maskOptions() {\n return lodash_1.default.map(this.component.inputMasks, mask => {\n return {\n label: mask.label,\n value: mask.label\n };\n });\n }\n get isMultipleMasksField() {\n return this.component.allowMultipleMasks && !!this.component.inputMasks && !!this.component.inputMasks.length;\n }\n getMaskByName(maskName) {\n const inputMask = lodash_1.default.find(this.component.inputMasks, (inputMask) => {\n return inputMask.label === maskName;\n });\n return inputMask ? inputMask.mask : undefined;\n }\n setInputMask(input, inputMask) {\n const mask = inputMask || this.component.displayMask || this.component.inputMask;\n return super.setInputMask(input, mask, !this.component.placeholder);\n }\n getMaskOptions() {\n return this.component.inputMasks\n .map(mask => ({\n label: mask.label,\n value: mask.label,\n }));\n }\n getWordCount(value) {\n return !value ? 0 : value.trim().split(/\\s+/).length;\n }\n get remainingWords() {\n const maxWords = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxWords'), 10);\n const wordCount = this.getWordCount(this.dataValue);\n return maxWords - wordCount;\n }\n get prefix() {\n return this.component.prefix;\n }\n get suffix() {\n if (this.component.widget && this.component.widget.type === 'calendar') {\n const calendarIcon = this.renderTemplate('icon', {\n ref: 'icon',\n // After font-awesome would be updated to v5.x, \"clock-o\" should be replaced with \"clock\"\n className: this.iconClass(this.component.enableDate || this.component.widget.enableDate ? 'calendar' : 'clock-o'),\n styles: '',\n content: ''\n }).trim();\n if (this.component.prefix !== calendarIcon) {\n // converting string to HTML markup to render correctly DateTime component in portal.form.io\n return (0, utils_1.convertStringToHTMLElement)(calendarIcon, `[${this._referenceAttributeName}=\"icon\"]`);\n }\n }\n return this.component.suffix;\n }\n renderElement(value, index) {\n // Double quotes cause the input value to close so replace them with html quote char.\n if (value && typeof value === 'string') {\n value = value.replace(/\"/g, '&quot;');\n }\n const info = this.inputInfo;\n info.attr = info.attr || {};\n info.attr.value = this.getValueAsString(this.formatValue(this.parseValue(value)))\n .replace(/\"/g, '&quot;');\n const valueMask = this.component.inputMask;\n const displayMask = this.component.displayMask;\n const hasDifferentDisplayAndSaveFormats = valueMask && displayMask && valueMask !== displayMask;\n if (this.isMultipleMasksField) {\n info.attr.class += ' formio-multiple-mask-input';\n }\n return this.isMultipleMasksField\n ? this.renderTemplate('multipleMasksInput', {\n input: info,\n value,\n index,\n selectOptions: this.getMaskOptions() || [],\n }, this.isHtmlRenderMode() ? 'html' : null)\n : this.renderTemplate('input', {\n prefix: this.prefix,\n suffix: this.suffix,\n input: info,\n value: this.formatValue(this.parseValue(value)),\n hasValueMaskInput: hasDifferentDisplayAndSaveFormats,\n index\n }, this.isHtmlRenderMode() ? 'html' : null);\n }\n setCounter(type, element, count, max) {\n if (max) {\n const remaining = max - count;\n if (remaining > 0) {\n this.removeClass(element, 'text-danger');\n }\n else {\n this.addClass(element, 'text-danger');\n }\n this.setContent(element, this.t(`{{ remaining }} ${type} remaining.`, {\n remaining: remaining\n }));\n }\n else {\n this.setContent(element, this.t(`{{ count }} ${type}`, {\n count: count\n }));\n }\n }\n updateValueAt(value, flags, index) {\n flags = flags || {};\n if (lodash_1.default.get(this.component, 'showWordCount', false)) {\n if (this.refs.wordcount && this.refs.wordcount[index]) {\n const maxWords = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxWords', 0), 10);\n this.setCounter(this.t('words'), this.refs.wordcount[index], this.getWordCount(value), maxWords);\n }\n }\n if (lodash_1.default.get(this.component, 'showCharCount', false)) {\n if (this.refs.charcount && this.refs.charcount[index]) {\n const maxChars = lodash_1.default.parseInt(lodash_1.default.get(this.component, 'validate.maxLength', 0), 10);\n this.setCounter(this.t('characters'), this.refs.charcount[index], value.length, maxChars);\n }\n }\n }\n getValueAt(index) {\n const input = this.performInputMapping(this.refs.input[index]);\n if (input && input.widget) {\n return input.widget.getValue();\n }\n return input ? input.value : undefined;\n }\n updateValue(value, flags, index) {\n flags = flags || {};\n const changed = super.updateValue(value, flags);\n this.triggerUpdateValueAt(this.dataValue, flags, index);\n return changed;\n }\n parseValue(value) {\n return value;\n }\n formatValue(value) {\n return value;\n }\n attach(element) {\n this.loadRefs(element, {\n charcount: 'multiple',\n wordcount: 'multiple',\n prefix: 'multiple',\n suffix: 'multiple'\n });\n return super.attach(element);\n }\n getWidget(index) {\n index = index || 0;\n if (this.refs.input && this.refs.input[index]) {\n return this.refs.input[index].widget;\n }\n return null;\n }\n attachElement(element, index) {\n super.attachElement(element, index);\n if (element.widget) {\n element.widget.destroy();\n }\n // Attach the widget.\n let promise = Promise.resolve();\n element.widget = this.createWidget(index);\n if (element.widget) {\n promise = element.widget.attach(element);\n if (this.refs.prefix && this.refs.prefix[index]) {\n element.widget.addPrefix(this.refs.prefix[index]);\n }\n if (this.refs.suffix && this.refs.suffix[index]) {\n element.widget.addSuffix(this.refs.suffix[index]);\n }\n }\n // Add focus and blur events.\n this.addFocusBlurEvents(element);\n if (this.options.submitOnEnter) {\n this.addEventListener(element, 'keypress', (event) => {\n const key = event.keyCode || event.which;\n if (key === 13) {\n event.preventDefault();\n event.stopPropagation();\n this.emit('submitButton');\n }\n });\n }\n return promise;\n }\n /**\n * Creates an instance of a widget for this component.\n *\n * @return {null}\n */\n createWidget(index) {\n var _a, _b;\n // Return null if no widget is found.\n if (!this.component.widget) {\n return null;\n }\n // Get the widget settings.\n const settings = (typeof this.component.widget === 'string') ? {\n type: this.component.widget\n } : this.component.widget;\n if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.shadowRoot) {\n settings.shadowRoot = (_b = this.root) === null || _b === void 0 ? void 0 : _b.shadowRoot;\n }\n // Make sure we have a widget.\n if (!widgets_1.default.hasOwnProperty(settings.type)) {\n return null;\n }\n // Create the widget.\n const widget = new widgets_1.default[settings.type](settings, this.component, this, index);\n widget.on('update', () => this.updateValue(this.getValue(), {\n modified: true\n }, index), true);\n widget.on('redraw', () => this.redraw(), true);\n return widget;\n }\n teardown() {\n if (this.element && this.element.widget) {\n this.element.widget.destroy();\n delete this.element.widget;\n }\n if (this.refs && this.refs.input) {\n for (let i = 0; i <= this.refs.input.length; i++) {\n const widget = this.getWidget(i);\n if (widget) {\n widget.destroy();\n }\n }\n }\n super.teardown();\n }\n detach() {\n if (this.refs && this.refs.input) {\n for (let i = 0; i <= this.refs.input.length; i++) {\n const widget = this.getWidget(i);\n if (widget) {\n widget.destroy();\n }\n }\n }\n this.refs.input = [];\n super.detach();\n }\n}\nexports[\"default\"] = Input;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/input/Input.js?");
5810
5820
 
5811
5821
  /***/ }),
5812
5822
 
@@ -5872,7 +5882,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
5872
5882
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
5873
5883
 
5874
5884
  "use strict";
5875
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ../../Components */ \"./lib/cjs/components/Components.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Component_1 = __importDefault(__webpack_require__(/*! ../component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nclass NestedComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n tree: false,\n lazyLoad: false,\n }, ...extend);\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.type = 'components';\n this._collapsed = !!this.component.collapsed;\n }\n get defaultSchema() {\n return NestedComponent.schema();\n }\n get schema() {\n const schema = super.schema;\n const components = lodash_1.default.uniqBy(this.getComponents(), 'component.key');\n schema.components = lodash_1.default.map(components, 'schema');\n return schema;\n }\n get collapsed() {\n return this._collapsed;\n }\n collapse(value) {\n const promise = this.redraw();\n if (!value) {\n this.checkValidity(this.data, !this.pristine);\n }\n return promise;\n }\n set collapsed(value) {\n this._collapsed = value;\n this.collapse(value);\n }\n set visible(value) {\n // DO NOT CALL super here. There is an issue where clearOnHide was getting triggered with\n // subcomponents because the \"parentVisible\" flag was set to false when it should really be\n // set to true.\n const visibilityChanged = this._visible !== value;\n this._visible = value;\n const isVisible = this.visible;\n const forceShow = this.shouldForceShow();\n const forceHide = this.shouldForceHide();\n this.components.forEach(component => {\n // Set the parent visibility first since we may have nested components within nested components\n // and they need to be able to determine their visibility based on the parent visibility.\n component.parentVisible = isVisible;\n const conditionallyVisible = component.conditionallyVisible();\n if (forceShow || conditionallyVisible) {\n component.visible = true;\n }\n else if (forceHide || !isVisible || !conditionallyVisible) {\n component.visible = false;\n }\n // If hiding a nested component, clear all errors below.\n if (!component.visible) {\n component.error = '';\n }\n });\n if (visibilityChanged) {\n this.clearOnHide();\n this.redraw();\n }\n }\n get visible() {\n return super.visible;\n }\n set parentVisible(value) {\n super.parentVisible = value;\n this.components.forEach(component => component.parentVisible = this.visible);\n }\n get parentVisible() {\n return super.parentVisible;\n }\n get disabled() {\n return super.disabled;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n this.components.forEach((component) => component.parentDisabled = disabled);\n }\n set parentDisabled(value) {\n super.parentDisabled = value;\n this.components.forEach(component => {\n component.parentDisabled = this.disabled;\n });\n }\n get parentDisabled() {\n return super.parentDisabled;\n }\n get ready() {\n return Promise.all(this.getComponents().map(component => component.ready));\n }\n get currentForm() {\n return super.currentForm;\n }\n set currentForm(instance) {\n super.currentForm = instance;\n this.getComponents().forEach(component => {\n component.currentForm = instance;\n });\n }\n get rowIndex() {\n return this._rowIndex;\n }\n set rowIndex(value) {\n this._rowIndex = value;\n this.eachComponent((component) => {\n component.rowIndex = value;\n });\n }\n componentContext() {\n return this._data;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n this.eachComponent((component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.components || [];\n }\n /**\n * Perform a deep iteration over every component, including those\n * within other container based components.\n *\n * @param {function} fn - Called for every component.\n */\n everyComponent(fn, options) {\n const components = this.getComponents();\n lodash_1.default.each(components, (component, index) => {\n if (fn(component, components, index) === false) {\n return false;\n }\n if (typeof component.everyComponent === 'function') {\n if (component.everyComponent(fn, options) === false) {\n return false;\n }\n }\n });\n }\n hasComponent(component) {\n let result = false;\n this.everyComponent((comp) => {\n if (comp === component) {\n result = true;\n return false;\n }\n });\n return result;\n }\n flattenComponents() {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n });\n return result;\n }\n /**\n * Perform an iteration over each component within this container component.\n *\n * @param {function} fn - Called for each component\n */\n eachComponent(fn) {\n lodash_1.default.each(this.getComponents(), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n /**\n * Returns a component provided a key. This performs a deep search within the\n * component tree.\n *\n * @param {string} key - The key of the component to retrieve.\n * @param {function} [fn] - Called with the component once found.\n * @param {string} [originalPath] - The original path to the component.\n * @return {Component} - The component that is located.\n */\n getComponent(path, fn, originalPath) {\n originalPath = originalPath || (0, utils_1.getStringFromComponentPath)(path);\n if (this.componentsMap.hasOwnProperty(originalPath)) {\n if (fn) {\n return fn(this.componentsMap[originalPath]);\n }\n else {\n return this.componentsMap[originalPath];\n }\n }\n path = (0, utils_1.getArrayFromComponentPath)(path);\n const pathStr = originalPath;\n const newPath = lodash_1.default.clone(path);\n let key = newPath.shift();\n const remainingPath = newPath;\n let comp = null;\n let possibleComp = null;\n if (lodash_1.default.isNumber(key)) {\n key = remainingPath.shift();\n }\n if (!lodash_1.default.isString(key)) {\n return comp;\n }\n this.everyComponent((component, components) => {\n const matchPath = component.hasInput && component.path ? pathStr.includes(component.path) : true;\n if (component.component.key === key) {\n possibleComp = component;\n if (matchPath) {\n comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn, originalPath);\n }\n else if (fn) {\n fn(component, components);\n }\n return false;\n }\n }\n });\n if (!comp) {\n comp = possibleComp;\n }\n return comp;\n }\n /**\n * Return a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component.\n * @param {function} fn - Called with the component once it is retrieved.\n * @return {Object} - The component retrieved.\n */\n getComponentById(id, fn) {\n let comp = null;\n this.everyComponent((component, components) => {\n if (component.id === id) {\n comp = component;\n if (fn) {\n fn(component, components);\n }\n return false;\n }\n });\n return comp;\n }\n /**\n * Create a new component and add it to the components array.\n *\n * @param component\n * @param data\n */\n createComponent(component, options, data, before, replacedComp) {\n if (!component) {\n return;\n }\n options = options || this.options;\n data = data || this.data;\n options.parent = this;\n options.parentVisible = this.visible;\n options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;\n options.localRoot = this.localRoot;\n options.skipInit = true;\n if (!(options.display === 'pdf' && this.builderMode)) {\n component.id = (0, utils_1.getRandomComponentId)();\n }\n const comp = Components_1.default.create(component, options, data, true);\n comp.init();\n if (component.internal) {\n return comp;\n }\n if (before) {\n const index = lodash_1.default.findIndex(this.components, { id: before.id });\n if (index !== -1) {\n this.components.splice(index, 0, comp);\n }\n else {\n this.components.push(comp);\n }\n }\n else if (replacedComp) {\n const index = lodash_1.default.findIndex(this.components, { id: replacedComp.id });\n if (index !== -1) {\n this.components[index] = comp;\n }\n else {\n this.components.push(comp);\n }\n }\n else {\n this.components.push(comp);\n }\n return comp;\n }\n getContainer() {\n return this.element;\n }\n get componentComponents() {\n return this.component.components || [];\n }\n get nestedKey() {\n return `nested-${this.key}`;\n }\n get templateName() {\n return 'container';\n }\n init() {\n this.components = this.components || [];\n this.addComponents();\n return super.init();\n }\n /**\n *\n * @param element\n * @param data\n */\n addComponents(data, options) {\n data = data || this.data;\n options = options || this.options;\n if (options.components) {\n this.components = options.components;\n }\n else {\n const components = this.hook('addComponents', this.componentComponents, this) || [];\n components.forEach((component) => this.addComponent(component, data));\n }\n }\n /**\n * Add a new component to the components array.\n *\n * @param {Object} component - The component JSON schema to add.\n * @param {Object} data - The submission data object to house the data for this component.\n * @param {HTMLElement} before - A DOM element to insert this element before.\n * @return {Component} - The created component instance.\n */\n addComponent(component, data, before, noAdd) {\n data = data || this.data;\n this.components = this.components || [];\n component = this.hook('addComponent', component, data, before, noAdd);\n const comp = this.createComponent(component, this.options, data, before ? before : null);\n if (noAdd) {\n return comp;\n }\n return comp;\n }\n beforeFocus() {\n if (this.parent && 'beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n }\n render(children) {\n // If already rendering, don't re-render.\n return super.render(children || this.renderTemplate(this.templateName, {\n children: !this.visible ? '' : this.renderComponents(),\n nestedKey: this.nestedKey,\n collapsed: this.options.pdf ? false : this.collapsed,\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n return this.renderTemplate('components', {\n children,\n components,\n });\n }\n attach(element) {\n const superPromise = super.attach(element);\n this.loadRefs(element, {\n header: 'single',\n collapsed: this.collapsed,\n [this.nestedKey]: 'single',\n });\n let childPromise = Promise.resolve();\n if (this.refs[this.nestedKey]) {\n childPromise = this.attachComponents(this.refs[this.nestedKey]);\n }\n if (!this.visible) {\n this.attachComponentsLogic();\n }\n if (this.component.collapsible && this.refs.header) {\n this.addEventListener(this.refs.header, 'click', () => {\n this.collapsed = !this.collapsed;\n });\n this.addEventListener(this.refs.header, 'keydown', (e) => {\n if (e.keyCode === 13 || e.keyCode === 32) {\n e.preventDefault();\n this.collapsed = !this.collapsed;\n }\n });\n }\n return Promise.all([\n superPromise,\n childPromise,\n ]);\n }\n attachComponentsLogic(components) {\n components = components || this.components;\n lodash_1.default.each(components, (comp) => {\n comp.attachLogic();\n if (lodash_1.default.isFunction(comp.attachComponentsLogic)) {\n comp.attachComponentsLogic();\n }\n });\n }\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n if (!element) {\n // Return a non-resolving promise.\n return (new Promise(() => { }));\n }\n let index = 0;\n const promises = [];\n Array.prototype.slice.call(element.children).forEach(child => {\n if (!child.getAttribute('data-noattach') && components[index]) {\n promises.push(components[index].attach(child));\n index++;\n }\n });\n return Promise.all(promises);\n }\n /**\n * Remove a component from the components array and from the children object\n *\n * @param {Component} component - The component to remove from the components.\n * @param {Array<Component>} components - An array of components to remove this component from.\n */\n removeComponent(component, components) {\n components = components || this.components;\n component.destroy();\n lodash_1.default.remove(components, { id: component.id });\n if (this.componentsMap[component.path]) {\n delete this.componentsMap[component.path];\n }\n }\n /**\n * Removes a component provided the API key of that component.\n *\n * @param {string} key - The API key of the component to remove.\n * @param {function} fn - Called once the component is removed.\n * @return {null}\n */\n removeComponentByKey(key, fn) {\n const comp = this.getComponent(key, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n /**\n * Removes a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component to remove.\n * @param {function} fn - Called when the component is removed.\n * @return {null}\n */\n removeComponentById(id, fn) {\n const comp = this.getComponentById(id, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n updateValue(value, flags = {}) {\n return this.components.reduce((changed, comp) => {\n return comp.updateValue(null, flags) || changed;\n }, super.updateValue(value, flags));\n }\n shouldSkipValidation(data, row, flags) {\n // Nested components with no input should not be validated.\n if (!this.component.input) {\n return true;\n }\n else {\n return super.shouldSkipValidation(data, row, flags);\n }\n }\n checkData(data, flags, row, components) {\n if (this.builderMode) {\n return true;\n }\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n components = components && lodash_1.default.isArray(components) ? components : this.getComponents();\n super.checkData(data, Object.assign({}, flags), row);\n components.forEach((comp) => comp.checkData(data, Object.assign({}, flags), row));\n }\n checkConditions(data, flags, row) {\n // check conditions of parent component first, because it may influence on visibility of it's children\n const check = super.checkConditions(data, flags, row);\n //row data of parent component not always corresponds to row of nested components, use comp.data as row data for children instead\n this.getComponents().forEach(comp => comp.checkConditions(data, flags, comp.data));\n return check;\n }\n clearOnHide(show) {\n super.clearOnHide(show);\n if (this.component.clearOnHide) {\n if (this.allowData && !this.hasValue() && !(this.options.server && !this.visible)) {\n this.dataValue = this.defaultValue;\n }\n if (this.hasValue()) {\n this.restoreComponentsContext();\n }\n }\n this.getComponents().forEach(component => component.clearOnHide(show));\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => component.data = this.dataValue);\n }\n /**\n * Allow components to hook into the next page trigger to perform their own logic.\n *\n * @return {*}\n */\n beforePage(next) {\n return Promise.all(this.getComponents().map((comp) => comp.beforePage(next)));\n }\n /**\n * Allow components to hook into the submission to provide their own async data.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.allSettled(this.getComponents().map((comp) => comp.beforeSubmit()));\n }\n calculateValue(data, flags, row) {\n // Do not iterate into children and calculateValues if this nested component is conditionally hidden.\n if (!this.conditionallyVisible()) {\n return false;\n }\n return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));\n }\n isLastPage() {\n return this.pages.length - 1 === this.page;\n }\n isValid(data, dirty) {\n return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));\n }\n validationProcessor({ scope, data, row, instance }, flags) {\n const { dirty } = flags;\n if (!instance) {\n return;\n }\n instance.checkComponentValidity(data, dirty, row, flags, scope.errors);\n if (instance.processOwnValidation) {\n scope.noRecurse = true;\n }\n }\n /**\n * Perform a validation on all child components of this nested component.\n * @param {*} components\n * @param {*} data\n * @param {*} flags\n * @returns\n */\n validateComponents(components, data, flags = {}) {\n components = components || this.component.components;\n data = data || this.rootValue;\n const { async, dirty, process } = flags;\n const validationProcessorProcess = (context) => this.validationProcessor(context, flags);\n const checkModalProcessorProcess = ({ instance, component, components }) => {\n // If we just validated the last component, and there are errors from our parent, then we need to show a model of those errors.\n if (instance &&\n instance.parent &&\n (component === components[components.length - 1]) &&\n instance.parent.componentModal) {\n instance.parent.checkModal(instance.parent.childErrors, dirty);\n }\n };\n const processorContext = {\n process: process || 'unknown',\n components,\n instances: this.componentsMap,\n data: data,\n scope: { errors: [] },\n processors: [\n {\n process: validationProcessorProcess,\n processSync: validationProcessorProcess\n },\n {\n process: checkModalProcessorProcess,\n processSync: checkModalProcessorProcess\n }\n ]\n };\n return async ? (0, process_1.process)(processorContext).then((scope) => scope.errors) : (0, process_1.processSync)(processorContext).errors;\n }\n /**\n * Validate a nested component with data, or its own internal data.\n * @param {*} data\n * @param {*} flags\n * @returns\n */\n validate(data, flags = {}) {\n data = data || this.rootValue;\n return this.validateComponents(this.getComponents().map((component) => component.component), data, flags);\n }\n checkComponentValidity(data, dirty, row, flags = {}, allErrors = []) {\n this.childErrors = [];\n return super.checkComponentValidity(data, dirty, row, flags, allErrors);\n }\n checkValidity(data, dirty, row, silentCheck, childErrors = []) {\n console.log('Deprecation warning: Component.checkValidity() will be deprecated in 6.x version of renderer. Use \"validate\" method instead.');\n childErrors.push(...this.validate(data, { dirty, silentCheck }));\n return this.checkComponentValidity(data, dirty, row, { dirty, silentCheck }, childErrors) && childErrors.length === 0;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n console.log('Deprecation warning: Component.checkAsyncValidity() will be deprecated in 6.x version of renderer.');\n return this.ready.then(() => {\n return this.validate(data, { dirty, silentCheck, async: true }).then((childErrors) => {\n return this.checkComponentValidity(data, dirty, row, { dirty, silentCheck, async: true }, childErrors).then((valid) => {\n return valid && childErrors.length === 0;\n });\n });\n });\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n this.getComponents().forEach((comp) => comp.setPristine(pristine));\n }\n get isPristine() {\n return this.pristine && this.getComponents().every((c) => c.isPristine);\n }\n get isDirty() {\n return this.dirty && this.getComponents().every((c) => c.isDirty);\n }\n detach() {\n this.components.forEach(component => {\n component.detach();\n });\n super.detach();\n }\n clear() {\n this.components.forEach(component => {\n component.clear();\n });\n super.clear();\n }\n destroy() {\n this.destroyComponents();\n super.destroy();\n }\n destroyComponents() {\n const components = this.getComponents().slice();\n components.forEach((comp) => this.removeComponent(comp, this.components));\n this.components = [];\n }\n get visibleErrors() {\n return this.getComponents().reduce((errors, comp) => errors.concat(comp.visibleErrors || []), super.visibleErrors);\n }\n get errors() {\n const thisErrors = super.errors;\n return this.getComponents()\n .reduce((errors, comp) => errors.concat(comp.errors || []), thisErrors)\n .filter(err => err.level !== 'hidden');\n }\n getValue() {\n return this.data;\n }\n resetValue() {\n super.resetValue();\n this.getComponents().forEach((comp) => comp.resetValue());\n this.setPristine(true);\n }\n get dataReady() {\n return Promise.all(this.getComponents().map((component) => component.dataReady));\n }\n setNestedValue(component, value, flags = {}) {\n component._data = this.componentContext(component);\n if (component.type === 'button') {\n return false;\n }\n if (component.type === 'components') {\n if (component.tree && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n return component.setValue(value, flags);\n }\n else if (value && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {\n flags.noValidate = !flags.dirty;\n flags.resetValue = true;\n return component.setValue(component.defaultValue, flags);\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n return false;\n }\n return this.getComponents().reduce((changed, component) => {\n return this.setNestedValue(component, value, flags, changed) || changed;\n }, false);\n }\n get lazyLoad() {\n var _a;\n return (_a = this.component.lazyLoad) !== null && _a !== void 0 ? _a : false;\n }\n}\nexports[\"default\"] = NestedComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/nested/NestedComponent.js?");
5885
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Field_1 = __importDefault(__webpack_require__(/*! ../field/Field */ \"./lib/cjs/components/_classes/field/Field.js\"));\nconst Components_1 = __importDefault(__webpack_require__(/*! ../../Components */ \"./lib/cjs/components/Components.js\"));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Component_1 = __importDefault(__webpack_require__(/*! ../component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nclass NestedComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n tree: false,\n lazyLoad: false,\n }, ...extend);\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.type = 'components';\n this._collapsed = !!this.component.collapsed;\n }\n get defaultSchema() {\n return NestedComponent.schema();\n }\n get schema() {\n const schema = super.schema;\n const components = lodash_1.default.uniqBy(this.getComponents(), 'component.key');\n schema.components = lodash_1.default.map(components, 'schema');\n return schema;\n }\n get collapsed() {\n return this._collapsed;\n }\n collapse(value) {\n const promise = this.redraw();\n if (!value) {\n this.checkValidity(this.data, !this.pristine);\n }\n return promise;\n }\n set collapsed(value) {\n this._collapsed = value;\n this.collapse(value);\n }\n set visible(value) {\n // DO NOT CALL super here. There is an issue where clearOnHide was getting triggered with\n // subcomponents because the \"parentVisible\" flag was set to false when it should really be\n // set to true.\n const visibilityChanged = this._visible !== value;\n this._visible = value;\n const isVisible = this.visible;\n const forceShow = this.shouldForceShow();\n const forceHide = this.shouldForceHide();\n this.components.forEach(component => {\n // Set the parent visibility first since we may have nested components within nested components\n // and they need to be able to determine their visibility based on the parent visibility.\n component.parentVisible = isVisible;\n const conditionallyVisible = component.conditionallyVisible();\n if (forceShow || conditionallyVisible) {\n component.visible = true;\n }\n else if (forceHide || !isVisible || !conditionallyVisible) {\n component.visible = false;\n }\n // If hiding a nested component, clear all errors below.\n if (!component.visible) {\n component.error = '';\n }\n });\n if (visibilityChanged) {\n this.clearOnHide();\n this.redraw();\n }\n }\n get visible() {\n return super.visible;\n }\n set parentVisible(value) {\n super.parentVisible = value;\n this.components.forEach(component => component.parentVisible = this.visible);\n }\n get parentVisible() {\n return super.parentVisible;\n }\n get disabled() {\n return super.disabled;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n this.components.forEach((component) => component.parentDisabled = disabled);\n }\n set parentDisabled(value) {\n super.parentDisabled = value;\n this.components.forEach(component => {\n component.parentDisabled = this.disabled;\n });\n }\n get parentDisabled() {\n return super.parentDisabled;\n }\n get ready() {\n return Promise.all(this.getComponents().map(component => component.ready));\n }\n get currentForm() {\n return super.currentForm;\n }\n set currentForm(instance) {\n super.currentForm = instance;\n this.getComponents().forEach(component => {\n component.currentForm = instance;\n });\n }\n get rowIndex() {\n return this._rowIndex;\n }\n set rowIndex(value) {\n this._rowIndex = value;\n this.eachComponent((component) => {\n component.rowIndex = value;\n });\n }\n componentContext() {\n return this._data;\n }\n get data() {\n return this._data;\n }\n set data(value) {\n this._data = value;\n this.eachComponent((component) => {\n component.data = this.componentContext(component);\n });\n }\n getComponents() {\n return this.components || [];\n }\n /**\n * Perform a deep iteration over every component, including those\n * within other container based components.\n *\n * @param {function} fn - Called for every component.\n */\n everyComponent(fn, options) {\n const components = this.getComponents();\n lodash_1.default.each(components, (component, index) => {\n if (fn(component, components, index) === false) {\n return false;\n }\n if (typeof component.everyComponent === 'function') {\n if (component.everyComponent(fn, options) === false) {\n return false;\n }\n }\n });\n }\n hasComponent(component) {\n let result = false;\n this.everyComponent((comp) => {\n if (comp === component) {\n result = true;\n return false;\n }\n });\n return result;\n }\n flattenComponents() {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n });\n return result;\n }\n /**\n * Perform an iteration over each component within this container component.\n *\n * @param {function} fn - Called for each component\n */\n eachComponent(fn) {\n lodash_1.default.each(this.getComponents(), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n /**\n * Returns a component provided a key. This performs a deep search within the\n * component tree.\n *\n * @param {string} key - The key of the component to retrieve.\n * @param {function} [fn] - Called with the component once found.\n * @param {string} [originalPath] - The original path to the component.\n * @return {Component} - The component that is located.\n */\n getComponent(path, fn, originalPath) {\n originalPath = originalPath || (0, utils_1.getStringFromComponentPath)(path);\n if (this.componentsMap.hasOwnProperty(originalPath)) {\n if (fn) {\n return fn(this.componentsMap[originalPath]);\n }\n else {\n return this.componentsMap[originalPath];\n }\n }\n path = (0, utils_1.getArrayFromComponentPath)(path);\n const pathStr = originalPath;\n const newPath = lodash_1.default.clone(path);\n let key = newPath.shift();\n const remainingPath = newPath;\n let comp = null;\n let possibleComp = null;\n if (lodash_1.default.isNumber(key)) {\n key = remainingPath.shift();\n }\n if (!lodash_1.default.isString(key)) {\n return comp;\n }\n this.everyComponent((component, components) => {\n const matchPath = component.hasInput && component.path ? pathStr.includes(component.path) : true;\n if (component.component.key === key) {\n possibleComp = component;\n if (matchPath) {\n comp = component;\n if (remainingPath.length > 0 && 'getComponent' in component) {\n comp = component.getComponent(remainingPath, fn, originalPath);\n }\n else if (fn) {\n fn(component, components);\n }\n return false;\n }\n }\n });\n if (!comp) {\n comp = possibleComp;\n }\n return comp;\n }\n /**\n * Return a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component.\n * @param {function} fn - Called with the component once it is retrieved.\n * @return {Object} - The component retrieved.\n */\n getComponentById(id, fn) {\n let comp = null;\n this.everyComponent((component, components) => {\n if (component.id === id) {\n comp = component;\n if (fn) {\n fn(component, components);\n }\n return false;\n }\n });\n return comp;\n }\n /**\n * Create a new component and add it to the components array.\n *\n * @param component\n * @param data\n */\n createComponent(component, options, data, before, replacedComp) {\n if (!component) {\n return;\n }\n options = options || this.options;\n data = data || this.data;\n options.parent = this;\n options.parentVisible = this.visible;\n options.root = (options === null || options === void 0 ? void 0 : options.root) || this.root || this;\n options.localRoot = this.localRoot;\n options.skipInit = true;\n if (!(options.display === 'pdf' && this.builderMode)) {\n component.id = (0, utils_1.getRandomComponentId)();\n }\n const comp = Components_1.default.create(component, options, data, true);\n comp.init();\n if (component.internal) {\n return comp;\n }\n if (before) {\n const index = lodash_1.default.findIndex(this.components, { id: before.id });\n if (index !== -1) {\n this.components.splice(index, 0, comp);\n }\n else {\n this.components.push(comp);\n }\n }\n else if (replacedComp) {\n const index = lodash_1.default.findIndex(this.components, { id: replacedComp.id });\n if (index !== -1) {\n this.components[index] = comp;\n }\n else {\n this.components.push(comp);\n }\n }\n else {\n this.components.push(comp);\n }\n return comp;\n }\n getContainer() {\n return this.element;\n }\n get componentComponents() {\n return this.component.components || [];\n }\n get nestedKey() {\n return `nested-${this.key}`;\n }\n get templateName() {\n return 'container';\n }\n init() {\n this.components = this.components || [];\n this.addComponents();\n return super.init();\n }\n /**\n *\n * @param element\n * @param data\n */\n addComponents(data, options) {\n data = data || this.data;\n this.components = this.components || [];\n options = options || this.options;\n if (options.components) {\n this.components = options.components;\n }\n else {\n const components = this.hook('addComponents', this.componentComponents, this) || [];\n components.forEach((component) => this.addComponent(component, data));\n }\n }\n /**\n * Add a new component to the components array.\n *\n * @param {Object} component - The component JSON schema to add.\n * @param {Object} data - The submission data object to house the data for this component.\n * @param {HTMLElement} before - A DOM element to insert this element before.\n * @return {Component} - The created component instance.\n */\n addComponent(component, data, before, noAdd) {\n data = data || this.data;\n this.components = this.components || [];\n component = this.hook('addComponent', component, data, before, noAdd);\n const comp = this.createComponent(component, this.options, data, before ? before : null);\n if (noAdd) {\n return comp;\n }\n return comp;\n }\n beforeFocus() {\n if (this.parent && 'beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n }\n render(children) {\n // If already rendering, don't re-render.\n return super.render(children || this.renderTemplate(this.templateName, {\n children: !this.visible ? '' : this.renderComponents(),\n nestedKey: this.nestedKey,\n collapsed: this.options.pdf ? false : this.collapsed,\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n return this.renderTemplate('components', {\n children,\n components,\n });\n }\n attach(element) {\n const superPromise = super.attach(element);\n this.loadRefs(element, {\n header: 'single',\n collapsed: this.collapsed,\n [this.nestedKey]: 'single',\n });\n let childPromise = Promise.resolve();\n if (this.refs[this.nestedKey]) {\n childPromise = this.attachComponents(this.refs[this.nestedKey]);\n }\n if (!this.visible) {\n this.attachComponentsLogic();\n }\n if (this.component.collapsible && this.refs.header) {\n this.addEventListener(this.refs.header, 'click', () => {\n this.collapsed = !this.collapsed;\n });\n this.addEventListener(this.refs.header, 'keydown', (e) => {\n if (e.keyCode === 13 || e.keyCode === 32) {\n e.preventDefault();\n this.collapsed = !this.collapsed;\n }\n });\n }\n return Promise.all([\n superPromise,\n childPromise,\n ]);\n }\n attachComponentsLogic(components) {\n components = components || this.components;\n lodash_1.default.each(components, (comp) => {\n comp.attachLogic();\n if (lodash_1.default.isFunction(comp.attachComponentsLogic)) {\n comp.attachComponentsLogic();\n }\n });\n }\n attachComponents(element, components, container) {\n components = components || this.components;\n container = container || this.component.components;\n element = this.hook('attachComponents', element, components, container, this);\n if (!element) {\n // Return a non-resolving promise.\n return (new Promise(() => { }));\n }\n let index = 0;\n const promises = [];\n Array.prototype.slice.call(element.children).forEach(child => {\n if (!child.getAttribute('data-noattach') && components[index]) {\n promises.push(components[index].attach(child));\n index++;\n }\n });\n return Promise.all(promises);\n }\n /**\n * Remove a component from the components array and from the children object\n *\n * @param {Component} component - The component to remove from the components.\n * @param {Array<Component>} components - An array of components to remove this component from.\n */\n removeComponent(component, components, all = false) {\n components = components || this.components;\n component.destroy(all);\n lodash_1.default.remove(components, { id: component.id });\n if (this.componentsMap[component.path]) {\n delete this.componentsMap[component.path];\n }\n }\n /**\n * Removes a component provided the API key of that component.\n *\n * @param {string} key - The API key of the component to remove.\n * @param {function} fn - Called once the component is removed.\n * @return {null}\n */\n removeComponentByKey(key, fn) {\n const comp = this.getComponent(key, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n /**\n * Removes a component provided the Id of the component.\n *\n * @param {string} id - The Id of the component to remove.\n * @param {function} fn - Called when the component is removed.\n * @return {null}\n */\n removeComponentById(id, fn) {\n const comp = this.getComponentById(id, (component, components) => {\n this.removeComponent(component, components);\n if (fn) {\n fn(component, components);\n }\n });\n if (!comp) {\n if (fn) {\n fn(null);\n }\n return null;\n }\n }\n updateValue(value, flags = {}) {\n return this.components.reduce((changed, comp) => {\n return comp.updateValue(null, flags) || changed;\n }, super.updateValue(value, flags));\n }\n shouldSkipValidation(data, row, flags) {\n // Nested components with no input should not be validated.\n if (!this.component.input) {\n return true;\n }\n else {\n return super.shouldSkipValidation(data, row, flags);\n }\n }\n checkData(data, flags, row, components) {\n if (this.builderMode) {\n return true;\n }\n data = data || this.rootValue;\n flags = flags || {};\n row = row || this.data;\n components = components && lodash_1.default.isArray(components) ? components : this.getComponents();\n super.checkData(data, Object.assign({}, flags), row);\n components.forEach((comp) => comp.checkData(data, Object.assign({}, flags), row));\n }\n checkConditions(data, flags, row) {\n // check conditions of parent component first, because it may influence on visibility of it's children\n const check = super.checkConditions(data, flags, row);\n //row data of parent component not always corresponds to row of nested components, use comp.data as row data for children instead\n this.getComponents().forEach(comp => comp.checkConditions(data, flags, comp.data));\n return check;\n }\n clearOnHide(show) {\n super.clearOnHide(show);\n if (this.component.clearOnHide) {\n if (this.allowData && !this.hasValue() && !(this.options.server && !this.visible)) {\n this.dataValue = this.defaultValue;\n }\n if (this.hasValue()) {\n this.restoreComponentsContext();\n }\n }\n this.getComponents().forEach(component => component.clearOnHide(show));\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => component.data = this.dataValue);\n }\n /**\n * Allow components to hook into the next page trigger to perform their own logic.\n *\n * @return {*}\n */\n beforePage(next) {\n return Promise.all(this.getComponents().map((comp) => comp.beforePage(next)));\n }\n /**\n * Allow components to hook into the submission to provide their own async data.\n *\n * @return {*}\n */\n beforeSubmit() {\n return Promise.allSettled(this.getComponents().map((comp) => comp.beforeSubmit()));\n }\n calculateValue(data, flags, row) {\n // Do not iterate into children and calculateValues if this nested component is conditionally hidden.\n if (!this.conditionallyVisible()) {\n return false;\n }\n return this.getComponents().reduce((changed, comp) => comp.calculateValue(data, flags, row) || changed, super.calculateValue(data, flags, row));\n }\n isLastPage() {\n return this.pages.length - 1 === this.page;\n }\n isValid(data, dirty) {\n return this.getComponents().reduce((valid, comp) => comp.isValid(data, dirty) && valid, super.isValid(data, dirty));\n }\n validationProcessor({ scope, data, row, instance }, flags) {\n const { dirty } = flags;\n if (!instance) {\n return;\n }\n instance.checkComponentValidity(data, dirty, row, flags, scope.errors);\n if (instance.processOwnValidation) {\n scope.noRecurse = true;\n }\n }\n /**\n * Perform a validation on all child components of this nested component.\n * @param {*} components\n * @param {*} data\n * @param {*} flags\n * @returns\n */\n validateComponents(components, data, flags = {}) {\n components = components || this.component.components;\n data = data || this.rootValue;\n const { async, dirty, process } = flags;\n const validationProcessorProcess = (context) => this.validationProcessor(context, flags);\n const checkModalProcessorProcess = ({ instance, component, components }) => {\n // If we just validated the last component, and there are errors from our parent, then we need to show a model of those errors.\n if (instance &&\n instance.parent &&\n (component === components[components.length - 1]) &&\n instance.parent.componentModal) {\n instance.parent.checkModal(instance.parent.childErrors, dirty);\n }\n };\n const processorContext = {\n process: process || 'unknown',\n components,\n instances: this.componentsMap,\n data: data,\n scope: { errors: [] },\n processors: [\n {\n process: validationProcessorProcess,\n processSync: validationProcessorProcess\n },\n {\n process: checkModalProcessorProcess,\n processSync: checkModalProcessorProcess\n }\n ]\n };\n return async ? (0, process_1.process)(processorContext).then((scope) => scope.errors) : (0, process_1.processSync)(processorContext).errors;\n }\n /**\n * Validate a nested component with data, or its own internal data.\n * @param {*} data\n * @param {*} flags\n * @returns\n */\n validate(data, flags = {}) {\n data = data || this.rootValue;\n return this.validateComponents(this.getComponents().map((component) => component.component), data, flags);\n }\n checkComponentValidity(data, dirty, row, flags = {}, allErrors = []) {\n this.childErrors = [];\n return super.checkComponentValidity(data, dirty, row, flags, allErrors);\n }\n checkValidity(data, dirty, row, silentCheck, childErrors = []) {\n console.log('Deprecation warning: Component.checkValidity() will be deprecated in 6.x version of renderer. Use \"validate\" method instead.');\n childErrors.push(...this.validate(data, { dirty, silentCheck }));\n return this.checkComponentValidity(data, dirty, row, { dirty, silentCheck }, childErrors) && childErrors.length === 0;\n }\n checkAsyncValidity(data, dirty, row, silentCheck) {\n console.log('Deprecation warning: Component.checkAsyncValidity() will be deprecated in 6.x version of renderer.');\n return this.ready.then(() => {\n return this.validate(data, { dirty, silentCheck, async: true }).then((childErrors) => {\n return this.checkComponentValidity(data, dirty, row, { dirty, silentCheck, async: true }, childErrors).then((valid) => {\n return valid && childErrors.length === 0;\n });\n });\n });\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n this.getComponents().forEach((comp) => comp.setPristine(pristine));\n }\n get isPristine() {\n return this.pristine && this.getComponents().every((c) => c.isPristine);\n }\n get isDirty() {\n return this.dirty && this.getComponents().every((c) => c.isDirty);\n }\n detach() {\n this.components.forEach(component => {\n component.detach();\n });\n super.detach();\n }\n clear() {\n this.components.forEach(component => {\n component.clear();\n });\n super.clear();\n }\n destroy(all = false) {\n this.destroyComponents(all);\n super.destroy(all);\n }\n destroyComponents(all = false) {\n const components = this.getComponents().slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n this.components = [];\n }\n get visibleErrors() {\n return this.getComponents().reduce((errors, comp) => errors.concat(comp.visibleErrors || []), super.visibleErrors);\n }\n get errors() {\n const thisErrors = super.errors;\n return this.getComponents()\n .reduce((errors, comp) => errors.concat(comp.errors || []), thisErrors)\n .filter(err => err.level !== 'hidden');\n }\n getValue() {\n return this.data;\n }\n resetValue() {\n super.resetValue();\n this.getComponents().forEach((comp) => comp.resetValue());\n this.setPristine(true);\n }\n get dataReady() {\n return Promise.all(this.getComponents().map((component) => component.dataReady));\n }\n setNestedValue(component, value, flags = {}) {\n component._data = this.componentContext(component);\n if (component.type === 'button') {\n return false;\n }\n if (component.type === 'components') {\n if (component.tree && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n return component.setValue(value, flags);\n }\n else if (value && component.hasValue(value)) {\n return component.setValue(lodash_1.default.get(value, component.key), flags);\n }\n else if ((!this.rootPristine || component.visible) && component.shouldAddDefaultValue) {\n flags.noValidate = !flags.dirty;\n flags.resetValue = true;\n return component.setValue(component.defaultValue, flags);\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n return false;\n }\n return this.getComponents().reduce((changed, component) => {\n return this.setNestedValue(component, value, flags, changed) || changed;\n }, false);\n }\n get lazyLoad() {\n var _a;\n return (_a = this.component.lazyLoad) !== null && _a !== void 0 ? _a : false;\n }\n}\nexports[\"default\"] = NestedComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/_classes/nested/NestedComponent.js?");
5876
5886
 
5877
5887
  /***/ }),
5878
5888
 
@@ -6081,7 +6091,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
6081
6091
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6082
6092
 
6083
6093
  "use strict";
6084
- 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 NestedComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nested/NestedComponent */ \"./lib/cjs/components/_classes/nested/NestedComponent.js\"));\nclass ColumnsComponent extends NestedComponent_1.default {\n static schema(...extend) {\n return NestedComponent_1.default.schema({\n label: 'Columns',\n key: 'columns',\n type: 'columns',\n columns: [\n { components: [], width: 6, offset: 0, push: 0, pull: 0, size: 'md' },\n { components: [], width: 6, offset: 0, push: 0, pull: 0, size: 'md' }\n ],\n clearOnHide: false,\n input: false,\n tableView: false,\n persistent: false,\n autoAdjust: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Columns',\n icon: 'columns',\n group: 'layout',\n documentation: '/userguide/form-building/layout-components#columns',\n showPreview: false,\n weight: 10,\n schema: ColumnsComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.rows = [];\n }\n get schema() {\n var _a;\n const schema = lodash_1.default.omit(super.schema, ['components']);\n (_a = schema.columns) === null || _a === void 0 ? void 0 : _a.map((column, colIndex) => {\n column.components.map((comp, compIndex) => {\n const clonedComp = lodash_1.default.clone(comp);\n clonedComp.internal = true;\n const component = this.createComponent(clonedComp);\n delete component.component.internal;\n schema.columns[colIndex].components[compIndex] = component.schema;\n });\n });\n return schema;\n }\n get defaultSchema() {\n return ColumnsComponent.schema();\n }\n get className() {\n return `row ${super.className}`;\n }\n get columnKey() {\n return `column-${this.id}`;\n }\n init() {\n super.init();\n this.columns = [];\n lodash_1.default.each(this.component.columns, (column, index) => {\n this.columns[index] = [];\n if (!column.size) {\n column.size = 'md';\n }\n column.currentWidth = this.options.condensedMode ? this.gridSize : column.width || 0;\n // Ensure there is a components array.\n if (!Array.isArray(column.components)) {\n column.components = [];\n }\n lodash_1.default.each(column.components, (comp) => {\n const component = this.createComponent(comp);\n component.column = index;\n this.columns[index].push(component);\n });\n });\n if (this.component.autoAdjust && this.options.display !== 'pdf') {\n this.justify();\n }\n this.rows = this.groupByRow();\n }\n labelIsHidden() {\n return true;\n }\n render() {\n return super.render(this.renderTemplate('columns', {\n columnKey: this.columnKey,\n columnComponents: this.columns.map(column => this.renderComponents(column))\n }));\n }\n justifyColumn(items, index) {\n const toAdjust = lodash_1.default.every(items, item => !item.visible);\n const column = this.component.columns[index];\n const width = (toAdjust && items.length) ? 0 : column.width;\n const shouldRedraw = !lodash_1.default.isEqual(width, column.currentWidth);\n column.currentWidth = width;\n return shouldRedraw;\n }\n justify() {\n return this.columns.reduce((redraw, items, index) => this.justifyColumn(items, index) || redraw, false);\n }\n attach(element) {\n this.loadRefs(element, { [this.columnKey]: 'multiple' });\n const superAttach = super.attach(element);\n if (this.refs[this.columnKey]) {\n this.refs[this.columnKey].forEach((column, index) => this.attachComponents(column, this.columns[index], this.component.columns[index].components));\n }\n return superAttach;\n }\n get gridSize() {\n return 12;\n }\n /**\n * Group columns in rows.\n * @return {Array.<ColumnComponent[]>}\n */\n groupByRow() {\n const initVal = { stack: [], rows: [] };\n const width = x => x.component.width;\n const result = lodash_1.default.reduce(this.components, (acc, next) => {\n const stack = [...acc.stack, next];\n if (lodash_1.default.sumBy(stack, width) <= this.gridSize) {\n acc.stack = stack;\n return acc;\n }\n else {\n acc.rows = [...acc.rows, acc.stack];\n acc.stack = [next];\n return acc;\n }\n }, initVal);\n return lodash_1.default.concat(result.rows, [result.stack]);\n }\n checkData(data, flags, row, components) {\n super.checkData(data, flags, row, components);\n if (this.component.autoAdjust && this.options.display !== 'pdf') {\n const redraw = this.justify();\n if (redraw) {\n this.redraw();\n }\n }\n }\n detach(all) {\n super.detach(all);\n }\n destroy() {\n super.destroy();\n this.columns = [];\n }\n}\nexports[\"default\"] = ColumnsComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/columns/Columns.js?");
6094
+ 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 NestedComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nested/NestedComponent */ \"./lib/cjs/components/_classes/nested/NestedComponent.js\"));\nclass ColumnsComponent extends NestedComponent_1.default {\n static schema(...extend) {\n return NestedComponent_1.default.schema({\n label: 'Columns',\n key: 'columns',\n type: 'columns',\n columns: [\n { components: [], width: 6, offset: 0, push: 0, pull: 0, size: 'md' },\n { components: [], width: 6, offset: 0, push: 0, pull: 0, size: 'md' }\n ],\n clearOnHide: false,\n input: false,\n tableView: false,\n persistent: false,\n autoAdjust: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Columns',\n icon: 'columns',\n group: 'layout',\n documentation: '/userguide/form-building/layout-components#columns',\n showPreview: false,\n weight: 10,\n schema: ColumnsComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.rows = [];\n }\n get schema() {\n var _a;\n const schema = lodash_1.default.omit(super.schema, ['components']);\n (_a = schema.columns) === null || _a === void 0 ? void 0 : _a.map((column, colIndex) => {\n column.components.map((comp, compIndex) => {\n const clonedComp = lodash_1.default.clone(comp);\n clonedComp.internal = true;\n const component = this.createComponent(clonedComp);\n delete component.component.internal;\n schema.columns[colIndex].components[compIndex] = component.schema;\n });\n });\n return schema;\n }\n get defaultSchema() {\n return ColumnsComponent.schema();\n }\n get className() {\n return `row ${super.className}`;\n }\n get columnKey() {\n return `column-${this.id}`;\n }\n init() {\n super.init();\n this.columns = [];\n lodash_1.default.each(this.component.columns, (column, index) => {\n this.columns[index] = [];\n if (!column.size) {\n column.size = 'md';\n }\n column.currentWidth = this.options.condensedMode ? this.gridSize : column.width || 0;\n // Ensure there is a components array.\n if (!Array.isArray(column.components)) {\n column.components = [];\n }\n lodash_1.default.each(column.components, (comp) => {\n const component = this.createComponent(comp);\n component.column = index;\n this.columns[index].push(component);\n });\n });\n if (this.component.autoAdjust && this.options.display !== 'pdf') {\n this.justify();\n }\n this.rows = this.groupByRow();\n }\n labelIsHidden() {\n return true;\n }\n render() {\n return super.render(this.renderTemplate('columns', {\n columnKey: this.columnKey,\n columnComponents: this.columns.map(column => this.renderComponents(column))\n }));\n }\n justifyColumn(items, index) {\n const toAdjust = lodash_1.default.every(items, item => !item.visible);\n const column = this.component.columns[index];\n const width = (toAdjust && items.length) ? 0 : column.width;\n const shouldRedraw = !lodash_1.default.isEqual(width, column.currentWidth);\n column.currentWidth = width;\n return shouldRedraw;\n }\n justify() {\n return this.columns.reduce((redraw, items, index) => this.justifyColumn(items, index) || redraw, false);\n }\n attach(element) {\n this.loadRefs(element, { [this.columnKey]: 'multiple' });\n const superAttach = super.attach(element);\n if (this.refs[this.columnKey]) {\n this.refs[this.columnKey].forEach((column, index) => this.attachComponents(column, this.columns[index], this.component.columns[index].components));\n }\n return superAttach;\n }\n get gridSize() {\n return 12;\n }\n /**\n * Group columns in rows.\n * @return {Array.<ColumnComponent[]>}\n */\n groupByRow() {\n const initVal = { stack: [], rows: [] };\n const width = x => x.component.width;\n const result = lodash_1.default.reduce(this.components, (acc, next) => {\n const stack = [...acc.stack, next];\n if (lodash_1.default.sumBy(stack, width) <= this.gridSize) {\n acc.stack = stack;\n return acc;\n }\n else {\n acc.rows = [...acc.rows, acc.stack];\n acc.stack = [next];\n return acc;\n }\n }, initVal);\n return lodash_1.default.concat(result.rows, [result.stack]);\n }\n checkData(data, flags, row, components) {\n super.checkData(data, flags, row, components);\n if (this.component.autoAdjust && this.options.display !== 'pdf') {\n const redraw = this.justify();\n if (redraw) {\n this.redraw();\n }\n }\n }\n detach(all) {\n super.detach(all);\n }\n destroy(all = false) {\n super.destroy(all);\n this.columns = [];\n }\n}\nexports[\"default\"] = ColumnsComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/columns/Columns.js?");
6085
6095
 
6086
6096
  /***/ }),
6087
6097
 
@@ -6510,7 +6520,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
6510
6520
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6511
6521
 
6512
6522
  "use strict";
6513
- 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 process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nconst components_1 = __webpack_require__(/*! @formio/bootstrap/components */ \"./node_modules/@formio/bootstrap/lib/cjs/templates/components/index.js\");\nconst NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Alert_1 = __importDefault(__webpack_require__(/*! ../alert/Alert */ \"./lib/cjs/components/alert/Alert.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst EditRowState = {\n New: 'new',\n Editing: 'editing',\n Saved: 'saved',\n Viewing: 'viewing',\n Removed: 'removed',\n Draft: 'draft',\n};\nclass EditGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n type: 'editgrid',\n label: 'Edit Grid',\n key: 'editGrid',\n clearOnHide: true,\n input: true,\n tree: true,\n removeRow: 'Cancel',\n defaultOpen: false,\n openWhenEmpty: false,\n modal: false,\n components: [],\n inlineEdit: false,\n templates: {\n header: EditGridComponent.defaultHeaderTemplate,\n row: EditGridComponent.defaultRowTemplate,\n tableHeader: EditGridComponent.defaultTableHeaderTemplate,\n tableRow: EditGridComponent.defaultTableRowTemplate,\n footer: '',\n },\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Edit Grid',\n icon: 'tasks',\n group: 'data',\n documentation: '/userguide/form-building/data-components#edit-grid',\n showPreview: false,\n weight: 30,\n schema: EditGridComponent.schema(),\n };\n }\n static get defaultHeaderTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">{{ t(component.label) }}</div>\n {% } %}\n {% }) %}\n </div>`;\n }\n static get defaultTableHeaderTemplate() {\n return `\n <tr>\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">{{ component.label }}</td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">Actions</td>\n {% } %}\n </tr>\n `;\n }\n static get defaultRowTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">\n {{ isVisibleInRow(component) ? getView(component, row[component.key]) : ''}}\n </div>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <div class=\"col-sm-2\">\n <div class=\"btn-group pull-right\">\n <button class=\"btn btn-default btn-light btn-sm editRow\"><i class=\"{{ iconClass('pen-fill') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </div>\n {% } %}\n </div>`;\n }\n static get defaultTableRowTemplate() {\n return `\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">\n {{ getView(component, row[component.key]) }}\n </td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">\n <div class=\"btn-group\">\n <button class=\"btn btn-default btn-light btn-sm editRow\" aria-label=\"{{ t('Edit row') }}\"><i class=\"{{ iconClass('pen-fill') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\" aria-label=\"{{ t('Remove row') }}\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </td>\n {% } %}\n `;\n }\n get defaultDialogTemplate() {\n return `\n <h3 ${this._referenceAttributeName}=\"dialogHeader\">${this.t('Do you want to clear data?')}</h3>\n <div style=\"display:flex; justify-content: flex-end;\">\n <button ${this._referenceAttributeName}=\"dialogCancelButton\" class=\"btn btn-secondary\" aria-label=\"${this.t('Cancel')}\">${this.t('Cancel')}</button>\n <button ${this._referenceAttributeName}=\"dialogYesButton\" class=\"btn btn-danger\" aria-label=\"${this.t('Yes, delete it')}\">${this.t('Yes, delete it')}</button>\n </div>\n `;\n }\n get defaultRowTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableRowTemplate\n : EditGridComponent.defaultRowTemplate;\n }\n get defaultHeaderTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableHeaderTemplate\n : EditGridComponent.defaultHeaderTemplate;\n }\n get rowTemplate() {\n let rowTemplate;\n if (utils_1.Evaluator.noeval) {\n rowTemplate = this.displayAsTable ?\n components_1.editgrid.tableRow\n : components_1.editgrid.row;\n }\n else {\n rowTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableRow', this.defaultRowTemplate)\n : lodash_1.default.get(this.component, 'templates.row', this.defaultRowTemplate);\n }\n return rowTemplate;\n }\n get headerTemplate() {\n let headerTemplate;\n if (utils_1.Evaluator.noeval) {\n headerTemplate = this.displayAsTable ?\n components_1.editgrid.tableHeader\n : components_1.editgrid.header;\n }\n else {\n headerTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableHeader', this.defaultHeaderTemplate)\n : lodash_1.default.get(this.component, 'templates.header', this.defaultHeaderTemplate);\n }\n return headerTemplate;\n }\n /**\n * Returns true if the component has nested components which don't trigger changes on the root level\n */ //\n get hasScopedChildren() {\n return !this.inlineEditMode;\n }\n get defaultSchema() {\n return EditGridComponent.schema();\n }\n get emptyValue() {\n return [];\n }\n get editgridKey() {\n return `editgrid-${this.key}`;\n }\n get rowRef() {\n return `${this.editgridKey}-row`;\n }\n get rowElements() {\n return this.refs[this.rowRef];\n }\n get rowRefs() {\n return this.refs[`editgrid-${this.component.key}-row`];\n }\n get addRowRef() {\n return `${this.editgridKey}-addRow`;\n }\n get addRowElements() {\n return this.refs[this.addRowRef];\n }\n get saveRowRef() {\n return `${this.editgridKey}-saveRow`;\n }\n get saveRowElements() {\n return this.refs[this.saveRowRef];\n }\n get cancelRowRef() {\n return `${this.editgridKey}-cancelRow`;\n }\n get cancelRowElements() {\n return this.refs[this.cancelRowRef];\n }\n get inlineEditMode() {\n return this.component.inlineEdit;\n }\n get saveEditMode() {\n return !this.inlineEditMode;\n }\n get minLength() {\n return this.builderMode ? 0 : lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n get data() {\n return this._data;\n }\n get dataValue() {\n return super.dataValue || [];\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get displayAsTable() {\n return this.component.displayAsTable;\n }\n set data(value) {\n this._data = value;\n const data = this.dataValue;\n (this.editRows || []).forEach((row, index) => {\n if (!data[index] && row.state !== EditRowState.New) {\n data[index] = {};\n }\n const rowData = data[index] || {};\n row.data = rowData;\n row.components.forEach((component) => {\n component.data = rowData;\n });\n });\n }\n get iteratableRows() {\n return this.editRows;\n }\n get defaultValue() {\n const value = super.defaultValue;\n const defaultValue = Array.isArray(value) ? value : [];\n lodash_1.default.times(this.minLength - defaultValue.length, () => defaultValue.push({}));\n return defaultValue;\n }\n constructor(...args) {\n super(...args);\n this.type = 'editgrid';\n }\n hasRemoveButtons() {\n return !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n init() {\n if (this.builderMode) {\n this.editRows = [];\n return super.init();\n }\n this.components = this.components || [];\n const dataValue = this.dataValue;\n const openWhenEmpty = !dataValue.length && this.component.openWhenEmpty;\n if (openWhenEmpty) {\n const dataObj = {};\n this.editRows = [];\n this.createRow(dataObj, 0);\n }\n else {\n this.editRows = dataValue.map((row, rowIndex) => ({\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n rowIndex,\n }));\n }\n this.prevHasAddButton = this.hasAddButton();\n this.checkData();\n this.setVariableTypeComponents();\n if (this.variableTypeComponentsIndexes.length) {\n lodash_1.default.each(this.editRows || [], (editRow, rowIndex) => this.checkRowVariableTypeComponents(editRow, rowIndex));\n }\n }\n checkRowVariableTypeComponents(editRow, rowIndex) {\n const rowComponents = editRow.components;\n if (lodash_1.default.some(this.variableTypeComponentsIndexes, (compIndex) => {\n const variableTypeComp = rowComponents[compIndex];\n return variableTypeComp.type !== variableTypeComp.component.type;\n })) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex, true);\n }\n }\n setVariableTypeComponents() {\n //set components which type is changing within a row (e.g.,by mergeComponentSchema action)\n this.variableTypeComponentsIndexes = [];\n lodash_1.default.each(this.component.components, (comp, index) => {\n if (comp.typeChangeEnabled) {\n this.variableTypeComponentsIndexes.push(index);\n }\n });\n }\n isOpen(editRow) {\n return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);\n }\n isComponentVisibleInSomeRow(component) {\n const rows = this.editRows;\n const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];\n const savedRows = rows.filter(row => lodash_1.default.includes(savedStates, row.state));\n this.visibleInHeader = this.visibleInHeader || [];\n const changeVisibleInHeader = (component, isVisible) => {\n if (!isVisible) {\n lodash_1.default.remove(this.visibleInHeader, (key) => key === component.key);\n }\n if (isVisible && !lodash_1.default.includes(this.visibleInHeader, component.key)) {\n this.visibleInHeader.push(component.key);\n }\n };\n if (lodash_1.default.isEmpty(rows)) {\n const rowComponents = this.createRowComponents({}, 0);\n let checkComponent;\n (0, utils_1.eachComponent)(rowComponents, (comp) => {\n if (comp.component.key === component.key) {\n checkComponent = comp;\n }\n comp.checkConditions();\n });\n const isVisible = checkComponent ? checkComponent.visible : true;\n [...this.components].forEach((comp) => this.removeComponent(comp, this.components));\n changeVisibleInHeader(component, isVisible);\n return isVisible;\n }\n const isOpenRowWhenEmpty = lodash_1.default.get(this.component, 'openWhenEmpty') && rows.length === 1 && rows[0].state === EditRowState.New;\n if (!lodash_1.default.isEmpty(rows) && lodash_1.default.isEmpty(savedRows) && !isOpenRowWhenEmpty) {\n return lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return lodash_1.default.some(isOpenRowWhenEmpty ? rows : savedRows, (row, index) => {\n const editingRow = row.state === EditRowState.Editing;\n let isVisible;\n if (!editingRow) {\n const flattenedComponents = this.flattenComponents(index);\n const instance = flattenedComponents[component.key];\n isVisible = instance ? instance.visible : true;\n changeVisibleInHeader(component, isVisible);\n }\n else {\n isVisible = lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return isVisible;\n });\n }\n render(children) {\n if (this.builderMode) {\n return super.render();\n }\n const dataValue = this.dataValue;\n const headerTemplate = this.headerTemplate;\n const t = this.t.bind(this);\n const templateName = this.displayAsTable ? 'editgridTable' : 'editgrid';\n return super.render(children || this.renderTemplate(templateName, {\n ref: {\n row: this.rowRef,\n addRow: this.addRowRef,\n saveRow: this.saveRowRef,\n cancelRow: this.cancelRowRef,\n },\n header: this.renderString(headerTemplate, {\n displayValue: (component) => this.displayComponentValue(component, true),\n components: this.component.components,\n value: dataValue,\n t\n }),\n footer: this.renderString(lodash_1.default.get(this.component, 'templates.footer'), {\n components: this.component.components,\n value: dataValue,\n t\n }),\n rows: this.editRows.map(this.renderRow.bind(this)),\n openRows: this.editRows.map((row) => this.isOpen(row)),\n errors: this.editRows.map((row) => row.error),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons: this.hasRemoveButtons(),\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n const templateName = this.displayAsTable && this.prevHasAddButton ? 'tableComponents' : 'components';\n return this.renderTemplate(templateName, {\n children,\n components,\n });\n }\n attach(element) {\n if (this.builderMode) {\n return super.attach(element);\n }\n this.loadRefs(element, {\n [this.addRowRef]: 'multiple',\n [this.saveRowRef]: 'multiple',\n [this.cancelRowRef]: 'multiple',\n [this.rowRef]: 'multiple',\n });\n this.addRowElements.forEach((addButton) => {\n this.addEventListener(addButton, 'click', () => this.addRow());\n });\n let openRowCount = 0;\n this.rowElements.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.isRowSelected) {\n row.classList.add('selected');\n }\n if (this.isOpen(editRow)) {\n this.attachComponents(row, editRow.components);\n this.addEventListener(this.saveRowElements[openRowCount], 'click', () => this.saveRow(rowIndex, true));\n this.addEventListener(this.cancelRowElements[openRowCount], 'click', () => this.cancelRow(rowIndex));\n openRowCount++;\n }\n else {\n // Attach edit and remove button events.\n [\n {\n className: 'removeRow',\n event: 'click',\n action: () => this.removeRow(rowIndex, true),\n },\n {\n className: 'editRow',\n event: 'click',\n action: () => {\n this.editRow(rowIndex).then(() => {\n var _a;\n if (this.component.rowDrafts) {\n const errors = this.validateRow(editRow, false);\n const shouldShowRowErrorsAlert = this.component.modal && errors.length && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted);\n if (shouldShowRowErrorsAlert) {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n }\n });\n },\n },\n {\n className: 'row',\n event: 'click',\n action: () => {\n row.classList.toggle('selected');\n let eventName = 'editGridSelectRow';\n if (Array.from(row.classList).includes('selected')) {\n editRow.isRowSelected = true;\n }\n else {\n delete editRow.isRowSelected;\n eventName = 'editGridUnSelectRow';\n }\n this.emit(eventName, {\n component: this.component,\n data: this.dataValue[rowIndex]\n });\n },\n }\n ].forEach(({ className, event, action, }) => {\n const elements = row.getElementsByClassName(className);\n Array.prototype.forEach.call(elements, (element) => {\n if (this.options.pdf && lodash_1.default.intersection(element.classList, ['editRow', 'removeRow']).length) {\n element.style.display = 'none';\n }\n else {\n this.addEventListener(element, event, action);\n }\n });\n });\n }\n });\n // Add open class to the element if any edit grid row is open\n if (openRowCount) {\n this.addClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n else {\n this.removeClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n messageContainer: 'single-scope',\n });\n return superAttach;\n }\n flattenRowDataValue(dataValue) {\n const flattened = {};\n Object.keys(dataValue).forEach((key) => {\n if (lodash_1.default.isObject(dataValue[key]) && !lodash_1.default.isNil(dataValue[key])) {\n Object.assign(flattened, this.flattenRowDataValue(dataValue[key]));\n }\n else {\n flattened[key] = dataValue[key];\n }\n });\n return flattened;\n }\n isComponentVisibleInRow(component, flattenedComponents) {\n const instance = flattenedComponents[component.key];\n return instance ? instance.visible : true;\n }\n displayComponentValue(component, header) {\n return !!((!component.hasOwnProperty('tableView') || component.tableView)\n && header ? this.isComponentVisibleInSomeRow(component) : lodash_1.default.includes(this.visibleInHeader, component.key));\n }\n renderRow(row, rowIndex) {\n const dataValue = this.dataValue;\n if (this.isOpen(row)) {\n return this.renderComponents(row.components);\n }\n else {\n const flattenedComponents = this.flattenComponents(rowIndex);\n const rowTemplate = this.rowTemplate;\n return this.renderString(rowTemplate, {\n row: dataValue[rowIndex] || {},\n data: this.data,\n rowIndex,\n components: this.component.components,\n flattenedComponents,\n displayValue: (component) => this.displayComponentValue(component),\n isVisibleInRow: (component) => this.isComponentVisibleInRow(component, flattenedComponents),\n getView: (component, data) => {\n var _a, _b;\n const instance = flattenedComponents[component.key];\n const view = instance ? instance.getView(data || instance.dataValue) : '';\n // If there is an html tag in view, don't allow it to be injected in template\n const htmlTagRegExp = new RegExp('<(.*?)>');\n return typeof view === 'string' && view.length && !((_a = instance.component) === null || _a === void 0 ? void 0 : _a.template) && htmlTagRegExp.test(view) && ((_b = instance.component) === null || _b === void 0 ? void 0 : _b.inputFormat) !== 'html'\n ? `<input type=\"text\" value=\"${view.replace(/\"/g, '&quot;')}\" readonly/>`\n : view;\n },\n state: this.editRows[rowIndex].state,\n t: this.t.bind(this)\n });\n }\n }\n eachComponent(fn, rowIndex) {\n lodash_1.default.each(this.getComponents(rowIndex), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => {\n var _a;\n const rowData = this.dataValue[component.rowIndex];\n const editRowData = (_a = this.editRows[component.rowIndex]) === null || _a === void 0 ? void 0 : _a.data;\n component.data = rowData || editRowData;\n });\n }\n flattenComponents(rowIndex) {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n }, rowIndex);\n return result;\n }\n getComponents(rowIndex) {\n // Ensure editrows is set.\n this.editRows = this.editRows || [];\n return this.builderMode\n ? super.getComponents()\n : lodash_1.default.isNumber(rowIndex)\n ? (this.editRows[rowIndex].components || [])\n : this.editRows.reduce((result, row) => result.concat(row.components || []), []);\n }\n destroyComponents(rowIndex) {\n if (this.builderMode) {\n return super.destroyComponents();\n }\n const components = this.getComponents(rowIndex).slice();\n components.forEach((comp) => this.removeComponent(comp, this.components));\n }\n createRow(dataObj, rowIndex) {\n const editRow = {\n components: this.createRowComponents(dataObj, rowIndex),\n data: dataObj,\n state: EditRowState.New,\n backup: null,\n error: null,\n rowIndex,\n };\n this.editRows.push(editRow);\n if (this.inlineEditMode) {\n this.dataValue.push(dataObj);\n }\n return editRow;\n }\n addRow() {\n if (this.options.readOnly) {\n return;\n }\n const dataObj = {};\n const rowIndex = this.editRows.length;\n const editRow = this.createRow(dataObj, rowIndex);\n if (editRow.state === EditRowState.New) {\n this.emptyRow = (0, utils_1.fastCloneDeep)(editRow.data);\n }\n if (this.inlineEditMode) {\n this.triggerChange();\n }\n this.emit('editGridAddRow', {\n component: this.component,\n row: editRow,\n });\n this.processRow('checkData', null, {}, editRow.data, editRow.components);\n if (this.component.modal) {\n this.addRowModal(rowIndex);\n }\n else {\n this.redraw();\n }\n return editRow;\n }\n addRowModal(rowIndex) {\n const modalContent = this.ce('div');\n const editRow = this.editRows[rowIndex];\n editRow.willBeSaved = false;\n const { components } = editRow;\n modalContent.innerHTML = this.renderComponents(components);\n const dialog = this.component.modal ? this.createModal(modalContent, {}, () => this.showDialog(rowIndex)) : undefined;\n dialog.classList.add(`editgrid-row-modal-${this.id}`);\n editRow.dialog = dialog;\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n this.alert = new Alert_1.default(dialog.refs.dialogContents, this);\n this.addEventListener(dialog, 'close', () => {\n if (!editRow.willBeSaved) {\n if (this.editRows[rowIndex] && this.editRows[rowIndex].state !== EditRowState.New) {\n this.editRows[rowIndex].components.forEach((comp) => {\n comp.setPristine(true);\n });\n }\n this.cancelRow(rowIndex);\n }\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n // Remove references to dialog elements to prevent possible in some cases memory leaks\n delete editRow.confirmationDialog;\n delete editRow.dialog;\n });\n dialog.refs.dialogContents.appendChild(this.ce('button', {\n class: 'btn btn-primary',\n onClick: () => {\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const errors = this.validateRow(editRow, true);\n if (!errors.length || this.component.rowDrafts) {\n editRow.willBeSaved = true;\n dialog.close();\n this.saveRow(rowIndex, true);\n }\n else {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n },\n }, this.component.saveRow || 'Save'));\n return this.attachComponents(modalContent, components);\n }\n showDialog(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow.state === EditRowState.New ? lodash_1.default.isEqual(this.emptyRow, editRow.data) : lodash_1.default.isEqual(editRow.backup, editRow.data)) {\n return Promise.resolve();\n }\n const wrapper = this.ce('div', { ref: 'confirmationDialog' });\n const dialogContent = this.component.dialogTemplate || this.defaultDialogTemplate;\n wrapper.innerHTML = dialogContent;\n wrapper.refs = {};\n this.loadRefs.call(wrapper, wrapper, {\n dialogHeader: 'single',\n dialogCancelButton: 'single',\n dialogYesButton: 'single',\n });\n const dialog = this.createModal(wrapper);\n dialog.classList.add(`editgrid-row-modal-confirmation-${this.id}`);\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n let dialogResult;\n const promise = new Promise((resolve, reject) => {\n dialogResult = { resolve, reject };\n });\n this.addEventListener(wrapper.refs.dialogYesButton, 'click', (event) => {\n close(event);\n dialogResult.resolve();\n });\n this.addEventListener(wrapper.refs.dialogCancelButton, 'click', (event) => {\n close(event);\n dialogResult.reject();\n });\n editRow.confirmationDialog = dialog;\n return promise;\n }\n editRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n const isAlreadyEditing = editRow.state === EditRowState.Editing || editRow.state === EditRowState.New;\n if (!editRow || isAlreadyEditing) {\n return Promise.resolve();\n }\n editRow.prevState = editRow.state;\n editRow.state = this.options.readOnly ? EditRowState.Viewing : EditRowState.Editing;\n if (this.lazyLoad && (editRow.components.length === 0)) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex);\n }\n const dataSnapshot = (0, utils_1.fastCloneDeep)(editRow.data);\n if (this.inlineEditMode) {\n editRow.backup = dataSnapshot;\n }\n else {\n editRow.backup = (0, utils_1.fastCloneDeep)(editRow.data);\n editRow.data = dataSnapshot;\n this.restoreRowContext(editRow);\n }\n if (this.component.modal) {\n return this.addRowModal(rowIndex);\n }\n return this.redraw();\n }\n clearErrors(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow && Array.isArray(editRow.components)) {\n editRow.components.forEach((comp) => {\n comp.setPristine(true);\n comp.setCustomValidity('');\n });\n }\n }\n cancelRow(rowIndex) {\n if (this.options.readOnly) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n switch (editRow.state) {\n case EditRowState.New: {\n editRow.state = EditRowState.Removed;\n this.clearErrors(rowIndex);\n this.destroyComponents(rowIndex);\n if (this.inlineEditMode) {\n this.splice(rowIndex);\n }\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n break;\n }\n case EditRowState.Editing: {\n editRow.state = editRow.prevState;\n if (this.inlineEditMode) {\n this.dataValue[rowIndex] = editRow.backup;\n }\n editRow.data = editRow.backup;\n editRow.backup = null;\n this.restoreRowContext(editRow);\n this.clearErrors(rowIndex);\n break;\n }\n }\n this.emit('editGridCancelRow', {\n instance: this,\n component: this.component,\n editRow,\n });\n this.checkValidity(null, true);\n this.redraw();\n if (this.component.rowDrafts) {\n this.checkValidity(this.data, false);\n }\n }\n saveRow(rowIndex, modified) {\n var _a, _b;\n const editRow = this.editRows[rowIndex];\n if (this.options.readOnly) {\n return;\n }\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const errors = this.validateRow(editRow, true);\n if (!this.component.rowDrafts) {\n if (errors.length) {\n return false;\n }\n }\n if (this.saveEditMode) {\n const dataValue = this.dataValue;\n if ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.component.typeChangeEnabled) {\n this.root.focusedComponent = null;\n }\n switch (editRow.state) {\n case EditRowState.New: {\n const newIndex = dataValue.length;\n dataValue.push(editRow.data);\n editRow.components.forEach(component => component.rowIndex = newIndex);\n if (rowIndex !== newIndex) {\n this.editRows.splice(rowIndex, 1);\n this.editRows.splice(newIndex, 0, editRow);\n }\n break;\n }\n case EditRowState.Editing: {\n dataValue[rowIndex] = editRow.data;\n break;\n }\n }\n }\n editRow.state = this.component.rowDrafts && errors.length ? EditRowState.Draft : EditRowState.Saved;\n editRow.backup = null;\n this.updateValue();\n this.emit('editGridSaveRow', {\n component: this.component,\n row: editRow.data,\n instance: this\n });\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n if (this.component.rowDrafts) {\n editRow.components.forEach(comp => comp.setPristine(this.pristine));\n }\n this.checkValidity(null, true);\n this.redraw();\n if (editRow.alerts) {\n editRow.alerts = false;\n }\n return true;\n }\n beforeFocus(component) {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n const relativePath = this.getRelativePath(component.path);\n const arrayPath = (0, utils_1.getArrayFromComponentPath)(relativePath);\n const rowIndex = arrayPath[0];\n let rowToEditIndex = arrayPath[0];\n this.editRows.forEach((row, indexInArray) => {\n if (row.rowIndex === rowIndex) {\n rowToEditIndex = indexInArray;\n }\n });\n if (lodash_1.default.isNumber(rowToEditIndex)) {\n this.editRow(rowToEditIndex);\n }\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n });\n }\n updateRowsComponents(rowIndex) {\n this.editRows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(row.components, rowIndex + index);\n });\n }\n baseRemoveRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n editRow.state = EditRowState.Removed;\n this.destroyComponents(rowIndex);\n return editRow;\n }\n removeRow(rowIndex, modified) {\n if (this.options.readOnly) {\n return;\n }\n this.clearErrors(rowIndex);\n this.baseRemoveRow(rowIndex);\n this.splice(rowIndex);\n this.emit('editGridDeleteRow', {\n index: rowIndex\n });\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n this.updateRowsComponents(rowIndex);\n this.updateValue();\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n this.checkValidity(null, true);\n this.checkData();\n this.redraw();\n }\n createRowComponents(row, rowIndex, recreatePartially) {\n const currentRowComponents = lodash_1.default.get(this.editRows, `[${rowIndex}].components`, null);\n return this.component.components.map((col, colIndex) => {\n var _a;\n if (recreatePartially && currentRowComponents && this.variableTypeComponentsIndexes.length) {\n const currentComp = currentRowComponents[colIndex];\n const shouldRecreate = lodash_1.default.includes(this.variableTypeComponentsIndexes, colIndex) && (currentComp === null || currentComp === void 0 ? void 0 : currentComp.type) !== ((_a = currentComp === null || currentComp === void 0 ? void 0 : currentComp.component) === null || _a === void 0 ? void 0 : _a.type);\n if (!shouldRecreate) {\n return currentComp;\n }\n col = currentComp.component;\n }\n const column = lodash_1.default.clone(col);\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n options.onChange = (flags = {}, changed, modified) => {\n var _a, _b;\n if (((_a = changed.instance.root) === null || _a === void 0 ? void 0 : _a.id) && (((_b = this.root) === null || _b === void 0 ? void 0 : _b.id) !== changed.instance.root.id)) {\n changed.instance.root.triggerChange(flags, changed, modified);\n }\n else if (!this.component.modal) {\n this.triggerRootChange(flags, changed, modified);\n }\n if (this.inlineEditMode) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n this.processRow('checkData', null, Object.assign(Object.assign({}, flags), { changed }), editRow.data, editRow.components);\n this.validateRow(editRow, false);\n }\n if (this.variableTypeComponentsIndexes.length) {\n this.checkRowVariableTypeComponents(editRow, rowIndex);\n this.redraw();\n }\n };\n const comp = this.createComponent(lodash_1.default.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);\n comp.rowIndex = rowIndex;\n comp.inEditGrid = true;\n return comp;\n });\n }\n hasOpenRows() {\n return this.editRows.some(row => this.isOpen(row));\n }\n getAttachedData(data = null) {\n const ourData = (0, utils_1.fastCloneDeep)(data || this._data || this.rootValue);\n lodash_1.default.set(ourData, this.key, this.editRows.map((row) => row.data));\n return ourData;\n }\n shouldValidateDraft(editRow) {\n var _a, _b;\n // Draft rows should be validated only when there was an attempt to submit a form\n return (editRow.state === EditRowState.Draft &&\n !this.pristine &&\n !((_a = this.root) === null || _a === void 0 ? void 0 : _a.pristine) &&\n !this.hasOpenRows()) ||\n ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted);\n }\n shouldValidateRow(editRow, dirty) {\n return this.shouldValidateDraft(editRow) ||\n editRow.state === EditRowState.New ||\n editRow.state === EditRowState.Editing ||\n editRow.alerts ||\n dirty;\n }\n validateRow(editRow, dirty, forceSilentCheck) {\n var _a;\n editRow.errors = [];\n if (this.shouldValidateRow(editRow, dirty)) {\n const silentCheck = (this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck;\n const rootValue = (0, utils_1.fastCloneDeep)(this.rootValue);\n const editGridValue = lodash_1.default.get(rootValue, this.path, []);\n editGridValue[editRow.rowIndex] = editRow.data;\n lodash_1.default.set(rootValue, this.path, editGridValue);\n const validationProcessorProcess = (context) => this.validationProcessor(context, { dirty, silentCheck });\n editRow.errors = (0, process_1.processSync)({\n components: (0, utils_1.fastCloneDeep)(this.component.components).map((component) => {\n component.parentPath = `${this.path}[${editRow.rowIndex}]`;\n return component;\n }),\n data: rootValue,\n row: editRow.data,\n process: 'validateRow',\n instances: this.componentsMap,\n scope: { errors: [] },\n processors: [\n {\n process: validationProcessorProcess,\n processSync: validationProcessorProcess\n }\n ]\n }).errors;\n }\n // TODO: this is essentially running its own custom validation and should be moved into a validation rule\n if (this.component.validate && this.component.validate.row) {\n const valid = this.evaluate(this.component.validate.row, {\n valid: (editRow.length === 0),\n row: editRow.data\n }, 'valid', true);\n if (valid.toString() !== 'true') {\n editRow.errors.push({\n type: 'error',\n rowError: true,\n message: valid.toString()\n });\n }\n if (valid === null) {\n editRow.errors.push({\n type: 'error',\n message: `Invalid row validation for ${this.key}`\n });\n }\n }\n if (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted)) {\n this.showRowErrorAlerts(editRow, editRow.errors);\n }\n return editRow.errors;\n }\n showRowErrorAlerts(editRow, errors) {\n if (editRow.alerts) {\n if (this.alert) {\n if (errors.length) {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n else {\n this.alert.clear();\n this.alert = null;\n }\n }\n }\n }\n /**\n * Return that this component processes its own validation.\n */\n get processOwnValidation() {\n return true;\n }\n checkComponentValidity(data, dirty, row, options = {}, errors = []) {\n var _a, _b;\n const { silentCheck } = options;\n const superValid = super.checkComponentValidity(data, dirty, row, options, errors);\n // If super tells us that component invalid and there is no need to update alerts, just return false\n if (!superValid && (!this.alert && !this.hasOpenRows())) {\n return false;\n }\n let rowsEditing = false;\n const allRowErrors = [];\n this.editRows.forEach((editRow, index) => {\n // Trigger all errors on the row.\n const rowErrors = this.validateRow(editRow, dirty, silentCheck);\n errors.push(...rowErrors);\n allRowErrors.push(...rowErrors);\n if (this.rowRefs) {\n const rowContainer = this.rowRefs[index];\n if (rowContainer) {\n const errorContainer = rowContainer.querySelector('.editgrid-row-error');\n if (rowErrors.length && errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n const rowError = rowErrors.find(error => error.rowError);\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(rowError ? rowError.message : this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n }\n // If this is a dirty check, and any rows are still editing, we need to throw validation error.\n rowsEditing |= (dirty && this.isOpen(editRow));\n });\n if (allRowErrors.length) {\n if (!silentCheck && (dirty || this.dirty) && (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted))) {\n this.setCustomValidity(this.t(this.errorMessage('invalidRowsError')), dirty);\n this.removeClass(this.element, 'has-error');\n }\n return false;\n }\n else if (rowsEditing && this.saveEditMode && !this.component.openWhenEmpty) {\n this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);\n return false;\n }\n const message = this.invalid || this.invalidMessage(data, dirty, false, row);\n if (allRowErrors.length && ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted) && !message) {\n this._errors = this.setCustomValidity(message, dirty);\n errors.push(...this._errors);\n this.root.showErrors([message]);\n }\n else {\n this._errors = this.setCustomValidity(message, dirty);\n errors.push(...this._errors);\n }\n return superValid;\n }\n setRowInvalid(ref, index) {\n const editRow = this.editRows[index];\n const errorContainer = ref.querySelector('.editgrid-row-error');\n if (errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n changeState(changed, flags) {\n if (this.visible && (changed || (flags.resetValue && this.component.modalEdit))) {\n this.rebuild();\n }\n else {\n this.redraw();\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n value = this.defaultValue;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n return false;\n }\n }\n const changed = this.hasChanged(value, this.dataValue);\n if (this.parent && !this.options.server) {\n this.parent.checkComponentConditions();\n }\n this.dataValue = value;\n // Refresh editRow data when data changes.\n this.dataValue.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n editRow.data = row;\n this.restoreRowContext(editRow, flags);\n editRow.state = EditRowState.Saved;\n editRow.backup = null;\n editRow.errors = [];\n }\n else {\n this.editRows[rowIndex] = {\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n errors: [],\n };\n }\n });\n let { length: dataLength } = this.dataValue;\n // If the last row is a new row, then do not remove it.\n if (this.editRows[dataLength] && (this.editRows[dataLength].state === EditRowState.New)) {\n dataLength = (dataLength + 1);\n }\n this.editRows.slice(dataLength).forEach((editRow, index) => this.baseRemoveRow(dataLength + index));\n this.editRows = this.editRows.slice(0, dataLength);\n this.openWhenEmpty();\n this.updateOnChange(flags, changed);\n // do not call checkData with server option, it is called when change is triggered in updateOnChange\n if (!this.options.server) {\n this.checkData();\n }\n this.changeState(changed, flags);\n return changed;\n }\n openWhenEmpty() {\n const shouldBeOpened = !this.dataValue.length && this.component.openWhenEmpty;\n const hasNoRows = !this.editRows.length;\n if (hasNoRows && shouldBeOpened && !this.builderMode) {\n const dataObj = {};\n this.createRow(dataObj, 0);\n }\n }\n restoreRowContext(editRow, flags = {}) {\n editRow.components.forEach((component) => {\n component.data = editRow.data;\n this.setNestedValue(component, editRow.data, flags);\n });\n }\n emptyRows() {\n this.editRows.forEach((editRow, index) => this.destroyComponents(index));\n this.editRows = [];\n }\n resetValue() {\n super.resetValue();\n this.emptyRows();\n }\n}\nexports[\"default\"] = EditGridComponent;\nEditGridComponent.prototype.hasChanged = Component_1.default.prototype.hasChanged;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/editgrid/EditGrid.js?");
6523
+ 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 process_1 = __webpack_require__(/*! @formio/core/process */ \"./node_modules/@formio/core/lib/process/index.js\");\nconst components_1 = __webpack_require__(/*! @formio/bootstrap/components */ \"./node_modules/@formio/bootstrap/lib/cjs/templates/components/index.js\");\nconst NestedArrayComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nestedarray/NestedArrayComponent */ \"./lib/cjs/components/_classes/nestedarray/NestedArrayComponent.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst Alert_1 = __importDefault(__webpack_require__(/*! ../alert/Alert */ \"./lib/cjs/components/alert/Alert.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst EditRowState = {\n New: 'new',\n Editing: 'editing',\n Saved: 'saved',\n Viewing: 'viewing',\n Removed: 'removed',\n Draft: 'draft',\n};\nclass EditGridComponent extends NestedArrayComponent_1.default {\n static schema(...extend) {\n return NestedArrayComponent_1.default.schema({\n type: 'editgrid',\n label: 'Edit Grid',\n key: 'editGrid',\n clearOnHide: true,\n input: true,\n tree: true,\n removeRow: 'Cancel',\n defaultOpen: false,\n openWhenEmpty: false,\n modal: false,\n components: [],\n inlineEdit: false,\n templates: {\n header: EditGridComponent.defaultHeaderTemplate,\n row: EditGridComponent.defaultRowTemplate,\n tableHeader: EditGridComponent.defaultTableHeaderTemplate,\n tableRow: EditGridComponent.defaultTableRowTemplate,\n footer: '',\n },\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Edit Grid',\n icon: 'tasks',\n group: 'data',\n documentation: '/userguide/form-building/data-components#edit-grid',\n showPreview: false,\n weight: 30,\n schema: EditGridComponent.schema(),\n };\n }\n static get defaultHeaderTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">{{ t(component.label) }}</div>\n {% } %}\n {% }) %}\n </div>`;\n }\n static get defaultTableHeaderTemplate() {\n return `\n <tr>\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">{{ component.label }}</td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">Actions</td>\n {% } %}\n </tr>\n `;\n }\n static get defaultRowTemplate() {\n return `<div class=\"row\">\n {% util.eachComponent(components, function(component) { %}\n {% if (displayValue(component)) { %}\n <div class=\"col-sm-2\">\n {{ isVisibleInRow(component) ? getView(component, row[component.key]) : ''}}\n </div>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <div class=\"col-sm-2\">\n <div class=\"btn-group pull-right\">\n <button class=\"btn btn-default btn-light btn-sm editRow\"><i class=\"{{ iconClass('pen-fill') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </div>\n {% } %}\n </div>`;\n }\n static get defaultTableRowTemplate() {\n return `\n {% util.eachComponent(components, function(component) { %}\n {% if (!component.hasOwnProperty('tableView') || component.tableView) { %}\n <td class=\"editgrid-table-column\">\n {{ getView(component, row[component.key]) }}\n </td>\n {% } %}\n {% }) %}\n {% if (!instance.options.readOnly && !instance.disabled) { %}\n <td class=\"editgrid-table-column\">\n <div class=\"btn-group\">\n <button class=\"btn btn-default btn-light btn-sm editRow\" aria-label=\"{{ t('Edit row') }}\"><i class=\"{{ iconClass('pen-fill') }}\"></i></button>\n {% if (!instance.hasRemoveButtons || instance.hasRemoveButtons()) { %}\n <button class=\"btn btn-danger btn-sm removeRow\" aria-label=\"{{ t('Remove row') }}\"><i class=\"{{ iconClass('trash') }}\"></i></button>\n {% } %}\n </div>\n </td>\n {% } %}\n `;\n }\n get defaultDialogTemplate() {\n return `\n <h3 ${this._referenceAttributeName}=\"dialogHeader\">${this.t('Do you want to clear data?')}</h3>\n <div style=\"display:flex; justify-content: flex-end;\">\n <button ${this._referenceAttributeName}=\"dialogCancelButton\" class=\"btn btn-secondary\" aria-label=\"${this.t('Cancel')}\">${this.t('Cancel')}</button>\n <button ${this._referenceAttributeName}=\"dialogYesButton\" class=\"btn btn-danger\" aria-label=\"${this.t('Yes, delete it')}\">${this.t('Yes, delete it')}</button>\n </div>\n `;\n }\n get defaultRowTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableRowTemplate\n : EditGridComponent.defaultRowTemplate;\n }\n get defaultHeaderTemplate() {\n return this.displayAsTable\n ? EditGridComponent.defaultTableHeaderTemplate\n : EditGridComponent.defaultHeaderTemplate;\n }\n get rowTemplate() {\n let rowTemplate;\n if (utils_1.Evaluator.noeval) {\n rowTemplate = this.displayAsTable ?\n components_1.editgrid.tableRow\n : components_1.editgrid.row;\n }\n else {\n rowTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableRow', this.defaultRowTemplate)\n : lodash_1.default.get(this.component, 'templates.row', this.defaultRowTemplate);\n }\n return rowTemplate;\n }\n get headerTemplate() {\n let headerTemplate;\n if (utils_1.Evaluator.noeval) {\n headerTemplate = this.displayAsTable ?\n components_1.editgrid.tableHeader\n : components_1.editgrid.header;\n }\n else {\n headerTemplate = this.displayAsTable ?\n lodash_1.default.get(this.component, 'templates.tableHeader', this.defaultHeaderTemplate)\n : lodash_1.default.get(this.component, 'templates.header', this.defaultHeaderTemplate);\n }\n return headerTemplate;\n }\n /**\n * Returns true if the component has nested components which don't trigger changes on the root level\n */ //\n get hasScopedChildren() {\n return !this.inlineEditMode;\n }\n get defaultSchema() {\n return EditGridComponent.schema();\n }\n get emptyValue() {\n return [];\n }\n get editgridKey() {\n return `editgrid-${this.key}`;\n }\n get rowRef() {\n return `${this.editgridKey}-row`;\n }\n get rowElements() {\n return this.refs[this.rowRef];\n }\n get rowRefs() {\n return this.refs[`editgrid-${this.component.key}-row`];\n }\n get addRowRef() {\n return `${this.editgridKey}-addRow`;\n }\n get addRowElements() {\n return this.refs[this.addRowRef];\n }\n get saveRowRef() {\n return `${this.editgridKey}-saveRow`;\n }\n get saveRowElements() {\n return this.refs[this.saveRowRef];\n }\n get cancelRowRef() {\n return `${this.editgridKey}-cancelRow`;\n }\n get cancelRowElements() {\n return this.refs[this.cancelRowRef];\n }\n get inlineEditMode() {\n return this.component.inlineEdit;\n }\n get saveEditMode() {\n return !this.inlineEditMode;\n }\n get minLength() {\n return this.builderMode ? 0 : lodash_1.default.get(this.component, 'validate.minLength', 0);\n }\n get data() {\n return this._data;\n }\n get dataValue() {\n return super.dataValue || [];\n }\n set dataValue(value) {\n super.dataValue = value;\n }\n get displayAsTable() {\n return this.component.displayAsTable;\n }\n set data(value) {\n this._data = value;\n const data = this.dataValue;\n (this.editRows || []).forEach((row, index) => {\n if (!data[index] && row.state !== EditRowState.New) {\n data[index] = {};\n }\n const rowData = data[index] || {};\n row.data = rowData;\n row.components.forEach((component) => {\n component.data = rowData;\n });\n });\n }\n get iteratableRows() {\n return this.editRows;\n }\n get defaultValue() {\n const value = super.defaultValue;\n const defaultValue = Array.isArray(value) ? value : [];\n lodash_1.default.times(this.minLength - defaultValue.length, () => defaultValue.push({}));\n return defaultValue;\n }\n constructor(...args) {\n super(...args);\n this.type = 'editgrid';\n }\n hasRemoveButtons() {\n return !this.component.disableAddingRemovingRows &&\n !this.options.readOnly &&\n !this.disabled &&\n this.fullMode &&\n (this.dataValue.length > lodash_1.default.get(this.component, 'validate.minLength', 0));\n }\n init() {\n if (this.builderMode) {\n this.editRows = [];\n return super.init();\n }\n this.components = this.components || [];\n const dataValue = this.dataValue;\n const openWhenEmpty = !dataValue.length && this.component.openWhenEmpty;\n if (openWhenEmpty) {\n const dataObj = {};\n this.editRows = [];\n this.createRow(dataObj, 0);\n }\n else {\n this.editRows = dataValue.map((row, rowIndex) => ({\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n error: null,\n rowIndex,\n }));\n }\n this.prevHasAddButton = this.hasAddButton();\n this.checkData();\n this.setVariableTypeComponents();\n if (this.variableTypeComponentsIndexes.length) {\n lodash_1.default.each(this.editRows || [], (editRow, rowIndex) => this.checkRowVariableTypeComponents(editRow, rowIndex));\n }\n }\n checkRowVariableTypeComponents(editRow, rowIndex) {\n const rowComponents = editRow.components;\n if (lodash_1.default.some(this.variableTypeComponentsIndexes, (compIndex) => {\n const variableTypeComp = rowComponents[compIndex];\n return variableTypeComp.type !== variableTypeComp.component.type;\n })) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex, true);\n }\n }\n setVariableTypeComponents() {\n //set components which type is changing within a row (e.g.,by mergeComponentSchema action)\n this.variableTypeComponentsIndexes = [];\n lodash_1.default.each(this.component.components, (comp, index) => {\n if (comp.typeChangeEnabled) {\n this.variableTypeComponentsIndexes.push(index);\n }\n });\n }\n isOpen(editRow) {\n return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);\n }\n isComponentVisibleInSomeRow(component) {\n const rows = this.editRows;\n const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];\n const savedRows = rows.filter(row => lodash_1.default.includes(savedStates, row.state));\n this.visibleInHeader = this.visibleInHeader || [];\n const changeVisibleInHeader = (component, isVisible) => {\n if (!isVisible) {\n lodash_1.default.remove(this.visibleInHeader, (key) => key === component.key);\n }\n if (isVisible && !lodash_1.default.includes(this.visibleInHeader, component.key)) {\n this.visibleInHeader.push(component.key);\n }\n };\n if (lodash_1.default.isEmpty(rows)) {\n const rowComponents = this.createRowComponents({}, 0);\n let checkComponent;\n (0, utils_1.eachComponent)(rowComponents, (comp) => {\n if (comp.component.key === component.key) {\n checkComponent = comp;\n }\n comp.checkConditions();\n });\n const isVisible = checkComponent ? checkComponent.visible : true;\n [...this.components].forEach((comp) => this.removeComponent(comp, this.components));\n changeVisibleInHeader(component, isVisible);\n return isVisible;\n }\n const isOpenRowWhenEmpty = lodash_1.default.get(this.component, 'openWhenEmpty') && rows.length === 1 && rows[0].state === EditRowState.New;\n if (!lodash_1.default.isEmpty(rows) && lodash_1.default.isEmpty(savedRows) && !isOpenRowWhenEmpty) {\n return lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return lodash_1.default.some(isOpenRowWhenEmpty ? rows : savedRows, (row, index) => {\n const editingRow = row.state === EditRowState.Editing;\n let isVisible;\n if (!editingRow) {\n const flattenedComponents = this.flattenComponents(index);\n const instance = flattenedComponents[component.key];\n isVisible = instance ? instance.visible : true;\n changeVisibleInHeader(component, isVisible);\n }\n else {\n isVisible = lodash_1.default.includes(this.visibleInHeader, component.key);\n }\n return isVisible;\n });\n }\n render(children) {\n if (this.builderMode) {\n return super.render();\n }\n const dataValue = this.dataValue;\n const headerTemplate = this.headerTemplate;\n const t = this.t.bind(this);\n const templateName = this.displayAsTable ? 'editgridTable' : 'editgrid';\n return super.render(children || this.renderTemplate(templateName, {\n ref: {\n row: this.rowRef,\n addRow: this.addRowRef,\n saveRow: this.saveRowRef,\n cancelRow: this.cancelRowRef,\n },\n header: this.renderString(headerTemplate, {\n displayValue: (component) => this.displayComponentValue(component, true),\n components: this.component.components,\n value: dataValue,\n t\n }),\n footer: this.renderString(lodash_1.default.get(this.component, 'templates.footer'), {\n components: this.component.components,\n value: dataValue,\n t\n }),\n rows: this.editRows.map(this.renderRow.bind(this)),\n openRows: this.editRows.map((row) => this.isOpen(row)),\n errors: this.editRows.map((row) => row.error),\n hasAddButton: this.hasAddButton(),\n hasRemoveButtons: this.hasRemoveButtons(),\n }));\n }\n renderComponents(components) {\n components = components || this.getComponents();\n const children = components.map(component => component.render());\n const templateName = this.displayAsTable && this.prevHasAddButton ? 'tableComponents' : 'components';\n return this.renderTemplate(templateName, {\n children,\n components,\n });\n }\n attach(element) {\n if (this.builderMode) {\n return super.attach(element);\n }\n this.loadRefs(element, {\n [this.addRowRef]: 'multiple',\n [this.saveRowRef]: 'multiple',\n [this.cancelRowRef]: 'multiple',\n [this.rowRef]: 'multiple',\n });\n this.addRowElements.forEach((addButton) => {\n this.addEventListener(addButton, 'click', () => this.addRow());\n });\n let openRowCount = 0;\n this.rowElements.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow === null || editRow === void 0 ? void 0 : editRow.isRowSelected) {\n row.classList.add('selected');\n }\n if (this.isOpen(editRow)) {\n this.attachComponents(row, editRow.components);\n this.addEventListener(this.saveRowElements[openRowCount], 'click', () => this.saveRow(rowIndex, true));\n this.addEventListener(this.cancelRowElements[openRowCount], 'click', () => this.cancelRow(rowIndex));\n openRowCount++;\n }\n else {\n // Attach edit and remove button events.\n [\n {\n className: 'removeRow',\n event: 'click',\n action: () => this.removeRow(rowIndex, true),\n },\n {\n className: 'editRow',\n event: 'click',\n action: () => {\n this.editRow(rowIndex).then(() => {\n var _a;\n if (this.component.rowDrafts) {\n const errors = this.validateRow(editRow, false);\n const shouldShowRowErrorsAlert = this.component.modal && errors.length && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted);\n if (shouldShowRowErrorsAlert) {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n }\n });\n },\n },\n {\n className: 'row',\n event: 'click',\n action: () => {\n row.classList.toggle('selected');\n let eventName = 'editGridSelectRow';\n if (Array.from(row.classList).includes('selected')) {\n editRow.isRowSelected = true;\n }\n else {\n delete editRow.isRowSelected;\n eventName = 'editGridUnSelectRow';\n }\n this.emit(eventName, {\n component: this.component,\n data: this.dataValue[rowIndex]\n });\n },\n }\n ].forEach(({ className, event, action, }) => {\n const elements = row.getElementsByClassName(className);\n Array.prototype.forEach.call(elements, (element) => {\n if (this.options.pdf && lodash_1.default.intersection(element.classList, ['editRow', 'removeRow']).length) {\n element.style.display = 'none';\n }\n else {\n this.addEventListener(element, event, action);\n }\n });\n });\n }\n });\n // Add open class to the element if any edit grid row is open\n if (openRowCount) {\n this.addClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n else {\n this.removeClass(this.refs.component, `formio-component-${this.component.type}-row-open`);\n }\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n messageContainer: 'single-scope',\n });\n return superAttach;\n }\n flattenRowDataValue(dataValue) {\n const flattened = {};\n Object.keys(dataValue).forEach((key) => {\n if (lodash_1.default.isObject(dataValue[key]) && !lodash_1.default.isNil(dataValue[key])) {\n Object.assign(flattened, this.flattenRowDataValue(dataValue[key]));\n }\n else {\n flattened[key] = dataValue[key];\n }\n });\n return flattened;\n }\n isComponentVisibleInRow(component, flattenedComponents) {\n const instance = flattenedComponents[component.key];\n return instance ? instance.visible : true;\n }\n displayComponentValue(component, header) {\n return !!((!component.hasOwnProperty('tableView') || component.tableView)\n && header ? this.isComponentVisibleInSomeRow(component) : lodash_1.default.includes(this.visibleInHeader, component.key));\n }\n renderRow(row, rowIndex) {\n const dataValue = this.dataValue;\n if (this.isOpen(row)) {\n return this.renderComponents(row.components);\n }\n else {\n const flattenedComponents = this.flattenComponents(rowIndex);\n const rowTemplate = this.rowTemplate;\n return this.renderString(rowTemplate, {\n row: dataValue[rowIndex] || {},\n data: this.data,\n rowIndex,\n components: this.component.components,\n flattenedComponents,\n displayValue: (component) => this.displayComponentValue(component),\n isVisibleInRow: (component) => this.isComponentVisibleInRow(component, flattenedComponents),\n getView: (component, data) => {\n var _a, _b;\n const instance = flattenedComponents[component.key];\n const view = instance ? instance.getView(data || instance.dataValue) : '';\n // If there is an html tag in view, don't allow it to be injected in template\n const htmlTagRegExp = new RegExp('<(.*?)>');\n return typeof view === 'string' && view.length && !((_a = instance.component) === null || _a === void 0 ? void 0 : _a.template) && htmlTagRegExp.test(view) && ((_b = instance.component) === null || _b === void 0 ? void 0 : _b.inputFormat) !== 'html'\n ? `<input type=\"text\" value=\"${view.replace(/\"/g, '&quot;')}\" readonly/>`\n : view;\n },\n state: this.editRows[rowIndex].state,\n t: this.t.bind(this)\n });\n }\n }\n eachComponent(fn, rowIndex) {\n lodash_1.default.each(this.getComponents(rowIndex), (component, index) => {\n if (fn(component, index) === false) {\n return false;\n }\n });\n }\n restoreComponentsContext() {\n this.getComponents().forEach((component) => {\n var _a;\n const rowData = this.dataValue[component.rowIndex];\n const editRowData = (_a = this.editRows[component.rowIndex]) === null || _a === void 0 ? void 0 : _a.data;\n component.data = rowData || editRowData;\n });\n }\n flattenComponents(rowIndex) {\n const result = {};\n this.everyComponent((component) => {\n result[component.component.flattenAs || component.key] = component;\n }, rowIndex);\n return result;\n }\n getComponents(rowIndex) {\n var _a;\n // Ensure editrows is set.\n this.editRows = this.editRows || [];\n return this.builderMode\n ? super.getComponents()\n : lodash_1.default.isNumber(rowIndex)\n ? (((_a = this.editRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.components) || [])\n : this.editRows.reduce((result, row) => result.concat(row.components || []), []);\n }\n destroy(all = false) {\n this.calculatedValue = undefined;\n super.destroy(all);\n }\n destroyComponents(all = false, rowIndex = 0) {\n if (this.builderMode) {\n return super.destroyComponents(all);\n }\n const components = this.getComponents(rowIndex).slice();\n components.forEach((comp) => this.removeComponent(comp, this.components, all));\n }\n createRow(dataObj, rowIndex) {\n const editRow = {\n components: this.createRowComponents(dataObj, rowIndex),\n data: dataObj,\n state: EditRowState.New,\n backup: null,\n error: null,\n rowIndex,\n };\n this.editRows.push(editRow);\n if (this.inlineEditMode) {\n this.dataValue.push(dataObj);\n }\n return editRow;\n }\n addRow() {\n if (this.options.readOnly) {\n return;\n }\n const dataObj = {};\n const rowIndex = this.editRows.length;\n const editRow = this.createRow(dataObj, rowIndex);\n if (editRow.state === EditRowState.New) {\n this.emptyRow = (0, utils_1.fastCloneDeep)(editRow.data);\n }\n if (this.inlineEditMode) {\n this.triggerChange();\n }\n this.emit('editGridAddRow', {\n component: this.component,\n row: editRow,\n });\n this.processRow('checkData', null, {}, editRow.data, editRow.components);\n if (this.component.modal) {\n this.addRowModal(rowIndex);\n }\n else {\n this.redraw();\n }\n return editRow;\n }\n addRowModal(rowIndex) {\n const modalContent = this.ce('div');\n const editRow = this.editRows[rowIndex];\n editRow.willBeSaved = false;\n const { components } = editRow;\n modalContent.innerHTML = this.renderComponents(components);\n const dialog = this.component.modal ? this.createModal(modalContent, {}, () => this.showDialog(rowIndex)) : undefined;\n dialog.classList.add(`editgrid-row-modal-${this.id}`);\n editRow.dialog = dialog;\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n this.alert = new Alert_1.default(dialog.refs.dialogContents, this);\n this.addEventListener(dialog, 'close', () => {\n if (!editRow.willBeSaved) {\n if (this.editRows[rowIndex] && this.editRows[rowIndex].state !== EditRowState.New) {\n this.editRows[rowIndex].components.forEach((comp) => {\n comp.setPristine(true);\n });\n }\n this.cancelRow(rowIndex);\n }\n if (this.alert) {\n this.alert.clear();\n this.alert = null;\n }\n // Remove references to dialog elements to prevent possible in some cases memory leaks\n delete editRow.confirmationDialog;\n delete editRow.dialog;\n });\n dialog.refs.dialogContents.appendChild(this.ce('button', {\n class: 'btn btn-primary',\n onClick: () => {\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const errors = this.validateRow(editRow, true);\n if (!errors.length || this.component.rowDrafts) {\n editRow.willBeSaved = true;\n dialog.close();\n this.saveRow(rowIndex, true);\n }\n else {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n },\n }, this.component.saveRow || 'Save'));\n return this.attachComponents(modalContent, components);\n }\n showDialog(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow.state === EditRowState.New ? lodash_1.default.isEqual(this.emptyRow, editRow.data) : lodash_1.default.isEqual(editRow.backup, editRow.data)) {\n return Promise.resolve();\n }\n const wrapper = this.ce('div', { ref: 'confirmationDialog' });\n const dialogContent = this.component.dialogTemplate || this.defaultDialogTemplate;\n wrapper.innerHTML = dialogContent;\n wrapper.refs = {};\n this.loadRefs.call(wrapper, wrapper, {\n dialogHeader: 'single',\n dialogCancelButton: 'single',\n dialogYesButton: 'single',\n });\n const dialog = this.createModal(wrapper);\n dialog.classList.add(`editgrid-row-modal-confirmation-${this.id}`);\n const close = (event) => {\n event.preventDefault();\n dialog.close();\n };\n let dialogResult;\n const promise = new Promise((resolve, reject) => {\n dialogResult = { resolve, reject };\n });\n this.addEventListener(wrapper.refs.dialogYesButton, 'click', (event) => {\n close(event);\n dialogResult.resolve();\n });\n this.addEventListener(wrapper.refs.dialogCancelButton, 'click', (event) => {\n close(event);\n dialogResult.reject();\n });\n editRow.confirmationDialog = dialog;\n return promise;\n }\n editRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n const isAlreadyEditing = editRow.state === EditRowState.Editing || editRow.state === EditRowState.New;\n if (!editRow || isAlreadyEditing) {\n return Promise.resolve();\n }\n editRow.prevState = editRow.state;\n editRow.state = this.options.readOnly ? EditRowState.Viewing : EditRowState.Editing;\n if (this.lazyLoad && (editRow.components.length === 0)) {\n editRow.components = this.createRowComponents(editRow.data, rowIndex);\n }\n const dataSnapshot = (0, utils_1.fastCloneDeep)(editRow.data);\n if (this.inlineEditMode) {\n editRow.backup = dataSnapshot;\n }\n else {\n editRow.backup = (0, utils_1.fastCloneDeep)(editRow.data);\n editRow.data = dataSnapshot;\n this.restoreRowContext(editRow);\n }\n if (this.component.modal) {\n return this.addRowModal(rowIndex);\n }\n return this.redraw();\n }\n clearErrors(rowIndex) {\n const editRow = this.editRows[rowIndex];\n if (editRow && Array.isArray(editRow.components)) {\n editRow.components.forEach((comp) => {\n comp.setPristine(true);\n comp.setCustomValidity('');\n });\n }\n }\n cancelRow(rowIndex) {\n if (this.options.readOnly) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n switch (editRow.state) {\n case EditRowState.New: {\n editRow.state = EditRowState.Removed;\n this.clearErrors(rowIndex);\n this.destroyComponents(false, rowIndex);\n if (this.inlineEditMode) {\n this.splice(rowIndex);\n }\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n break;\n }\n case EditRowState.Editing: {\n editRow.state = editRow.prevState;\n if (this.inlineEditMode) {\n this.dataValue[rowIndex] = editRow.backup;\n }\n editRow.data = editRow.backup;\n editRow.backup = null;\n this.restoreRowContext(editRow);\n this.clearErrors(rowIndex);\n break;\n }\n }\n this.emit('editGridCancelRow', {\n instance: this,\n component: this.component,\n editRow,\n });\n this.checkValidity(null, true);\n this.redraw();\n if (this.component.rowDrafts) {\n this.checkValidity(this.data, false);\n }\n }\n saveRow(rowIndex, modified) {\n var _a, _b;\n const editRow = this.editRows[rowIndex];\n if (this.options.readOnly) {\n return;\n }\n // After an attempt to save, all the components inside the row should become not pristine\n if (!this.component.rowDrafts) {\n editRow.components.forEach((comp) => comp.setPristine(false));\n }\n const errors = this.validateRow(editRow, true);\n if (!this.component.rowDrafts) {\n if (errors.length) {\n return false;\n }\n }\n if (this.saveEditMode) {\n const dataValue = this.dataValue;\n if ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.component.typeChangeEnabled) {\n this.root.focusedComponent = null;\n }\n switch (editRow.state) {\n case EditRowState.New: {\n const newIndex = dataValue.length;\n dataValue.push(editRow.data);\n editRow.components.forEach(component => component.rowIndex = newIndex);\n if (rowIndex !== newIndex) {\n this.editRows.splice(rowIndex, 1);\n this.editRows.splice(newIndex, 0, editRow);\n }\n break;\n }\n case EditRowState.Editing: {\n dataValue[rowIndex] = editRow.data;\n break;\n }\n }\n }\n editRow.state = this.component.rowDrafts && errors.length ? EditRowState.Draft : EditRowState.Saved;\n editRow.backup = null;\n this.updateValue();\n this.emit('editGridSaveRow', {\n component: this.component,\n row: editRow.data,\n instance: this\n });\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n if (this.component.rowDrafts) {\n editRow.components.forEach(comp => comp.setPristine(this.pristine));\n }\n this.checkValidity(null, true);\n this.redraw();\n if (editRow.alerts) {\n editRow.alerts = false;\n }\n return true;\n }\n beforeFocus(component) {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n const relativePath = this.getRelativePath(component.path);\n const arrayPath = (0, utils_1.getArrayFromComponentPath)(relativePath);\n const rowIndex = arrayPath[0];\n let rowToEditIndex = arrayPath[0];\n this.editRows.forEach((row, indexInArray) => {\n if (row.rowIndex === rowIndex) {\n rowToEditIndex = indexInArray;\n }\n });\n if (lodash_1.default.isNumber(rowToEditIndex)) {\n this.editRow(rowToEditIndex);\n }\n }\n updateComponentsRowIndex(components, rowIndex) {\n components.forEach((component, colIndex) => {\n component.rowIndex = rowIndex;\n component.row = `${rowIndex}-${colIndex}`;\n });\n }\n updateRowsComponents(rowIndex) {\n this.editRows.slice(rowIndex).forEach((row, index) => {\n this.updateComponentsRowIndex(row.components, rowIndex + index);\n });\n }\n baseRemoveRow(rowIndex) {\n const editRow = this.editRows[rowIndex];\n editRow.state = EditRowState.Removed;\n this.destroyComponents(false, rowIndex);\n return editRow;\n }\n removeRow(rowIndex, modified) {\n if (this.options.readOnly) {\n return;\n }\n this.clearErrors(rowIndex);\n this.baseRemoveRow(rowIndex);\n this.splice(rowIndex);\n this.emit('editGridDeleteRow', {\n index: rowIndex\n });\n this.editRows.splice(rowIndex, 1);\n this.openWhenEmpty();\n this.updateRowsComponents(rowIndex);\n this.updateValue();\n this.triggerChange({ modified, noPristineChangeOnModified: modified && this.component.rowDrafts, isolateRow: true });\n this.checkValidity(null, true);\n this.checkData();\n this.redraw();\n }\n createRowComponents(row, rowIndex, recreatePartially) {\n // Iterate through existing components and destroy the ones with the same rowIndex.\n if (this.components) {\n for (let i = 0; i < this.components.length; i++) {\n if (this.components[i].rowIndex === rowIndex) {\n this.components[i].destroy();\n this.components.splice(i, 1);\n }\n }\n }\n const currentRowComponents = lodash_1.default.get(this.editRows, `[${rowIndex}].components`, null);\n return this.component.components.map((col, colIndex) => {\n var _a;\n if (recreatePartially && currentRowComponents && this.variableTypeComponentsIndexes.length) {\n const currentComp = currentRowComponents[colIndex];\n const shouldRecreate = lodash_1.default.includes(this.variableTypeComponentsIndexes, colIndex) && (currentComp === null || currentComp === void 0 ? void 0 : currentComp.type) !== ((_a = currentComp === null || currentComp === void 0 ? void 0 : currentComp.component) === null || _a === void 0 ? void 0 : _a.type);\n if (!shouldRecreate) {\n return currentComp;\n }\n col = currentComp.component;\n }\n const column = lodash_1.default.clone(col);\n const options = lodash_1.default.clone(this.options);\n options.name += `[${rowIndex}]`;\n options.row = `${rowIndex}-${colIndex}`;\n options.onChange = (flags = {}, changed, modified) => {\n var _a, _b;\n if (((_a = changed.instance.root) === null || _a === void 0 ? void 0 : _a.id) && (((_b = this.root) === null || _b === void 0 ? void 0 : _b.id) !== changed.instance.root.id)) {\n changed.instance.root.triggerChange(flags, changed, modified);\n }\n else if (!this.component.modal) {\n this.triggerRootChange(flags, changed, modified);\n }\n if (this.inlineEditMode) {\n return;\n }\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n this.processRow('checkData', null, Object.assign(Object.assign({}, flags), { changed }), editRow.data, editRow.components);\n this.validateRow(editRow, false);\n }\n if (this.variableTypeComponentsIndexes.length) {\n this.checkRowVariableTypeComponents(editRow, rowIndex);\n this.redraw();\n }\n };\n const comp = this.createComponent(lodash_1.default.assign({}, column, { row: options.row }), options, row, null, recreatePartially && currentRowComponents ? currentRowComponents[colIndex] : null);\n comp.rowIndex = rowIndex;\n comp.inEditGrid = true;\n return comp;\n });\n }\n hasOpenRows() {\n return this.editRows.some(row => this.isOpen(row));\n }\n getAttachedData(data = null) {\n const ourData = (0, utils_1.fastCloneDeep)(data || this._data || this.rootValue);\n lodash_1.default.set(ourData, this.key, this.editRows.map((row) => row.data));\n return ourData;\n }\n shouldValidateDraft(editRow) {\n var _a, _b;\n // Draft rows should be validated only when there was an attempt to submit a form\n return (editRow.state === EditRowState.Draft &&\n !this.pristine &&\n !((_a = this.root) === null || _a === void 0 ? void 0 : _a.pristine) &&\n !this.hasOpenRows()) ||\n ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted);\n }\n shouldValidateRow(editRow, dirty) {\n return this.shouldValidateDraft(editRow) ||\n editRow.state === EditRowState.New ||\n editRow.state === EditRowState.Editing ||\n editRow.alerts ||\n dirty;\n }\n validateRow(editRow, dirty, forceSilentCheck) {\n var _a;\n editRow.errors = [];\n if (this.shouldValidateRow(editRow, dirty)) {\n const silentCheck = (this.component.rowDrafts && !this.shouldValidateDraft(editRow)) || forceSilentCheck;\n const rootValue = (0, utils_1.fastCloneDeep)(this.rootValue);\n const editGridValue = lodash_1.default.get(rootValue, this.path, []);\n editGridValue[editRow.rowIndex] = editRow.data;\n lodash_1.default.set(rootValue, this.path, editGridValue);\n const validationProcessorProcess = (context) => this.validationProcessor(context, { dirty, silentCheck });\n editRow.errors = (0, process_1.processSync)({\n components: (0, utils_1.fastCloneDeep)(this.component.components).map((component) => {\n component.parentPath = `${this.path}[${editRow.rowIndex}]`;\n return component;\n }),\n data: rootValue,\n row: editRow.data,\n process: 'validateRow',\n instances: this.componentsMap,\n scope: { errors: [] },\n processors: [\n {\n process: validationProcessorProcess,\n processSync: validationProcessorProcess\n }\n ]\n }).errors;\n }\n // TODO: this is essentially running its own custom validation and should be moved into a validation rule\n if (this.component.validate && this.component.validate.row) {\n const valid = this.evaluate(this.component.validate.row, {\n valid: (editRow.length === 0),\n row: editRow.data\n }, 'valid', true);\n if (valid.toString() !== 'true') {\n editRow.errors.push({\n type: 'error',\n rowError: true,\n message: valid.toString()\n });\n }\n if (valid === null) {\n editRow.errors.push({\n type: 'error',\n message: `Invalid row validation for ${this.key}`\n });\n }\n }\n if (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted)) {\n this.showRowErrorAlerts(editRow, editRow.errors);\n }\n return editRow.errors;\n }\n showRowErrorAlerts(editRow, errors) {\n if (editRow.alerts) {\n if (this.alert) {\n if (errors.length) {\n this.alert.showErrors(errors, false);\n editRow.alerts = true;\n }\n else {\n this.alert.clear();\n this.alert = null;\n }\n }\n }\n }\n /**\n * Return that this component processes its own validation.\n */\n get processOwnValidation() {\n return true;\n }\n checkComponentValidity(data, dirty, row, options = {}, errors = []) {\n var _a, _b;\n const { silentCheck } = options;\n const superValid = super.checkComponentValidity(data, dirty, row, options, errors);\n // If super tells us that component invalid and there is no need to update alerts, just return false\n if (!superValid && (!this.alert && !this.hasOpenRows())) {\n return false;\n }\n let rowsEditing = false;\n const allRowErrors = [];\n this.editRows.forEach((editRow, index) => {\n // Trigger all errors on the row.\n const rowErrors = this.validateRow(editRow, dirty, silentCheck);\n errors.push(...rowErrors);\n allRowErrors.push(...rowErrors);\n if (this.rowRefs) {\n const rowContainer = this.rowRefs[index];\n if (rowContainer) {\n const errorContainer = rowContainer.querySelector('.editgrid-row-error');\n if (rowErrors.length && errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n const rowError = rowErrors.find(error => error.rowError);\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(rowError ? rowError.message : this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n }\n // If this is a dirty check, and any rows are still editing, we need to throw validation error.\n rowsEditing |= (dirty && this.isOpen(editRow));\n });\n if (allRowErrors.length) {\n if (!silentCheck && (dirty || this.dirty) && (!this.component.rowDrafts || ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted))) {\n this.setCustomValidity(this.t(this.errorMessage('invalidRowsError')), dirty);\n this.removeClass(this.element, 'has-error');\n }\n return false;\n }\n else if (rowsEditing && this.saveEditMode && !this.component.openWhenEmpty) {\n this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);\n return false;\n }\n const message = this.invalid || this.invalidMessage(data, dirty, false, row);\n if (allRowErrors.length && ((_b = this.root) === null || _b === void 0 ? void 0 : _b.submitted) && !message) {\n this._errors = this.setCustomValidity(message, dirty);\n errors.push(...this._errors);\n this.root.showErrors([message]);\n }\n else {\n this._errors = this.setCustomValidity(message, dirty);\n errors.push(...this._errors);\n }\n return superValid;\n }\n setRowInvalid(ref, index) {\n const editRow = this.editRows[index];\n const errorContainer = ref.querySelector('.editgrid-row-error');\n if (errorContainer && (!this.component.rowDrafts || this.shouldValidateDraft(editRow))) {\n this.addClass(errorContainer, 'help-block');\n errorContainer.textContent = this.t(this.errorMessage('invalidRowError'));\n }\n else if (errorContainer) {\n errorContainer.textContent = '';\n }\n }\n changeState(changed, flags) {\n if (this.visible && (changed || (flags.resetValue && this.component.modalEdit))) {\n this.rebuild();\n }\n else {\n this.redraw();\n }\n }\n setValue(value, flags = {}) {\n if (!value) {\n value = this.defaultValue;\n }\n if (!Array.isArray(value)) {\n if (typeof value === 'object') {\n value = [value];\n }\n else {\n return false;\n }\n }\n const changed = this.hasChanged(value, this.dataValue);\n if (this.parent && !this.options.server) {\n this.parent.checkComponentConditions();\n }\n this.dataValue = value;\n // Refresh editRow data when data changes.\n this.dataValue.forEach((row, rowIndex) => {\n const editRow = this.editRows[rowIndex];\n if (editRow) {\n editRow.data = row;\n this.restoreRowContext(editRow, flags);\n editRow.state = EditRowState.Saved;\n editRow.backup = null;\n editRow.errors = [];\n }\n else {\n this.editRows[rowIndex] = {\n components: this.lazyLoad ? [] : this.createRowComponents(row, rowIndex),\n data: row,\n state: EditRowState.Saved,\n backup: null,\n errors: [],\n };\n }\n });\n let { length: dataLength } = this.dataValue;\n // If the last row is a new row, then do not remove it.\n if (this.editRows[dataLength] && (this.editRows[dataLength].state === EditRowState.New)) {\n dataLength = (dataLength + 1);\n }\n this.editRows.slice(dataLength).forEach((editRow, index) => this.baseRemoveRow(dataLength + index));\n this.editRows = this.editRows.slice(0, dataLength);\n this.openWhenEmpty();\n this.updateOnChange(flags, changed);\n // do not call checkData with server option, it is called when change is triggered in updateOnChange\n if (!this.options.server) {\n this.checkData();\n }\n this.changeState(changed, flags);\n return changed;\n }\n openWhenEmpty() {\n const shouldBeOpened = !this.dataValue.length && this.component.openWhenEmpty;\n const hasNoRows = !this.editRows.length;\n if (hasNoRows && shouldBeOpened && !this.builderMode) {\n const dataObj = {};\n this.createRow(dataObj, 0);\n }\n }\n restoreRowContext(editRow, flags = {}) {\n editRow.components.forEach((component) => {\n component.data = editRow.data;\n this.setNestedValue(component, editRow.data, flags);\n });\n }\n emptyRows() {\n this.editRows.forEach((editRow, index) => this.destroyComponents(false, index));\n this.editRows = [];\n }\n resetValue() {\n super.resetValue();\n this.emptyRows();\n }\n}\nexports[\"default\"] = EditGridComponent;\nEditGridComponent.prototype.hasChanged = Component_1.default.prototype.hasChanged;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/editgrid/EditGrid.js?");
6514
6524
 
6515
6525
  /***/ }),
6516
6526
 
@@ -6653,7 +6663,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
6653
6663
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6654
6664
 
6655
6665
  "use strict";
6656
- 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};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\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\");\nconst downloadjs_1 = __importDefault(__webpack_require__(/*! downloadjs */ \"./node_modules/downloadjs/download.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst fileProcessor_1 = __importDefault(__webpack_require__(/*! ../../providers/processor/fileProcessor */ \"./lib/cjs/providers/processor/fileProcessor.js\"));\nconst browser_md5_file_1 = __importDefault(__webpack_require__(/*! browser-md5-file */ \"./node_modules/browser-md5-file/dist/index.umd.js\"));\nlet Camera;\nlet webViewCamera = 'undefined' !== typeof window ? navigator.camera : Camera;\n// canvas.toBlob polyfill.\nlet htmlCanvasElement;\nif (typeof window !== 'undefined') {\n htmlCanvasElement = window.HTMLCanvasElement;\n}\nelse if (typeof __webpack_require__.g !== 'undefined') {\n htmlCanvasElement = __webpack_require__.g.HTMLCanvasElement;\n}\nif (htmlCanvasElement && !htmlCanvasElement.prototype.toBlob) {\n Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {\n value: function (callback, type, quality) {\n var canvas = this;\n setTimeout(function () {\n var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);\n for (var i = 0; i < len; i++) {\n arr[i] = binStr.charCodeAt(i);\n }\n callback(new Blob([arr], { type: type || 'image/png' }));\n });\n }\n });\n}\nconst createRandomString = () => Math.random().toString(36).substring(2, 15);\nclass FileComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'file',\n label: 'Upload',\n key: 'file',\n image: false,\n privateDownload: false,\n imageSize: '200',\n filePattern: '*',\n fileMinSize: '0KB',\n fileMaxSize: '1GB',\n uploadOnly: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'File',\n group: 'premium',\n icon: 'file',\n documentation: '/userguide/form-building/premium-components#file',\n weight: 100,\n schema: FileComponent.schema(),\n };\n }\n static get serverConditionSettings() {\n return FileComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isEmpty', 'isNotEmpty'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n webViewCamera = navigator.camera || Camera;\n const fileReaderSupported = (typeof FileReader !== 'undefined');\n const formDataSupported = typeof window !== 'undefined' ? Boolean(window.FormData) : false;\n const progressSupported = (typeof window !== 'undefined' && window.XMLHttpRequest) ? ('upload' in new XMLHttpRequest) : false;\n this.support = {\n filereader: fileReaderSupported,\n formdata: formDataSupported,\n hasWarning: !fileReaderSupported || !formDataSupported || !progressSupported,\n progress: progressSupported,\n };\n this.cameraMode = false;\n this.fileDropHidden = false;\n this.filesToSync = {\n filesToUpload: [],\n filesToDelete: [],\n };\n this.isSyncing = false;\n this.abortUploads = [];\n }\n get dataReady() {\n return this.filesReady || Promise.resolve();\n }\n get defaultSchema() {\n return FileComponent.schema();\n }\n loadImage(fileInfo) {\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n return this.fileService.downloadFile(fileInfo).then((result) => result.url);\n }\n get emptyValue() {\n return [];\n }\n getValueAsString(value) {\n if (lodash_1.default.isArray(value)) {\n return lodash_1.default.map(value, 'originalName').join(', ');\n }\n return lodash_1.default.get(value, 'originalName', '');\n }\n getValue() {\n return this.dataValue;\n }\n get defaultValue() {\n const value = super.defaultValue;\n return Array.isArray(value) ? value : [];\n }\n get hasTypes() {\n return this.component.fileTypes &&\n Array.isArray(this.component.fileTypes) &&\n this.component.fileTypes.length !== 0 &&\n (this.component.fileTypes[0].label !== '' || this.component.fileTypes[0].value !== '');\n }\n get fileDropHidden() {\n return this._fileBrowseHidden;\n }\n set fileDropHidden(value) {\n if (typeof value !== 'boolean' || this.component.multiple) {\n return;\n }\n this._fileBrowseHidden = value;\n }\n get shouldSyncFiles() {\n return Boolean(this.filesToSync.filesToDelete.length || this.filesToSync.filesToUpload.length);\n }\n get autoSync() {\n return lodash_1.default.get(this, 'component.autoSync', false);\n }\n get columnsSize() {\n const actionsColumn = this.disabled ? 0 : this.autoSync ? 2 : 1;\n const typeColumn = this.hasTypes ? 2 : 0;\n const sizeColumn = 2;\n const nameColumn = 12 - actionsColumn - typeColumn - sizeColumn;\n return {\n name: nameColumn,\n size: sizeColumn,\n type: typeColumn,\n actions: actionsColumn,\n };\n }\n render() {\n const { filesToDelete, filesToUpload } = this.filesToSync;\n return super.render(this.renderTemplate('file', {\n fileSize: this.fileSize,\n files: this.dataValue || [],\n filesToDelete,\n filesToUpload,\n disabled: this.disabled,\n support: this.support,\n fileDropHidden: this.fileDropHidden,\n showSyncButton: this.autoSync && (filesToDelete.length || filesToUpload.length),\n isSyncing: this.isSyncing,\n columns: this.columnsSize,\n }));\n }\n getVideoStream(constraints) {\n return navigator.mediaDevices.getUserMedia({\n video: Object.assign({ width: { min: 640, ideal: 1920 }, height: { min: 360, ideal: 1080 }, aspectRatio: { ideal: 16 / 9 } }, constraints),\n audio: false,\n });\n }\n stopVideoStream(videoStream) {\n videoStream.getVideoTracks().forEach((track) => track.stop());\n }\n getFrame(videoPlayer) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n canvas.height = videoPlayer.videoHeight;\n canvas.width = videoPlayer.videoWidth;\n const context = canvas.getContext('2d');\n context.drawImage(videoPlayer, 0, 0);\n canvas.toBlob(resolve);\n });\n }\n startVideo() {\n this.getVideoStream()\n .then((stream) => {\n this.videoStream = stream;\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n videoPlayer.srcObject = stream;\n const width = parseInt(this.component.webcamSize) || 320;\n videoPlayer.setAttribute('width', width);\n videoPlayer.play();\n })\n .catch((err) => {\n console.error(err);\n this.cameraMode = false;\n this.redraw();\n });\n }\n stopVideo() {\n if (this.videoStream) {\n this.stopVideoStream(this.videoStream);\n this.videoStream = null;\n }\n }\n takePicture() {\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n this.getFrame(videoPlayer)\n .then((frame) => {\n frame.name = `photo-${Date.now()}.png`;\n this.handleFilesToUpload([frame]);\n this.cameraMode = false;\n this.redraw();\n });\n }\n browseFiles(attrs = {}) {\n return new Promise((resolve) => {\n const fileInput = this.ce('input', Object.assign({ type: 'file', style: 'height: 0; width: 0; visibility: hidden;', tabindex: '-1' }, attrs));\n document.body.appendChild(fileInput);\n fileInput.addEventListener('change', () => {\n resolve(fileInput.files);\n document.body.removeChild(fileInput);\n }, true);\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof fileInput.trigger === 'function') {\n fileInput.trigger('click');\n }\n else {\n fileInput.click();\n }\n });\n }\n set cameraMode(value) {\n this._cameraMode = value;\n if (value) {\n this.startVideo();\n }\n else {\n this.stopVideo();\n }\n }\n get cameraMode() {\n return this._cameraMode;\n }\n get useWebViewCamera() {\n return this.imageUpload && webViewCamera;\n }\n get imageUpload() {\n return Boolean(this.component.image);\n }\n get browseOptions() {\n const options = {};\n if (this.component.multiple) {\n options.multiple = true;\n }\n if (this.component.capture) {\n options.capture = this.component.capture;\n }\n //use \"accept\" attribute only for desktop devices because of its limited support by mobile browsers\n const filePattern = this.component.filePattern.trim() || '';\n if (!this.isMobile.any) {\n const imagesPattern = 'image/*';\n if (this.imageUpload && (!filePattern || filePattern === '*')) {\n options.accept = imagesPattern;\n }\n else if (this.imageUpload && !filePattern.includes(imagesPattern)) {\n options.accept = `${imagesPattern},${filePattern}`;\n }\n else {\n options.accept = filePattern;\n }\n }\n // if input capture is set, we need the \"accept\" attribute to determine which device to launch\n else if (this.component.capture) {\n if (filePattern.includes('video')) {\n options.accept = 'video/*';\n }\n else if (filePattern.includes('audio')) {\n options.accept = 'audio/*';\n }\n else {\n options.accept = 'image/*';\n }\n }\n return options;\n }\n get actions() {\n return {\n abort: this.abortRequest.bind(this),\n };\n }\n attach(element) {\n this.loadRefs(element, {\n fileDrop: 'single',\n fileBrowse: 'single',\n galleryButton: 'single',\n cameraButton: 'single',\n takePictureButton: 'single',\n toggleCameraMode: 'single',\n videoPlayer: 'single',\n fileLink: 'multiple',\n removeLink: 'multiple',\n fileToSyncRemove: 'multiple',\n fileImage: 'multiple',\n fileType: 'multiple',\n fileProcessingLoader: 'single',\n syncNow: 'single',\n restoreFile: 'multiple',\n progress: 'multiple',\n });\n // Ensure we have an empty input refs. We need this for the setValue method to redraw the control when it is set.\n this.refs.input = [];\n const superAttach = super.attach(element);\n if (this.refs.fileDrop) {\n // if (!this.statuses.length) {\n // this.refs.fileDrop.removeAttribute('hidden');\n // }\n const _this = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n _this.handleFilesToUpload(event.dataTransfer.files);\n });\n }\n this.addEventListener(element, 'click', (event) => {\n this.handleAction(event);\n });\n if (this.refs.fileBrowse) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n this.browseFiles(this.browseOptions)\n .then((files) => {\n this.handleFilesToUpload(files);\n });\n });\n }\n this.refs.fileLink.forEach((fileLink, index) => {\n this.addEventListener(fileLink, 'click', (event) => {\n event.preventDefault();\n this.getFile(this.dataValue[index]);\n });\n });\n this.refs.removeLink.forEach((removeLink, index) => {\n this.addEventListener(removeLink, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.dataValue[index];\n this.handleFileToRemove(fileInfo);\n });\n });\n this.refs.fileToSyncRemove.forEach((fileToSyncRemove, index) => {\n this.addEventListener(fileToSyncRemove, 'click', (event) => {\n event.preventDefault();\n this.filesToSync.filesToUpload.splice(index, 1);\n this.redraw();\n });\n });\n this.refs.restoreFile.forEach((fileToRestore, index) => {\n this.addEventListener(fileToRestore, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.filesToSync.filesToDelete[index];\n delete fileInfo.status;\n delete fileInfo.message;\n this.filesToSync.filesToDelete.splice(index, 1);\n this.dataValue.push(fileInfo);\n this.triggerChange();\n this.redraw();\n });\n });\n if (this.refs.galleryButton && webViewCamera) {\n this.addEventListener(this.refs.galleryButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.PHOTOLIBRARY,\n });\n });\n }\n if (this.refs.cameraButton && webViewCamera) {\n this.addEventListener(this.refs.cameraButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.CAMERA,\n encodingType: webViewCamera.EncodingType.PNG,\n mediaType: webViewCamera.MediaType.PICTURE,\n saveToPhotoAlbum: true,\n correctOrientation: false,\n });\n });\n }\n if (this.refs.takePictureButton) {\n this.addEventListener(this.refs.takePictureButton, 'click', (event) => {\n event.preventDefault();\n this.takePicture();\n });\n }\n if (this.refs.toggleCameraMode) {\n this.addEventListener(this.refs.toggleCameraMode, 'click', (event) => {\n event.preventDefault();\n this.cameraMode = !this.cameraMode;\n this.redraw();\n });\n }\n this.refs.fileType.forEach((fileType, index) => {\n if (!this.dataValue[index]) {\n return;\n }\n this.dataValue[index].fileType = this.dataValue[index].fileType || this.component.fileTypes[0].label;\n this.addEventListener(fileType, 'change', (event) => {\n event.preventDefault();\n const fileType = this.component.fileTypes.find((typeObj) => typeObj.value === event.target.value);\n this.dataValue[index].fileType = fileType.label;\n });\n });\n this.addEventListener(this.refs.syncNow, 'click', (event) => {\n event.preventDefault();\n this.syncFiles();\n });\n const fileService = this.fileService;\n if (fileService) {\n const loadingImages = [];\n this.filesReady = new Promise((resolve, reject) => {\n this.filesReadyResolve = resolve;\n this.filesReadyReject = reject;\n });\n this.refs.fileImage.forEach((image, index) => {\n loadingImages.push(this.loadImage(this.dataValue[index]).then((url) => (image.src = url)));\n });\n if (loadingImages.length) {\n Promise.all(loadingImages).then(() => {\n this.filesReadyResolve();\n }).catch(() => this.filesReadyReject());\n }\n else {\n this.filesReadyResolve();\n }\n }\n return superAttach;\n }\n /* eslint-disable max-len */\n fileSize(a, b, c, d, e) {\n return `${(b = Math, c = b.log, d = 1024, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2)} ${e ? `${'kMGTPEZY'[--e]}B` : 'Bytes'}`;\n }\n /* eslint-enable max-len */\n /* eslint-disable max-depth */\n globStringToRegex(str) {\n str = str.replace(/\\s/g, '');\n let regexp = '', excludes = [];\n if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n regexp = str.substring(1, str.length - 1);\n }\n else {\n const split = str.split(',');\n if (split.length > 1) {\n for (let i = 0; i < split.length; i++) {\n const r = this.globStringToRegex(split[i]);\n if (r.regexp) {\n regexp += `(${r.regexp})`;\n if (i < split.length - 1) {\n regexp += '|';\n }\n }\n else {\n excludes = excludes.concat(r.excludes);\n }\n }\n }\n else {\n if (str.startsWith('!')) {\n excludes.push(`^((?!${this.globStringToRegex(str.substring(1)).regexp}).)*$`);\n }\n else {\n if (str.startsWith('.')) {\n str = `*${str}`;\n }\n regexp = `^${str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&')}$`;\n regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n }\n }\n }\n return { regexp, excludes };\n }\n /* eslint-enable max-depth */\n translateScalars(str) {\n if (typeof str === 'string') {\n if (str.search(/kb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024);\n }\n if (str.search(/mb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024);\n }\n if (str.search(/gb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024 * 1024);\n }\n if (str.search(/b/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/s/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/m/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 60);\n }\n if (str.search(/h/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 3600);\n }\n }\n return str;\n }\n validatePattern(file, val) {\n if (!val) {\n return true;\n }\n const pattern = this.globStringToRegex(val);\n let valid = true;\n if (pattern.regexp && pattern.regexp.length) {\n const regexp = new RegExp(pattern.regexp, 'i');\n valid = (!lodash_1.default.isNil(file.type) && regexp.test(file.type)) ||\n (!lodash_1.default.isNil(file.name) && regexp.test(file.name));\n }\n valid = pattern.excludes.reduce((result, excludePattern) => {\n const exclude = new RegExp(excludePattern, 'i');\n return result && (lodash_1.default.isNil(file.type) || exclude.test(file.type)) &&\n (lodash_1.default.isNil(file.name) || exclude.test(file.name));\n }, valid);\n return valid;\n }\n validateMinSize(file, val) {\n return file.size + 0.1 >= this.translateScalars(val);\n }\n validateMaxSize(file, val) {\n return file.size - 0.1 <= this.translateScalars(val);\n }\n abortRequest(id) {\n const abortUpload = this.abortUploads.find(abortUpload => abortUpload.id === id);\n if (abortUpload) {\n abortUpload.abort();\n }\n }\n handleAction(event) {\n const target = event.target;\n if (!target.id) {\n return;\n }\n const [action, id] = target.id.split('-');\n if (!action || !id || !this.actions[action]) {\n return;\n }\n this.actions[action](id);\n }\n getFileName(file) {\n return (0, utils_1.uniqueName)(file.name, this.component.fileNameTemplate, this.evalContext());\n }\n getInitFileToSync(file) {\n const escapedFileName = file.name ? file.name.replaceAll('<', '&lt;').replaceAll('>', '&gt;') : file.name;\n return {\n id: createRandomString(),\n // Get a unique name for this file to keep file collisions from occurring.\n dir: this.interpolate(this.component.dir || ''),\n name: this.getFileName(file),\n originalName: escapedFileName,\n fileKey: this.component.fileKey || 'file',\n storage: this.component.storage,\n options: this.component.options,\n file,\n size: file.size,\n status: 'info',\n message: this.t('Processing file. Please wait...'),\n hash: '',\n };\n }\n handleSubmissionRevisions(file) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.root.form.submissionRevisions !== 'true') {\n return '';\n }\n const bmf = new browser_md5_file_1.default();\n const hash = yield new Promise((resolve, reject) => {\n this.emit('fileUploadingStart');\n bmf.md5(file, (err, md5) => {\n if (err) {\n return reject(err);\n }\n return resolve(md5);\n });\n });\n this.emit('fileUploadingEnd');\n return hash;\n });\n }\n validateFileName(file) {\n // Check if file with the same name is being uploaded\n const fileWithSameNameUploading = this.filesToSync.filesToUpload\n .some(fileToSync => { var _a; return ((_a = fileToSync.file) === null || _a === void 0 ? void 0 : _a.name) === file.name; });\n const fileWithSameNameUploaded = this.dataValue\n .some(fileStatus => fileStatus.originalName === file.name);\n return fileWithSameNameUploaded || fileWithSameNameUploading\n ? {\n status: 'error',\n message: this.t(`File with the same name is already ${fileWithSameNameUploading ? 'being ' : ''}uploaded`),\n }\n : {};\n }\n validateFileSettings(file) {\n // Check file pattern\n if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {\n return {\n status: 'error',\n message: this.t('File is the wrong type; it must be {{ pattern }}', {\n pattern: this.component.filePattern,\n }),\n };\n }\n // Check file minimum size\n if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {\n return {\n status: 'error',\n message: this.t('File is too small; it must be at least {{ size }}', {\n size: this.component.fileMinSize,\n }),\n };\n }\n // Check file maximum size\n if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {\n return {\n status: 'error',\n message: this.t('File is too big; it must be at most {{ size }}', {\n size: this.component.fileMaxSize,\n }),\n };\n }\n return {};\n }\n validateFileService() {\n const { fileService } = this;\n return !fileService\n ? {\n status: 'error',\n message: this.t('File Service not provided.'),\n }\n : {};\n }\n validateFile(file) {\n const fileServiceValidation = this.validateFileService();\n if (fileServiceValidation.status === 'error') {\n return fileServiceValidation;\n }\n const fileNameValidation = this.validateFileName(file);\n if (fileNameValidation.status === 'error') {\n return fileNameValidation;\n }\n return this.validateFileSettings(file);\n }\n getGroupPermissions() {\n let groupKey = null;\n let groupPermissions = null;\n //Iterate through form components to find group resource if one exists\n this.root.everyComponent((element) => {\n var _a, _b;\n if (((_a = element.component) === null || _a === void 0 ? void 0 : _a.submissionAccess) || ((_b = element.component) === null || _b === void 0 ? void 0 : _b.defaultPermission)) {\n groupPermissions = !element.component.submissionAccess ? [\n {\n type: element.component.defaultPermission,\n roles: [],\n },\n ] : element.component.submissionAccess;\n groupPermissions.forEach((permission) => {\n groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;\n });\n }\n });\n return { groupKey, groupPermissions };\n }\n triggerFileProcessor(file) {\n return __awaiter(this, void 0, void 0, function* () {\n let processedFile = null;\n if (this.root.options.fileProcessor) {\n try {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'block';\n }\n const fileProcessorHandler = (0, fileProcessor_1.default)(this.fileService, this.root.options.fileProcessor);\n processedFile = yield fileProcessorHandler(file, this.component.properties);\n }\n catch (err) {\n this.fileDropHidden = false;\n return {\n status: 'error',\n message: this.t('File processing has been failed.'),\n };\n }\n finally {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'none';\n }\n }\n }\n return {\n file: processedFile,\n };\n });\n }\n prepareFileToUpload(file) {\n return __awaiter(this, void 0, void 0, function* () {\n const fileToSync = this.getInitFileToSync(file);\n fileToSync.hash = yield this.handleSubmissionRevisions(file);\n const { status, message } = this.validateFile(file);\n if (status === 'error') {\n fileToSync.isValidationError = true;\n fileToSync.status = status;\n fileToSync.message = message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.component.privateDownload) {\n file.private = true;\n }\n const { groupKey, groupPermissions } = this.getGroupPermissions();\n const processedFile = yield this.triggerFileProcessor(file);\n if (processedFile.status === 'error') {\n fileToSync.status === 'error';\n fileToSync.message = processedFile.message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.autoSync) {\n fileToSync.message = this.t('Ready to be uploaded into storage');\n }\n this.filesToSync.filesToUpload.push(Object.assign(Object.assign({}, fileToSync), { message: fileToSync.message, file: processedFile.file || file, url: this.interpolate(this.component.url, { file: fileToSync }), groupPermissions, groupResourceId: groupKey ? this.currentForm.submission.data[groupKey]._id : null }));\n });\n }\n prepareFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n // Only allow one upload if not multiple.\n if (!this.component.multiple) {\n files = Array.prototype.slice.call(files, 0, 1);\n }\n if (this.component.storage && files && files.length) {\n this.fileDropHidden = true;\n return Promise.all([...files].map((file) => __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFileToUpload(file);\n this.redraw();\n })));\n }\n else {\n return Promise.resolve();\n }\n });\n }\n handleFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFilesToUpload(files);\n if (!this.autoSync) {\n yield this.syncFiles();\n }\n });\n }\n prepareFileToDelete(fileInfo) {\n this.filesToSync.filesToDelete.push(Object.assign(Object.assign({}, fileInfo), { status: 'info', message: this.autoSync\n ? this.t('Ready to be removed from storage')\n : this.t('Preparing file to remove') }));\n const index = this.dataValue.findIndex(file => file.name === fileInfo.name);\n this.splice(index);\n this.redraw();\n }\n handleFileToRemove(fileInfo) {\n this.prepareFileToDelete(fileInfo);\n if (!this.autoSync) {\n this.syncFiles();\n }\n }\n deleteFile(fileInfo) {\n return __awaiter(this, void 0, void 0, function* () {\n const { options = {} } = this.component;\n if (fileInfo && (['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage))) {\n const { fileService } = this;\n if (fileService && typeof fileService.deleteFile === 'function') {\n return yield fileService.deleteFile(fileInfo, options);\n }\n else {\n const formio = this.options.formio || (this.root && this.root.formio);\n if (formio) {\n return yield formio.makeRequest('', fileInfo.url, 'delete');\n }\n }\n }\n });\n }\n delete() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToDelete.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToDelete.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n try {\n if (fileToSync.isValidationError) {\n return { fileToSync };\n }\n yield this.deleteFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully removed');\n }\n catch (response) {\n fileToSync.status = 'error';\n fileToSync.message = typeof response === 'string' ? response : response.toString();\n }\n finally {\n this.redraw();\n }\n return { fileToSync };\n })));\n });\n }\n updateProgress(fileInfo, progressEvent) {\n fileInfo.progress = parseInt(100.0 * progressEvent.loaded / progressEvent.total);\n if (fileInfo.status !== 'progress') {\n fileInfo.status = 'progress';\n delete fileInfo.message;\n this.redraw();\n }\n else {\n const progress = Array.prototype.find.call(this.refs.progress, progressElement => progressElement.id === fileInfo.id);\n progress.innerHTML = `<span class=\"visually-hidden\">${fileInfo.progress}% ${this.t('Complete')}</span>`;\n progress.style.width = `${fileInfo.progress}%`;\n progress.ariaValueNow = fileInfo.progress.toString();\n }\n }\n getMultipartOptions(fileToSync) {\n let count = 0;\n return this.component.useMultipartUpload && this.component.multipart ? Object.assign(Object.assign({}, this.component.multipart), { progressCallback: (total) => {\n count++;\n fileToSync.status = 'progress';\n fileToSync.progress = parseInt(100 * count / total);\n delete fileToSync.message;\n this.redraw();\n }, changeMessage: (message) => {\n fileToSync.message = message;\n this.redraw();\n } }) : false;\n }\n uploadFile(fileToSync) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir, \n // Progress callback\n this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => { }, \n // Abort upload callback\n (abort) => this.abortUploads.push({\n id: fileToSync.id,\n abort,\n }), this.getMultipartOptions(fileToSync));\n });\n }\n upload() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToUpload.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToUpload.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n let fileInfo = null;\n try {\n if (fileToSync.isValidationError) {\n return {\n fileToSync,\n fileInfo,\n };\n }\n fileInfo = yield this.uploadFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully uploaded');\n fileInfo.originalName = fileToSync.originalName;\n fileInfo.hash = fileToSync.hash;\n }\n catch (response) {\n fileToSync.status = 'error';\n delete fileToSync.progress;\n fileToSync.message = typeof response === 'string'\n ? response\n : response.type === 'abort'\n ? this.t('Request was aborted')\n : response.toString();\n }\n finally {\n delete fileToSync.progress;\n this.redraw();\n }\n return {\n fileToSync,\n fileInfo,\n };\n })));\n });\n }\n syncFiles() {\n return __awaiter(this, void 0, void 0, function* () {\n this.isSyncing = true;\n this.fileDropHidden = true;\n this.redraw();\n try {\n const [filesToDelete = [], filesToUpload = []] = yield Promise.all([this.delete(), this.upload()]);\n this.filesToSync.filesToDelete = filesToDelete\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n this.filesToSync.filesToUpload = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n if (!this.hasValue()) {\n this.dataValue = [];\n }\n const data = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'success'; })\n .map(file => file.fileInfo);\n this.dataValue.push(...data);\n this.triggerChange();\n return Promise.resolve();\n }\n catch (err) {\n return Promise.reject();\n }\n finally {\n this.isSyncing = false;\n this.fileDropHidden = false;\n this.abortUploads = [];\n this.redraw();\n }\n });\n }\n getFile(fileInfo) {\n const { options = {} } = this.component;\n const { fileService } = this;\n if (!fileService) {\n return alert('File Service not provided');\n }\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n fileService.downloadFile(fileInfo, options).then((file) => {\n if (file) {\n if (['base64', 'indexeddb'].includes(file.storage)) {\n (0, downloadjs_1.default)(file.url, file.originalName || file.name, file.type);\n }\n else {\n window.open(file.url, '_blank');\n }\n }\n })\n .catch((response) => {\n // Is alert the best way to do this?\n // User is expecting an immediate notification due to attempting to download a file.\n alert(response);\n });\n }\n focus() {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if (this.refs.fileBrowse) {\n this.refs.fileBrowse.focus();\n }\n }\n beforeSubmit() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (!this.autoSync) {\n return Promise.resolve();\n }\n yield this.syncFiles();\n return this.shouldSyncFiles\n ? Promise.reject('Synchronization is failed')\n : Promise.resolve();\n }\n catch (error) {\n return Promise.reject(error.message);\n }\n });\n }\n destroy() {\n this.stopVideo();\n super.destroy();\n }\n}\nexports[\"default\"] = FileComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/file/File.js?");
6666
+ 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};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\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\");\nconst downloadjs_1 = __importDefault(__webpack_require__(/*! downloadjs */ \"./node_modules/downloadjs/download.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst fileProcessor_1 = __importDefault(__webpack_require__(/*! ../../providers/processor/fileProcessor */ \"./lib/cjs/providers/processor/fileProcessor.js\"));\nconst browser_md5_file_1 = __importDefault(__webpack_require__(/*! browser-md5-file */ \"./node_modules/browser-md5-file/dist/index.umd.js\"));\nlet Camera;\nlet webViewCamera = 'undefined' !== typeof window ? navigator.camera : Camera;\n// canvas.toBlob polyfill.\nlet htmlCanvasElement;\nif (typeof window !== 'undefined') {\n htmlCanvasElement = window.HTMLCanvasElement;\n}\nelse if (typeof __webpack_require__.g !== 'undefined') {\n htmlCanvasElement = __webpack_require__.g.HTMLCanvasElement;\n}\nif (htmlCanvasElement && !htmlCanvasElement.prototype.toBlob) {\n Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {\n value: function (callback, type, quality) {\n var canvas = this;\n setTimeout(function () {\n var binStr = atob(canvas.toDataURL(type, quality).split(',')[1]), len = binStr.length, arr = new Uint8Array(len);\n for (var i = 0; i < len; i++) {\n arr[i] = binStr.charCodeAt(i);\n }\n callback(new Blob([arr], { type: type || 'image/png' }));\n });\n }\n });\n}\nconst createRandomString = () => Math.random().toString(36).substring(2, 15);\nclass FileComponent extends Field_1.default {\n static schema(...extend) {\n return Field_1.default.schema({\n type: 'file',\n label: 'Upload',\n key: 'file',\n image: false,\n privateDownload: false,\n imageSize: '200',\n filePattern: '*',\n fileMinSize: '0KB',\n fileMaxSize: '1GB',\n uploadOnly: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'File',\n group: 'premium',\n icon: 'file',\n documentation: '/userguide/form-building/premium-components#file',\n weight: 100,\n schema: FileComponent.schema(),\n };\n }\n static get serverConditionSettings() {\n return FileComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: ['isEmpty', 'isNotEmpty'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n webViewCamera = navigator.camera || Camera;\n const fileReaderSupported = (typeof FileReader !== 'undefined');\n const formDataSupported = typeof window !== 'undefined' ? Boolean(window.FormData) : false;\n const progressSupported = (typeof window !== 'undefined' && window.XMLHttpRequest) ? ('upload' in new XMLHttpRequest) : false;\n this.support = {\n filereader: fileReaderSupported,\n formdata: formDataSupported,\n hasWarning: !fileReaderSupported || !formDataSupported || !progressSupported,\n progress: progressSupported,\n };\n this.cameraMode = false;\n this.fileDropHidden = false;\n this.filesToSync = {\n filesToUpload: [],\n filesToDelete: [],\n };\n this.isSyncing = false;\n this.abortUploads = [];\n }\n get dataReady() {\n return this.filesReady || Promise.resolve();\n }\n get defaultSchema() {\n return FileComponent.schema();\n }\n loadImage(fileInfo) {\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n return this.fileService.downloadFile(fileInfo).then((result) => result.url);\n }\n get emptyValue() {\n return [];\n }\n getValueAsString(value) {\n if (lodash_1.default.isArray(value)) {\n return lodash_1.default.map(value, 'originalName').join(', ');\n }\n return lodash_1.default.get(value, 'originalName', '');\n }\n getValue() {\n return this.dataValue;\n }\n get defaultValue() {\n const value = super.defaultValue;\n return Array.isArray(value) ? value : [];\n }\n get hasTypes() {\n return this.component.fileTypes &&\n Array.isArray(this.component.fileTypes) &&\n this.component.fileTypes.length !== 0 &&\n (this.component.fileTypes[0].label !== '' || this.component.fileTypes[0].value !== '');\n }\n get fileDropHidden() {\n return this._fileBrowseHidden;\n }\n set fileDropHidden(value) {\n if (typeof value !== 'boolean' || this.component.multiple) {\n return;\n }\n this._fileBrowseHidden = value;\n }\n get shouldSyncFiles() {\n return Boolean(this.filesToSync.filesToDelete.length || this.filesToSync.filesToUpload.length);\n }\n get autoSync() {\n return lodash_1.default.get(this, 'component.autoSync', false);\n }\n get columnsSize() {\n const actionsColumn = this.disabled ? 0 : this.autoSync ? 2 : 1;\n const typeColumn = this.hasTypes ? 2 : 0;\n const sizeColumn = 2;\n const nameColumn = 12 - actionsColumn - typeColumn - sizeColumn;\n return {\n name: nameColumn,\n size: sizeColumn,\n type: typeColumn,\n actions: actionsColumn,\n };\n }\n render() {\n const { filesToDelete, filesToUpload } = this.filesToSync;\n return super.render(this.renderTemplate('file', {\n fileSize: this.fileSize,\n files: this.dataValue || [],\n filesToDelete,\n filesToUpload,\n disabled: this.disabled,\n support: this.support,\n fileDropHidden: this.fileDropHidden,\n showSyncButton: this.autoSync && (filesToDelete.length || filesToUpload.length),\n isSyncing: this.isSyncing,\n columns: this.columnsSize,\n }));\n }\n getVideoStream(constraints) {\n return navigator.mediaDevices.getUserMedia({\n video: Object.assign({ width: { min: 640, ideal: 1920 }, height: { min: 360, ideal: 1080 }, aspectRatio: { ideal: 16 / 9 } }, constraints),\n audio: false,\n });\n }\n stopVideoStream(videoStream) {\n videoStream.getVideoTracks().forEach((track) => track.stop());\n }\n getFrame(videoPlayer) {\n return new Promise((resolve) => {\n const canvas = document.createElement('canvas');\n canvas.height = videoPlayer.videoHeight;\n canvas.width = videoPlayer.videoWidth;\n const context = canvas.getContext('2d');\n context.drawImage(videoPlayer, 0, 0);\n canvas.toBlob(resolve);\n });\n }\n startVideo() {\n this.getVideoStream()\n .then((stream) => {\n this.videoStream = stream;\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n videoPlayer.srcObject = stream;\n const width = parseInt(this.component.webcamSize) || 320;\n videoPlayer.setAttribute('width', width);\n videoPlayer.play();\n })\n .catch((err) => {\n console.error(err);\n this.cameraMode = false;\n this.redraw();\n });\n }\n stopVideo() {\n if (this.videoStream) {\n this.stopVideoStream(this.videoStream);\n this.videoStream = null;\n }\n }\n takePicture() {\n const { videoPlayer } = this.refs;\n if (!videoPlayer) {\n console.warn('Video player not found in template.');\n this.cameraMode = false;\n this.redraw();\n return;\n }\n this.getFrame(videoPlayer)\n .then((frame) => {\n frame.name = `photo-${Date.now()}.png`;\n this.handleFilesToUpload([frame]);\n this.cameraMode = false;\n this.redraw();\n });\n }\n browseFiles(attrs = {}) {\n return new Promise((resolve) => {\n const fileInput = this.ce('input', Object.assign({ type: 'file', style: 'height: 0; width: 0; visibility: hidden;', tabindex: '-1' }, attrs));\n document.body.appendChild(fileInput);\n fileInput.addEventListener('change', () => {\n resolve(fileInput.files);\n document.body.removeChild(fileInput);\n }, true);\n // There is no direct way to trigger a file dialog. To work around this, create an input of type file and trigger\n // a click event on it.\n if (typeof fileInput.trigger === 'function') {\n fileInput.trigger('click');\n }\n else {\n fileInput.click();\n }\n });\n }\n set cameraMode(value) {\n this._cameraMode = value;\n if (value) {\n this.startVideo();\n }\n else {\n this.stopVideo();\n }\n }\n get cameraMode() {\n return this._cameraMode;\n }\n get useWebViewCamera() {\n return this.imageUpload && webViewCamera;\n }\n get imageUpload() {\n return Boolean(this.component.image);\n }\n get browseOptions() {\n const options = {};\n if (this.component.multiple) {\n options.multiple = true;\n }\n if (this.component.capture) {\n options.capture = this.component.capture;\n }\n //use \"accept\" attribute only for desktop devices because of its limited support by mobile browsers\n const filePattern = this.component.filePattern.trim() || '';\n if (!this.isMobile.any) {\n const imagesPattern = 'image/*';\n if (this.imageUpload && (!filePattern || filePattern === '*')) {\n options.accept = imagesPattern;\n }\n else if (this.imageUpload && !filePattern.includes(imagesPattern)) {\n options.accept = `${imagesPattern},${filePattern}`;\n }\n else {\n options.accept = filePattern;\n }\n }\n // if input capture is set, we need the \"accept\" attribute to determine which device to launch\n else if (this.component.capture) {\n if (filePattern.includes('video')) {\n options.accept = 'video/*';\n }\n else if (filePattern.includes('audio')) {\n options.accept = 'audio/*';\n }\n else {\n options.accept = 'image/*';\n }\n }\n return options;\n }\n get actions() {\n return {\n abort: this.abortRequest.bind(this),\n };\n }\n attach(element) {\n this.loadRefs(element, {\n fileDrop: 'single',\n fileBrowse: 'single',\n galleryButton: 'single',\n cameraButton: 'single',\n takePictureButton: 'single',\n toggleCameraMode: 'single',\n videoPlayer: 'single',\n fileLink: 'multiple',\n removeLink: 'multiple',\n fileToSyncRemove: 'multiple',\n fileImage: 'multiple',\n fileType: 'multiple',\n fileProcessingLoader: 'single',\n syncNow: 'single',\n restoreFile: 'multiple',\n progress: 'multiple',\n });\n // Ensure we have an empty input refs. We need this for the setValue method to redraw the control when it is set.\n this.refs.input = [];\n const superAttach = super.attach(element);\n if (this.refs.fileDrop) {\n // if (!this.statuses.length) {\n // this.refs.fileDrop.removeAttribute('hidden');\n // }\n const _this = this;\n this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {\n this.className = 'fileSelector fileDragOver';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'dragleave', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n });\n this.addEventListener(this.refs.fileDrop, 'drop', function (event) {\n this.className = 'fileSelector';\n event.preventDefault();\n _this.handleFilesToUpload(event.dataTransfer.files);\n });\n }\n this.addEventListener(element, 'click', (event) => {\n this.handleAction(event);\n });\n if (this.refs.fileBrowse) {\n this.addEventListener(this.refs.fileBrowse, 'click', (event) => {\n event.preventDefault();\n this.browseFiles(this.browseOptions)\n .then((files) => {\n this.handleFilesToUpload(files);\n });\n });\n }\n this.refs.fileLink.forEach((fileLink, index) => {\n this.addEventListener(fileLink, 'click', (event) => {\n event.preventDefault();\n this.getFile(this.dataValue[index]);\n });\n });\n this.refs.removeLink.forEach((removeLink, index) => {\n this.addEventListener(removeLink, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.dataValue[index];\n this.handleFileToRemove(fileInfo);\n });\n });\n this.refs.fileToSyncRemove.forEach((fileToSyncRemove, index) => {\n this.addEventListener(fileToSyncRemove, 'click', (event) => {\n event.preventDefault();\n this.filesToSync.filesToUpload.splice(index, 1);\n this.redraw();\n });\n });\n this.refs.restoreFile.forEach((fileToRestore, index) => {\n this.addEventListener(fileToRestore, 'click', (event) => {\n event.preventDefault();\n const fileInfo = this.filesToSync.filesToDelete[index];\n delete fileInfo.status;\n delete fileInfo.message;\n this.filesToSync.filesToDelete.splice(index, 1);\n this.dataValue.push(fileInfo);\n this.triggerChange();\n this.redraw();\n });\n });\n if (this.refs.galleryButton && webViewCamera) {\n this.addEventListener(this.refs.galleryButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.PHOTOLIBRARY,\n });\n });\n }\n if (this.refs.cameraButton && webViewCamera) {\n this.addEventListener(this.refs.cameraButton, 'click', (event) => {\n event.preventDefault();\n webViewCamera.getPicture((success) => {\n window.resolveLocalFileSystemURL(success, (fileEntry) => {\n fileEntry.file((file) => {\n const reader = new FileReader();\n reader.onloadend = (evt) => {\n const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });\n blob.name = file.name;\n this.handleFilesToUpload([blob]);\n };\n reader.readAsArrayBuffer(file);\n });\n });\n }, (err) => {\n console.error(err);\n }, {\n sourceType: webViewCamera.PictureSourceType.CAMERA,\n encodingType: webViewCamera.EncodingType.PNG,\n mediaType: webViewCamera.MediaType.PICTURE,\n saveToPhotoAlbum: true,\n correctOrientation: false,\n });\n });\n }\n if (this.refs.takePictureButton) {\n this.addEventListener(this.refs.takePictureButton, 'click', (event) => {\n event.preventDefault();\n this.takePicture();\n });\n }\n if (this.refs.toggleCameraMode) {\n this.addEventListener(this.refs.toggleCameraMode, 'click', (event) => {\n event.preventDefault();\n this.cameraMode = !this.cameraMode;\n this.redraw();\n });\n }\n this.refs.fileType.forEach((fileType, index) => {\n if (!this.dataValue[index]) {\n return;\n }\n this.dataValue[index].fileType = this.dataValue[index].fileType || this.component.fileTypes[0].label;\n this.addEventListener(fileType, 'change', (event) => {\n event.preventDefault();\n const fileType = this.component.fileTypes.find((typeObj) => typeObj.value === event.target.value);\n this.dataValue[index].fileType = fileType.label;\n });\n });\n this.addEventListener(this.refs.syncNow, 'click', (event) => {\n event.preventDefault();\n this.syncFiles();\n });\n const fileService = this.fileService;\n if (fileService) {\n const loadingImages = [];\n this.filesReady = new Promise((resolve, reject) => {\n this.filesReadyResolve = resolve;\n this.filesReadyReject = reject;\n });\n this.refs.fileImage.forEach((image, index) => {\n loadingImages.push(this.loadImage(this.dataValue[index]).then((url) => (image.src = url)));\n });\n if (loadingImages.length) {\n Promise.all(loadingImages).then(() => {\n this.filesReadyResolve();\n }).catch(() => this.filesReadyReject());\n }\n else {\n this.filesReadyResolve();\n }\n }\n return superAttach;\n }\n /* eslint-disable max-len */\n fileSize(a, b, c, d, e) {\n return `${(b = Math, c = b.log, d = 1024, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2)} ${e ? `${'kMGTPEZY'[--e]}B` : 'Bytes'}`;\n }\n /* eslint-enable max-len */\n /* eslint-disable max-depth */\n globStringToRegex(str) {\n str = str.replace(/\\s/g, '');\n let regexp = '', excludes = [];\n if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {\n regexp = str.substring(1, str.length - 1);\n }\n else {\n const split = str.split(',');\n if (split.length > 1) {\n for (let i = 0; i < split.length; i++) {\n const r = this.globStringToRegex(split[i]);\n if (r.regexp) {\n regexp += `(${r.regexp})`;\n if (i < split.length - 1) {\n regexp += '|';\n }\n }\n else {\n excludes = excludes.concat(r.excludes);\n }\n }\n }\n else {\n if (str.startsWith('!')) {\n excludes.push(`^((?!${this.globStringToRegex(str.substring(1)).regexp}).)*$`);\n }\n else {\n if (str.startsWith('.')) {\n str = `*${str}`;\n }\n regexp = `^${str.replace(new RegExp('[.\\\\\\\\+*?\\\\[\\\\^\\\\]$(){}=!<>|:\\\\-]', 'g'), '\\\\$&')}$`;\n regexp = regexp.replace(/\\\\\\*/g, '.*').replace(/\\\\\\?/g, '.');\n }\n }\n }\n return { regexp, excludes };\n }\n /* eslint-enable max-depth */\n translateScalars(str) {\n if (typeof str === 'string') {\n if (str.search(/kb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024);\n }\n if (str.search(/mb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024);\n }\n if (str.search(/gb/i) === str.length - 2) {\n return parseFloat(str.substring(0, str.length - 2) * 1024 * 1024 * 1024);\n }\n if (str.search(/b/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/s/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1));\n }\n if (str.search(/m/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 60);\n }\n if (str.search(/h/i) === str.length - 1) {\n return parseFloat(str.substring(0, str.length - 1) * 3600);\n }\n }\n return str;\n }\n validatePattern(file, val) {\n if (!val) {\n return true;\n }\n const pattern = this.globStringToRegex(val);\n let valid = true;\n if (pattern.regexp && pattern.regexp.length) {\n const regexp = new RegExp(pattern.regexp, 'i');\n valid = (!lodash_1.default.isNil(file.type) && regexp.test(file.type)) ||\n (!lodash_1.default.isNil(file.name) && regexp.test(file.name));\n }\n valid = pattern.excludes.reduce((result, excludePattern) => {\n const exclude = new RegExp(excludePattern, 'i');\n return result && (lodash_1.default.isNil(file.type) || exclude.test(file.type)) &&\n (lodash_1.default.isNil(file.name) || exclude.test(file.name));\n }, valid);\n return valid;\n }\n validateMinSize(file, val) {\n return file.size + 0.1 >= this.translateScalars(val);\n }\n validateMaxSize(file, val) {\n return file.size - 0.1 <= this.translateScalars(val);\n }\n abortRequest(id) {\n const abortUpload = this.abortUploads.find(abortUpload => abortUpload.id === id);\n if (abortUpload) {\n abortUpload.abort();\n }\n }\n handleAction(event) {\n const target = event.target;\n if (!target.id) {\n return;\n }\n const [action, id] = target.id.split('-');\n if (!action || !id || !this.actions[action]) {\n return;\n }\n this.actions[action](id);\n }\n getFileName(file) {\n return (0, utils_1.uniqueName)(file.name, this.component.fileNameTemplate, this.evalContext());\n }\n getInitFileToSync(file) {\n const escapedFileName = file.name ? file.name.replaceAll('<', '&lt;').replaceAll('>', '&gt;') : file.name;\n return {\n id: createRandomString(),\n // Get a unique name for this file to keep file collisions from occurring.\n dir: this.interpolate(this.component.dir || ''),\n name: this.getFileName(file),\n originalName: escapedFileName,\n fileKey: this.component.fileKey || 'file',\n storage: this.component.storage,\n options: this.component.options,\n file,\n size: file.size,\n status: 'info',\n message: this.t('Processing file. Please wait...'),\n hash: '',\n };\n }\n handleSubmissionRevisions(file) {\n return __awaiter(this, void 0, void 0, function* () {\n if (this.root.form.submissionRevisions !== 'true') {\n return '';\n }\n const bmf = new browser_md5_file_1.default();\n const hash = yield new Promise((resolve, reject) => {\n this.emit('fileUploadingStart');\n bmf.md5(file, (err, md5) => {\n if (err) {\n return reject(err);\n }\n return resolve(md5);\n });\n });\n this.emit('fileUploadingEnd');\n return hash;\n });\n }\n validateFileName(file) {\n // Check if file with the same name is being uploaded\n const fileWithSameNameUploading = this.filesToSync.filesToUpload\n .some(fileToSync => { var _a; return ((_a = fileToSync.file) === null || _a === void 0 ? void 0 : _a.name) === file.name; });\n const fileWithSameNameUploaded = this.dataValue\n .some(fileStatus => fileStatus.originalName === file.name);\n return fileWithSameNameUploaded || fileWithSameNameUploading\n ? {\n status: 'error',\n message: this.t(`File with the same name is already ${fileWithSameNameUploading ? 'being ' : ''}uploaded`),\n }\n : {};\n }\n validateFileSettings(file) {\n // Check file pattern\n if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {\n return {\n status: 'error',\n message: this.t('File is the wrong type; it must be {{ pattern }}', {\n pattern: this.component.filePattern,\n }),\n };\n }\n // Check file minimum size\n if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {\n return {\n status: 'error',\n message: this.t('File is too small; it must be at least {{ size }}', {\n size: this.component.fileMinSize,\n }),\n };\n }\n // Check file maximum size\n if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {\n return {\n status: 'error',\n message: this.t('File is too big; it must be at most {{ size }}', {\n size: this.component.fileMaxSize,\n }),\n };\n }\n return {};\n }\n validateFileService() {\n const { fileService } = this;\n return !fileService\n ? {\n status: 'error',\n message: this.t('File Service not provided.'),\n }\n : {};\n }\n validateFile(file) {\n const fileServiceValidation = this.validateFileService();\n if (fileServiceValidation.status === 'error') {\n return fileServiceValidation;\n }\n const fileNameValidation = this.validateFileName(file);\n if (fileNameValidation.status === 'error') {\n return fileNameValidation;\n }\n return this.validateFileSettings(file);\n }\n getGroupPermissions() {\n let groupKey = null;\n let groupPermissions = null;\n //Iterate through form components to find group resource if one exists\n this.root.everyComponent((element) => {\n var _a, _b;\n if (((_a = element.component) === null || _a === void 0 ? void 0 : _a.submissionAccess) || ((_b = element.component) === null || _b === void 0 ? void 0 : _b.defaultPermission)) {\n groupPermissions = !element.component.submissionAccess ? [\n {\n type: element.component.defaultPermission,\n roles: [],\n },\n ] : element.component.submissionAccess;\n groupPermissions.forEach((permission) => {\n groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;\n });\n }\n });\n return { groupKey, groupPermissions };\n }\n triggerFileProcessor(file) {\n return __awaiter(this, void 0, void 0, function* () {\n let processedFile = null;\n if (this.root.options.fileProcessor) {\n try {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'block';\n }\n const fileProcessorHandler = (0, fileProcessor_1.default)(this.fileService, this.root.options.fileProcessor);\n processedFile = yield fileProcessorHandler(file, this.component.properties);\n }\n catch (err) {\n this.fileDropHidden = false;\n return {\n status: 'error',\n message: this.t('File processing has been failed.'),\n };\n }\n finally {\n if (this.refs.fileProcessingLoader) {\n this.refs.fileProcessingLoader.style.display = 'none';\n }\n }\n }\n return {\n file: processedFile,\n };\n });\n }\n prepareFileToUpload(file) {\n return __awaiter(this, void 0, void 0, function* () {\n const fileToSync = this.getInitFileToSync(file);\n fileToSync.hash = yield this.handleSubmissionRevisions(file);\n const { status, message } = this.validateFile(file);\n if (status === 'error') {\n fileToSync.isValidationError = true;\n fileToSync.status = status;\n fileToSync.message = message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.component.privateDownload) {\n file.private = true;\n }\n const { groupKey, groupPermissions } = this.getGroupPermissions();\n const processedFile = yield this.triggerFileProcessor(file);\n if (processedFile.status === 'error') {\n fileToSync.status === 'error';\n fileToSync.message = processedFile.message;\n return this.filesToSync.filesToUpload.push(fileToSync);\n }\n if (this.autoSync) {\n fileToSync.message = this.t('Ready to be uploaded into storage');\n }\n this.filesToSync.filesToUpload.push(Object.assign(Object.assign({}, fileToSync), { message: fileToSync.message, file: processedFile.file || file, url: this.interpolate(this.component.url, { file: fileToSync }), groupPermissions, groupResourceId: groupKey ? this.currentForm.submission.data[groupKey]._id : null }));\n });\n }\n prepareFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n // Only allow one upload if not multiple.\n if (!this.component.multiple) {\n files = Array.prototype.slice.call(files, 0, 1);\n }\n if (this.component.storage && files && files.length) {\n this.fileDropHidden = true;\n return Promise.all([...files].map((file) => __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFileToUpload(file);\n this.redraw();\n })));\n }\n else {\n return Promise.resolve();\n }\n });\n }\n handleFilesToUpload(files) {\n return __awaiter(this, void 0, void 0, function* () {\n yield this.prepareFilesToUpload(files);\n if (!this.autoSync) {\n yield this.syncFiles();\n }\n });\n }\n prepareFileToDelete(fileInfo) {\n this.filesToSync.filesToDelete.push(Object.assign(Object.assign({}, fileInfo), { status: 'info', message: this.autoSync\n ? this.t('Ready to be removed from storage')\n : this.t('Preparing file to remove') }));\n const index = this.dataValue.findIndex(file => file.name === fileInfo.name);\n this.splice(index);\n this.redraw();\n }\n handleFileToRemove(fileInfo) {\n this.prepareFileToDelete(fileInfo);\n if (!this.autoSync) {\n this.syncFiles();\n }\n }\n deleteFile(fileInfo) {\n return __awaiter(this, void 0, void 0, function* () {\n const { options = {} } = this.component;\n if (fileInfo && (['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage))) {\n const { fileService } = this;\n if (fileService && typeof fileService.deleteFile === 'function') {\n return yield fileService.deleteFile(fileInfo, options);\n }\n else {\n const formio = this.options.formio || (this.root && this.root.formio);\n if (formio) {\n return yield formio.makeRequest('', fileInfo.url, 'delete');\n }\n }\n }\n });\n }\n delete() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToDelete.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToDelete.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n try {\n if (fileToSync.isValidationError) {\n return { fileToSync };\n }\n yield this.deleteFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully removed');\n }\n catch (response) {\n fileToSync.status = 'error';\n fileToSync.message = typeof response === 'string' ? response : response.toString();\n }\n finally {\n this.redraw();\n }\n return { fileToSync };\n })));\n });\n }\n updateProgress(fileInfo, progressEvent) {\n fileInfo.progress = parseInt(100.0 * progressEvent.loaded / progressEvent.total);\n if (fileInfo.status !== 'progress') {\n fileInfo.status = 'progress';\n delete fileInfo.message;\n this.redraw();\n }\n else {\n const progress = Array.prototype.find.call(this.refs.progress, progressElement => progressElement.id === fileInfo.id);\n progress.innerHTML = `<span class=\"visually-hidden\">${fileInfo.progress}% ${this.t('Complete')}</span>`;\n progress.style.width = `${fileInfo.progress}%`;\n progress.ariaValueNow = fileInfo.progress.toString();\n }\n }\n getMultipartOptions(fileToSync) {\n let count = 0;\n return this.component.useMultipartUpload && this.component.multipart ? Object.assign(Object.assign({}, this.component.multipart), { progressCallback: (total) => {\n count++;\n fileToSync.status = 'progress';\n fileToSync.progress = parseInt(100 * count / total);\n delete fileToSync.message;\n this.redraw();\n }, changeMessage: (message) => {\n fileToSync.message = message;\n this.redraw();\n } }) : false;\n }\n uploadFile(fileToSync) {\n return __awaiter(this, void 0, void 0, function* () {\n return yield this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir, \n // Progress callback\n this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => { }, \n // Abort upload callback\n (abort) => this.abortUploads.push({\n id: fileToSync.id,\n abort,\n }), this.getMultipartOptions(fileToSync));\n });\n }\n upload() {\n return __awaiter(this, void 0, void 0, function* () {\n if (!this.filesToSync.filesToUpload.length) {\n return Promise.resolve();\n }\n return yield Promise.all(this.filesToSync.filesToUpload.map((fileToSync) => __awaiter(this, void 0, void 0, function* () {\n let fileInfo = null;\n try {\n if (fileToSync.isValidationError) {\n return {\n fileToSync,\n fileInfo,\n };\n }\n fileInfo = yield this.uploadFile(fileToSync);\n fileToSync.status = 'success';\n fileToSync.message = this.t('Succefully uploaded');\n fileInfo.originalName = fileToSync.originalName;\n fileInfo.hash = fileToSync.hash;\n }\n catch (response) {\n fileToSync.status = 'error';\n delete fileToSync.progress;\n fileToSync.message = typeof response === 'string'\n ? response\n : response.type === 'abort'\n ? this.t('Request was aborted')\n : response.toString();\n }\n finally {\n delete fileToSync.progress;\n this.redraw();\n }\n return {\n fileToSync,\n fileInfo,\n };\n })));\n });\n }\n syncFiles() {\n return __awaiter(this, void 0, void 0, function* () {\n this.isSyncing = true;\n this.fileDropHidden = true;\n this.redraw();\n try {\n const [filesToDelete = [], filesToUpload = []] = yield Promise.all([this.delete(), this.upload()]);\n this.filesToSync.filesToDelete = filesToDelete\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n this.filesToSync.filesToUpload = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'error'; })\n .map(file => file.fileToSync);\n if (!this.hasValue()) {\n this.dataValue = [];\n }\n const data = filesToUpload\n .filter(file => { var _a; return ((_a = file.fileToSync) === null || _a === void 0 ? void 0 : _a.status) === 'success'; })\n .map(file => file.fileInfo);\n this.dataValue.push(...data);\n this.triggerChange();\n return Promise.resolve();\n }\n catch (err) {\n return Promise.reject();\n }\n finally {\n this.isSyncing = false;\n this.fileDropHidden = false;\n this.abortUploads = [];\n this.redraw();\n }\n });\n }\n getFile(fileInfo) {\n const { options = {} } = this.component;\n const { fileService } = this;\n if (!fileService) {\n return alert('File Service not provided');\n }\n if (this.component.privateDownload) {\n fileInfo.private = true;\n }\n fileService.downloadFile(fileInfo, options).then((file) => {\n if (file) {\n if (['base64', 'indexeddb'].includes(file.storage)) {\n (0, downloadjs_1.default)(file.url, file.originalName || file.name, file.type);\n }\n else {\n window.open(file.url, '_blank');\n }\n }\n })\n .catch((response) => {\n // Is alert the best way to do this?\n // User is expecting an immediate notification due to attempting to download a file.\n alert(response);\n });\n }\n focus() {\n if ('beforeFocus' in this.parent) {\n this.parent.beforeFocus(this);\n }\n if (this.refs.fileBrowse) {\n this.refs.fileBrowse.focus();\n }\n }\n beforeSubmit() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n if (!this.autoSync) {\n return Promise.resolve();\n }\n yield this.syncFiles();\n return this.shouldSyncFiles\n ? Promise.reject('Synchronization is failed')\n : Promise.resolve();\n }\n catch (error) {\n return Promise.reject(error.message);\n }\n });\n }\n destroy(all) {\n this.stopVideo();\n super.destroy(all);\n }\n}\nexports[\"default\"] = FileComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/file/File.js?");
6657
6667
 
6658
6668
  /***/ }),
6659
6669
 
@@ -6719,7 +6729,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
6719
6729
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
6720
6730
 
6721
6731
  "use strict";
6722
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/* eslint-disable max-statements */\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../_classes/componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst eventemitter3_1 = __importDefault(__webpack_require__(/*! eventemitter3 */ \"./node_modules/eventemitter3/index.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst Form_1 = __importDefault(__webpack_require__(/*! ../../Form */ \"./lib/cjs/Form.js\"));\nclass FormComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n label: 'Form',\n type: 'form',\n key: 'form',\n src: '',\n reference: true,\n form: '',\n path: '',\n tableView: true,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Nested Form',\n icon: 'wpforms',\n group: 'premium',\n documentation: '/userguide/form-building/premium-components#nested-form',\n weight: 110,\n schema: FormComponent.schema()\n };\n }\n static savedValueTypes() {\n return [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n this.formObj = {\n display: this.component.display,\n settings: this.component.settings,\n components: this.component.components\n };\n this.valueChanged = false;\n this.subForm = null;\n this.formSrc = '';\n if (this.component.src) {\n this.formSrc = this.component.src;\n }\n if (!this.component.src &&\n !this.options.formio &&\n (this.component.form || this.component.path)) {\n if (this.component.project) {\n this.formSrc = Formio_1.Formio.getBaseUrl();\n // Check to see if it is a MongoID.\n if ((0, utils_1.isMongoId)(this.component.project)) {\n this.formSrc += '/project';\n }\n this.formSrc += `/${this.component.project}`;\n this.options.project = this.formSrc;\n }\n else {\n this.formSrc = Formio_1.Formio.getProjectUrl();\n this.options.project = this.formSrc;\n }\n if (this.component.form) {\n if ((0, utils_1.isMongoId)(this.component.form)) {\n this.formSrc += `/form/${this.component.form}`;\n }\n else {\n this.formSrc += `/${this.component.form}`;\n }\n }\n else if (this.component.path) {\n this.formSrc += `/${this.component.path}`;\n }\n }\n // Build the source based on the root src path.\n if (!this.formSrc && this.options.formio) {\n const rootSrc = this.options.formio.formsUrl;\n if (this.component.form && (0, utils_1.isMongoId)(this.component.form)) {\n this.formSrc = `${rootSrc}/${this.component.form}`;\n }\n else {\n const formPath = this.component.path || this.component.form;\n this.formSrc = `${rootSrc.replace(/\\/form$/, '')}/${formPath}`;\n }\n }\n if (this.builderMode && this.component.hasOwnProperty('formRevision')) {\n this.component.revision = this.component.formRevision;\n delete this.component.formRevision;\n }\n // Add revision version if set.\n if (this.component.revision || this.component.revision === 0 ||\n this.component.formRevision || this.component.formRevision === 0\n || this.component.revisionId) {\n this.setFormRevision(this.component.revisionId || this.component.revision || this.component.formRevision);\n }\n return this.createSubForm();\n }\n get dataReady() {\n return this.subFormReady || Promise.resolve();\n }\n get defaultValue() {\n // Not not provide a default value unless the subform is ready so that it will initialize correctly.\n return this.subForm ? super.defaultValue : null;\n }\n get defaultSchema() {\n return FormComponent.schema();\n }\n get emptyValue() {\n return { data: {} };\n }\n get ready() {\n return this.subFormReady || Promise.resolve();\n }\n get useOriginalRevision() {\n var _a, _b;\n return ((_a = this.component) === null || _a === void 0 ? void 0 : _a.useOriginalRevision) && !!((_b = this.formObj) === null || _b === void 0 ? void 0 : _b.revisions);\n }\n setFormRevision(rev) {\n // Remove current revisions from src if it is\n this.formSrc = this.formSrc.replace(/\\/v\\/[0-9a-z]+/, '');\n const revNumber = Number.parseInt(rev);\n if (!isNaN(revNumber)) {\n this.subFormRevision = rev;\n this.formSrc += `/v/${rev}`;\n }\n else {\n this.subFormRevision = undefined;\n }\n }\n getComponent(path, fn) {\n path = (0, utils_1.getArrayFromComponentPath)(path);\n if (path[0] === 'data') {\n path.shift();\n }\n const originalPathStr = `${this.path}.data.${(0, utils_1.getStringFromComponentPath)(path)}`;\n if (this.subForm) {\n return this.subForm.getComponent(path, fn, originalPathStr);\n }\n }\n /* eslint-disable max-statements */\n getSubOptions(options = {}) {\n options.events = this.createEmitter();\n // Make sure to not show the submit button in wizards in the nested forms.\n lodash_1.default.set(options, 'buttonSettings.showSubmit', false);\n if (!this.options) {\n return options;\n }\n if (this.options.base) {\n options.base = this.options.base;\n }\n if (this.options.project) {\n options.project = this.options.project;\n }\n if (this.options.readOnly || this.component.disabled) {\n options.readOnly = this.options.readOnly || this.component.disabled;\n }\n if (this.options.breadcrumbSettings) {\n options.breadcrumbSettings = this.options.breadcrumbSettings;\n }\n if (this.options.buttonSettings) {\n options.buttonSettings = lodash_1.default.clone(this.options.buttonSettings);\n }\n if (this.options.viewAsHtml) {\n options.viewAsHtml = this.options.viewAsHtml;\n }\n if (this.options.language) {\n options.language = this.options.language;\n }\n if (this.options.template) {\n options.template = this.options.template;\n }\n if (this.options.templates) {\n options.templates = this.options.templates;\n }\n if (this.options.renderMode) {\n options.renderMode = this.options.renderMode;\n }\n if (this.options.attachMode) {\n options.attachMode = this.options.attachMode;\n }\n if (this.options.iconset) {\n options.iconset = this.options.iconset;\n }\n if (this.options.fileService) {\n options.fileService = this.options.fileService;\n }\n if (this.options.onChange) {\n options.onChange = this.options.onChange;\n }\n if (this.options.preview) {\n options.preview = this.options.preview;\n }\n if (this.options.inEditGrid) {\n options.inEditGrid = this.options.inEditGrid;\n }\n if (this.options.saveDraft) {\n options.saveDraft = this.options.saveDraft;\n options.formio = new Formio_1.Formio(this.formSrc);\n }\n if (this.options.saveDraftThrottle) {\n options.saveDraftThrottle = this.options.saveDraftThrottle;\n }\n if (this.options.skipDraftRestore) {\n options.skipDraftRestore = this.options.skipDraftRestore;\n }\n return options;\n }\n /* eslint-enable max-statements */\n render() {\n if (this.builderMode) {\n return super.render(this.component.label || 'Nested form');\n }\n const subform = this.subForm ? this.subForm.render() : this.renderTemplate('loading');\n return super.render(subform);\n }\n asString(value) {\n return this.getValueAsString(value);\n }\n /**\n * Prints out the value of form components as a datagrid value.\n */\n getValueAsString(value, options) {\n if (!value) {\n return 'No data provided';\n }\n if (!value.data && value._id) {\n return value._id;\n }\n if (!value.data || !Object.keys(value.data).length) {\n return 'No data provided';\n }\n if (options === null || options === void 0 ? void 0 : options.email) {\n let result = (`\n <table border=\"1\" style=\"width:100%\">\n <tbody>\n `);\n this.everyComponent((component) => {\n if (component.isInputComponent && component.visible && !component.skipInEmail) {\n result += (`\n <tr>\n <th style=\"padding: 5px 10px;\">${component.label}</th>\n <td style=\"width:100%;padding:5px 10px;\">${component.getView(component.dataValue, options)}</td>\n </tr>\n `);\n }\n }, Object.assign(Object.assign({}, options), { fromRoot: true }));\n result += (`\n </tbody>\n </table>\n `);\n return result;\n }\n if (lodash_1.default.isEmpty(value)) {\n return '';\n }\n return '[Complex Data]';\n }\n attach(element) {\n // Don't attach in builder.\n if (this.builderMode) {\n return super.attach(element);\n }\n return super.attach(element)\n .then(() => {\n if (this.isSubFormLazyLoad() && !this.hasLoadedForm && !this.subFormLoading) {\n this.createSubForm(true);\n }\n return this.subFormReady.then(() => {\n this.empty(element);\n if (this.options.builder) {\n this.setContent(element, this.ce('div', {\n class: 'text-muted text-center p-2'\n }, this.text(this.formObj.title)));\n return;\n }\n this.setContent(element, this.render());\n if (this.subForm) {\n if (this.isNestedWizard) {\n element = this.root.element;\n }\n this.subForm.attach(element);\n this.valueChanged = this.hasSetValue;\n if (!this.valueChanged && this.dataValue.state !== 'submitted') {\n this.setDefaultValue();\n }\n else {\n this.restoreValue();\n }\n }\n if (!this.builderMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n this.componentModal = new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\n this.setOpenModalElement();\n }\n this.calculateValue();\n });\n });\n }\n detach() {\n if (this.subForm) {\n this.subForm.detach();\n }\n super.detach();\n }\n get currentForm() {\n return this._currentForm;\n }\n get hasLoadedForm() {\n return this.formObj\n && this.formObj.components\n && Array.isArray(this.formObj.components)\n && this.formObj.components.length;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n if (!this.subForm) {\n return;\n }\n this.subForm.getComponents().forEach(component => {\n component.currentForm = this;\n });\n }\n get isRevisionChanged() {\n return lodash_1.default.isNumber(this.subFormRevision)\n && lodash_1.default.isNumber(this.formObj._vid)\n && this.formObj._vid !== this.subFormRevision;\n }\n destroy() {\n if (this.subForm) {\n this.subForm.destroy();\n this.subForm = null;\n this.subFormReady = null;\n }\n super.destroy();\n }\n redraw() {\n if (this.subForm) {\n this.subForm.form = this.formObj;\n this.setSubFormDisabled(this.subForm);\n }\n return super.redraw();\n }\n /**\n * Pass everyComponent to subform.\n * @param args\n * @returns {*|void}\n */\n everyComponent(...args) {\n if (this.subForm) {\n this.subForm.everyComponent(...args);\n }\n }\n setSubFormDisabled(subForm) {\n subForm.disabled = this.disabled; // When the Nested Form is disabled make the subForm disabled\n }\n updateSubWizards(subForm) {\n var _a, _b;\n if (this.isNestedWizard && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.subWizards) && ((_b = subForm === null || subForm === void 0 ? void 0 : subForm._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard') {\n const existedForm = this.root.subWizards.findIndex(form => form.component.form === this.component.form);\n if (existedForm !== -1) {\n this.root.subWizards[existedForm] = this;\n }\n else {\n this.root.subWizards.push(this);\n }\n this.emit('subWizardsUpdated', subForm);\n }\n }\n /**\n * Create a subform instance.\n *\n * @return {*}\n */\n createSubForm(fromAttach) {\n this.subFormReady = this.loadSubForm(fromAttach).then((form) => {\n if (!form) {\n return;\n }\n // Iterate through every component and hide the submit button.\n (0, utils_1.eachComponent)(form.components, (component) => {\n this.hideSubmitButton(component);\n });\n // If the subform is already created then destroy the old one.\n if (this.subForm) {\n this.subForm.destroy();\n }\n // Render the form.\n return (new Form_1.default(form, this.getSubOptions())).ready.then((instance) => {\n this.subForm = instance;\n this.subForm.currentForm = this;\n this.subForm.parent = this;\n this.subForm.parentVisible = this.visible;\n this.subForm.on('change', () => {\n if (this.subForm) {\n this.dataValue = this.subForm.getValue();\n this.triggerChange({\n noEmit: true\n });\n }\n });\n this.subForm.url = this.formSrc;\n this.subForm.nosubmit = true;\n this.subForm.root = this.root;\n this.subForm.localRoot = this.isNestedWizard ? this.localRoot : this.subForm;\n this.restoreValue();\n this.valueChanged = this.hasSetValue;\n this.onChange();\n return this.subForm;\n });\n }).then((subForm) => {\n this.updateSubWizards(subForm);\n return subForm;\n });\n return this.subFormReady;\n }\n hideSubmitButton(component) {\n const isSubmitButton = (component.type === 'button') &&\n ((component.action === 'submit') || !component.action);\n if (isSubmitButton) {\n component.hidden = true;\n }\n }\n /**\n * Load the subform.\n */\n loadSubForm(fromAttach) {\n var _a, _b, _c;\n if (this.builderMode || this.isHidden() || (this.isSubFormLazyLoad() && !fromAttach)) {\n return Promise.resolve();\n }\n if (this.hasLoadedForm && !this.isRevisionChanged &&\n !(this.options.pdf && ((_a = this.component) === null || _a === void 0 ? void 0 : _a.useOriginalRevision) && lodash_1.default.isNull(this.subForm) && !this.subFormLoading)) {\n // Pass config down to sub forms.\n if (this.root && this.root.form && this.root.form.config && !this.formObj.config) {\n this.formObj.config = this.root.form.config;\n }\n return Promise.resolve(this.formObj);\n }\n else if (this.formSrc) {\n this.subFormLoading = true;\n const options = ((_b = this.root.formio) === null || _b === void 0 ? void 0 : _b.base) && ((_c = this.root.formio) === null || _c === void 0 ? void 0 : _c.projectUrl)\n ? {\n base: this.root.formio.base,\n project: this.root.formio.projectUrl,\n }\n : {};\n return (new Formio_1.Formio(this.formSrc, options)).loadForm({ params: { live: 1 } })\n .then((formObj) => {\n this.formObj = formObj;\n if (this.options.pdf && this.component.useOriginalRevision) {\n this.formObj.display = 'form';\n }\n this.subFormLoading = false;\n return formObj;\n })\n .catch((err) => {\n console.log(err);\n return null;\n });\n }\n return Promise.resolve();\n }\n get subFormData() {\n var _a;\n return ((_a = this.dataValue) === null || _a === void 0 ? void 0 : _a.data) || {};\n }\n checkComponentValidity(data, dirty, row, options, errors = []) {\n options = options || {};\n const silentCheck = options.silentCheck || false;\n if (this.subForm) {\n return this.subForm.checkValidity(this.subFormData, dirty, null, silentCheck, errors);\n }\n return super.checkComponentValidity(data, dirty, row, options, errors);\n }\n checkComponentConditions(data, flags, row) {\n const visible = super.checkComponentConditions(data, flags, row);\n // Return if already hidden\n if (!visible) {\n return visible;\n }\n if (this.subForm) {\n return this.subForm.checkConditions(this.subFormData);\n }\n // There are few cases when subForm is not loaded when a change is triggered,\n // so we need to perform checkConditions after it is ready, or some conditional fields might be hidden in View mode\n else if (this.subFormReady) {\n this.subFormReady.then(() => {\n if (this.subForm) {\n return this.subForm.checkConditions(this.subFormData);\n }\n });\n }\n return visible;\n }\n calculateValue(data, flags, row) {\n if (this.subForm) {\n return this.subForm.calculateValue(this.subFormData, flags);\n }\n return super.calculateValue(data, flags, row);\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n if (this.subForm) {\n this.subForm.setPristine(pristine);\n }\n }\n /**\n * Determine if the subform should be submitted.\n * @return {*|boolean}\n */\n get shouldSubmit() {\n return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.isHidden();\n }\n /**\n * Returns the data for the subform.\n *\n * @return {*}\n */\n getSubFormData() {\n if (lodash_1.default.get(this.subForm, 'form.display') === 'pdf') {\n return this.subForm.getSubmission();\n }\n else {\n return Promise.resolve(this.dataValue);\n }\n }\n /**\n * Submit the subform if configured to do so.\n *\n * @return {*}\n */\n submitSubForm() {\n // If we wish to submit the form on next page, then do that here.\n if (this.shouldSubmit) {\n return this.subFormReady.then(() => {\n if (!this.subForm) {\n return this.dataValue;\n }\n this.subForm.nosubmit = false;\n this.subForm.submitted = true;\n return this.subForm.submitForm().then(result => {\n this.subForm.loading = false;\n this.subForm.showAllErrors = false;\n this.dataValue = result.submission;\n return this.dataValue;\n }).catch(err => {\n this.subForm.showAllErrors = true;\n this.subForm.onSubmissionError(err);\n return Promise.reject(err);\n });\n });\n }\n return this.getSubFormData();\n }\n /**\n * Submit the form before the next page is triggered.\n */\n beforePage(next) {\n // Should not submit child forms if we are going to the previous page\n if (!next) {\n return super.beforePage(next);\n }\n return this.submitSubForm(true).then(() => super.beforePage(next));\n }\n /**\n * Submit the form before the whole form is triggered.\n */\n beforeSubmit() {\n var _a, _b, _c;\n const submission = this.dataValue;\n // Cancel triggered saveDraft\n if (((_a = this.subForm) === null || _a === void 0 ? void 0 : _a.draftEnabled) && ((_b = this.subForm.triggerSaveDraft) === null || _b === void 0 ? void 0 : _b.cancel)) {\n this.subForm.triggerSaveDraft.cancel();\n }\n const isAlreadySubmitted = submission && submission._id && submission.form;\n const isDraftSubmission = this.options.saveDraft && submission.state === 'draft';\n // This submission has already been submitted, so just return the reference data.\n if (isAlreadySubmitted && !((_c = this.subForm) === null || _c === void 0 ? void 0 : _c.wizard) && !isDraftSubmission) {\n this.dataValue = submission;\n return Promise.resolve(this.dataValue);\n }\n return this.submitSubForm(false)\n .then(() => {\n return this.dataValue;\n })\n .then(() => super.beforeSubmit());\n }\n isSubFormLazyLoad() {\n var _a, _b;\n return ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard' && this.component.lazyLoad;\n }\n isHidden() {\n if (!this.visible) {\n return true;\n }\n return !super.checkConditions(this.rootValue);\n }\n setValue(submission, flags = {}) {\n var _a;\n const changed = super.setValue(submission, flags);\n this.valueChanged = true;\n if (this.subForm) {\n const revisionPath = submission._frid ? '_frid' : '_vid';\n const shouldLoadOriginalRevision = this.useOriginalRevision\n && (lodash_1.default.isNumber(submission[revisionPath]) || lodash_1.default.isNumber(submission._fvid))\n && lodash_1.default.isNumber((_a = this.subForm.form) === null || _a === void 0 ? void 0 : _a[revisionPath])\n && submission._fvid !== this.subForm.form[revisionPath];\n if (shouldLoadOriginalRevision) {\n this.setFormRevision(submission._frid || submission._fvid);\n this.createSubForm().then(() => {\n this.attach(this.element);\n });\n }\n else {\n this.setSubFormValue(submission, flags);\n }\n }\n return changed;\n }\n setSubFormValue(submission, flags) {\n var _a, _b;\n const shouldLoadSubmissionById = submission\n && submission._id\n && this.subForm.formio\n && lodash_1.default.isEmpty(submission.data);\n if (shouldLoadSubmissionById) {\n const formId = submission.form || this.formObj.form || this.component.form;\n const submissionUrl = `${this.subForm.formio.formsUrl}/${formId}/submission/${submission._id}`;\n const options = ((_a = this.root.formio) === null || _a === void 0 ? void 0 : _a.base) && ((_b = this.root.formio) === null || _b === void 0 ? void 0 : _b.projectUrl)\n ? {\n base: this.root.formio.base,\n project: this.root.formio.projectUrl,\n }\n : {};\n this.subForm.setUrl(submissionUrl, Object.assign(Object.assign({}, this.options), options));\n this.subForm.loadSubmission().catch((err) => {\n console.error(`Unable to load subform submission ${submission._id}:`, err);\n });\n }\n else {\n this.subForm.setValue(submission, flags);\n }\n }\n isEmpty(value = this.dataValue) {\n return value === null || lodash_1.default.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value === null || value === void 0 ? void 0 : value.data) && !(value === null || value === void 0 ? void 0 : value._id));\n }\n areAllComponentsEmpty(data) {\n let res = true;\n if (this.subForm) {\n this.subForm.everyComponent((comp) => {\n const componentValue = lodash_1.default.get(data, comp.key);\n res &= comp.isEmpty(componentValue);\n });\n }\n else {\n res = false;\n }\n return res;\n }\n getValue() {\n if (this.subForm) {\n return this.subForm.getValue();\n }\n return this.dataValue;\n }\n get errors() {\n let errors = super.errors;\n if (this.subForm) {\n errors = errors.concat(this.subForm.errors);\n }\n return errors;\n }\n updateSubFormVisibility() {\n if (this.subForm) {\n this.subForm.parentVisible = this.visible;\n }\n }\n /**\n * Determines if this form is a Nested Wizard\n * which means it should be a Wizard itself and should be a direct child of a Wizard's page\n * @returns {boolean}\n */\n get isNestedWizard() {\n var _a, _b, _c, _d, _e;\n return ((_b = (_a = this.subForm) === null || _a === void 0 ? void 0 : _a._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard' && ((_e = (_d = (_c = this.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d._form) === null || _e === void 0 ? void 0 : _e.display) === 'wizard';\n }\n get visible() {\n return super.visible;\n }\n set visible(value) {\n const isNestedWizard = this.isNestedWizard;\n if (this._visible !== value) {\n this._visible = value;\n // Form doesn't load if hidden. If it becomes visible, create the form.\n if (!this.subForm && value) {\n this.createSubForm();\n this.subFormReady.then(() => {\n this.updateSubFormVisibility();\n this.clearOnHide();\n });\n this.redraw();\n return;\n }\n this.updateSubFormVisibility();\n this.clearOnHide();\n isNestedWizard ? this.rebuild() : this.redraw();\n }\n if (!value && isNestedWizard) {\n this.root.redraw();\n }\n }\n get parentVisible() {\n return super.parentVisible;\n }\n set parentVisible(value) {\n if (this._parentVisible !== value) {\n this._parentVisible = value;\n this.clearOnHide();\n // Form doesn't load if hidden. If it becomes visible, create the form.\n if (!this.subForm && value) {\n this.createSubForm();\n this.subFormReady.then(() => {\n this.updateSubFormVisibility();\n });\n this.redraw();\n return;\n }\n this.updateSubFormVisibility();\n this.redraw();\n }\n }\n isInternalEvent(event) {\n switch (event) {\n case 'focus':\n case 'blur':\n case 'componentChange':\n case 'componentError':\n case 'error':\n case 'formLoad':\n case 'languageChanged':\n case 'render':\n case 'checkValidity':\n case 'initialized':\n case 'submit':\n case 'submitButton':\n case 'nosubmit':\n case 'updateComponent':\n case 'submitDone':\n case 'submissionDeleted':\n case 'requestDone':\n case 'nextPage':\n case 'prevPage':\n case 'wizardNavigationClicked':\n case 'updateWizardNav':\n case 'restoreDraft':\n case 'saveDraft':\n case 'saveComponent':\n case 'pdfUploaded':\n return true;\n default:\n return false;\n }\n }\n createEmitter() {\n const emitter = new eventemitter3_1.default();\n const nativeEmit = emitter.emit;\n const that = this;\n emitter.emit = function (event, ...args) {\n const eventType = event.replace(`${that.options.namespace}.`, '');\n nativeEmit.call(this, event, ...args);\n if (!that.isInternalEvent(eventType)) {\n that.emit(eventType, ...args);\n }\n };\n return emitter;\n }\n deleteValue() {\n super.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n}\nexports[\"default\"] = FormComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/form/Form.js?");
6732
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\n/* eslint-disable max-statements */\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst Component_1 = __importDefault(__webpack_require__(/*! ../_classes/component/Component */ \"./lib/cjs/components/_classes/component/Component.js\"));\nconst ComponentModal_1 = __importDefault(__webpack_require__(/*! ../_classes/componentModal/ComponentModal */ \"./lib/cjs/components/_classes/componentModal/ComponentModal.js\"));\nconst eventemitter3_1 = __importDefault(__webpack_require__(/*! eventemitter3 */ \"./node_modules/eventemitter3/index.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst Form_1 = __importDefault(__webpack_require__(/*! ../../Form */ \"./lib/cjs/Form.js\"));\nclass FormComponent extends Component_1.default {\n static schema(...extend) {\n return Component_1.default.schema({\n label: 'Form',\n type: 'form',\n key: 'form',\n src: '',\n reference: true,\n form: '',\n path: '',\n tableView: true,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Nested Form',\n icon: 'wpforms',\n group: 'premium',\n documentation: '/userguide/form-building/premium-components#nested-form',\n weight: 110,\n schema: FormComponent.schema()\n };\n }\n static savedValueTypes() {\n return [utils_1.componentValueTypes.object];\n }\n init() {\n super.init();\n this.formObj = {\n display: this.component.display,\n settings: this.component.settings,\n components: this.component.components\n };\n this.valueChanged = false;\n this.subForm = null;\n this.formSrc = '';\n if (this.component.src) {\n this.formSrc = this.component.src;\n }\n if (!this.component.src &&\n !this.options.formio &&\n (this.component.form || this.component.path)) {\n if (this.component.project) {\n this.formSrc = Formio_1.Formio.getBaseUrl();\n // Check to see if it is a MongoID.\n if ((0, utils_1.isMongoId)(this.component.project)) {\n this.formSrc += '/project';\n }\n this.formSrc += `/${this.component.project}`;\n this.options.project = this.formSrc;\n }\n else {\n this.formSrc = Formio_1.Formio.getProjectUrl();\n this.options.project = this.formSrc;\n }\n if (this.component.form) {\n if ((0, utils_1.isMongoId)(this.component.form)) {\n this.formSrc += `/form/${this.component.form}`;\n }\n else {\n this.formSrc += `/${this.component.form}`;\n }\n }\n else if (this.component.path) {\n this.formSrc += `/${this.component.path}`;\n }\n }\n // Build the source based on the root src path.\n if (!this.formSrc && this.options.formio) {\n const rootSrc = this.options.formio.formsUrl;\n if (this.component.form && (0, utils_1.isMongoId)(this.component.form)) {\n this.formSrc = `${rootSrc}/${this.component.form}`;\n }\n else {\n const formPath = this.component.path || this.component.form;\n this.formSrc = `${rootSrc.replace(/\\/form$/, '')}/${formPath}`;\n }\n }\n if (this.builderMode && this.component.hasOwnProperty('formRevision')) {\n this.component.revision = this.component.formRevision;\n delete this.component.formRevision;\n }\n // Add revision version if set.\n if (this.component.revision || this.component.revision === 0 ||\n this.component.formRevision || this.component.formRevision === 0\n || this.component.revisionId) {\n this.setFormRevision(this.component.revisionId || this.component.revision || this.component.formRevision);\n }\n return this.createSubForm();\n }\n get dataReady() {\n return this.subFormReady || Promise.resolve();\n }\n get defaultValue() {\n // Not not provide a default value unless the subform is ready so that it will initialize correctly.\n return this.subForm ? super.defaultValue : null;\n }\n get defaultSchema() {\n return FormComponent.schema();\n }\n get emptyValue() {\n return { data: {} };\n }\n get ready() {\n return this.subFormReady || Promise.resolve();\n }\n get useOriginalRevision() {\n var _a, _b;\n return ((_a = this.component) === null || _a === void 0 ? void 0 : _a.useOriginalRevision) && !!((_b = this.formObj) === null || _b === void 0 ? void 0 : _b.revisions);\n }\n setFormRevision(rev) {\n // Remove current revisions from src if it is\n this.formSrc = this.formSrc.replace(/\\/v\\/[0-9a-z]+/, '');\n const revNumber = Number.parseInt(rev);\n if (!isNaN(revNumber)) {\n this.subFormRevision = rev;\n this.formSrc += `/v/${rev}`;\n }\n else {\n this.subFormRevision = undefined;\n }\n }\n getComponent(path, fn) {\n path = (0, utils_1.getArrayFromComponentPath)(path);\n if (path[0] === 'data') {\n path.shift();\n }\n const originalPathStr = `${this.path}.data.${(0, utils_1.getStringFromComponentPath)(path)}`;\n if (this.subForm) {\n return this.subForm.getComponent(path, fn, originalPathStr);\n }\n }\n /* eslint-disable max-statements */\n getSubOptions(options = {}) {\n options.events = this.createEmitter();\n // Make sure to not show the submit button in wizards in the nested forms.\n lodash_1.default.set(options, 'buttonSettings.showSubmit', false);\n if (!this.options) {\n return options;\n }\n if (this.options.base) {\n options.base = this.options.base;\n }\n if (this.options.project) {\n options.project = this.options.project;\n }\n if (this.options.readOnly || this.component.disabled) {\n options.readOnly = this.options.readOnly || this.component.disabled;\n }\n if (this.options.breadcrumbSettings) {\n options.breadcrumbSettings = this.options.breadcrumbSettings;\n }\n if (this.options.buttonSettings) {\n options.buttonSettings = lodash_1.default.clone(this.options.buttonSettings);\n }\n if (this.options.viewAsHtml) {\n options.viewAsHtml = this.options.viewAsHtml;\n }\n if (this.options.language) {\n options.language = this.options.language;\n }\n if (this.options.template) {\n options.template = this.options.template;\n }\n if (this.options.templates) {\n options.templates = this.options.templates;\n }\n if (this.options.renderMode) {\n options.renderMode = this.options.renderMode;\n }\n if (this.options.attachMode) {\n options.attachMode = this.options.attachMode;\n }\n if (this.options.iconset) {\n options.iconset = this.options.iconset;\n }\n if (this.options.fileService) {\n options.fileService = this.options.fileService;\n }\n if (this.options.onChange) {\n options.onChange = this.options.onChange;\n }\n if (this.options.preview) {\n options.preview = this.options.preview;\n }\n if (this.options.inEditGrid) {\n options.inEditGrid = this.options.inEditGrid;\n }\n if (this.options.saveDraft) {\n options.saveDraft = this.options.saveDraft;\n options.formio = new Formio_1.Formio(this.formSrc);\n }\n if (this.options.saveDraftThrottle) {\n options.saveDraftThrottle = this.options.saveDraftThrottle;\n }\n if (this.options.skipDraftRestore) {\n options.skipDraftRestore = this.options.skipDraftRestore;\n }\n return options;\n }\n /* eslint-enable max-statements */\n render() {\n if (this.builderMode) {\n return super.render(this.component.label || 'Nested form');\n }\n const subform = this.subForm ? this.subForm.render() : this.renderTemplate('loading');\n return super.render(subform);\n }\n asString(value) {\n return this.getValueAsString(value);\n }\n /**\n * Prints out the value of form components as a datagrid value.\n */\n getValueAsString(value, options) {\n if (!value) {\n return 'No data provided';\n }\n if (!value.data && value._id) {\n return value._id;\n }\n if (!value.data || !Object.keys(value.data).length) {\n return 'No data provided';\n }\n if (options === null || options === void 0 ? void 0 : options.email) {\n let result = (`\n <table border=\"1\" style=\"width:100%\">\n <tbody>\n `);\n this.everyComponent((component) => {\n if (component.isInputComponent && component.visible && !component.skipInEmail) {\n result += (`\n <tr>\n <th style=\"padding: 5px 10px;\">${component.label}</th>\n <td style=\"width:100%;padding:5px 10px;\">${component.getView(component.dataValue, options)}</td>\n </tr>\n `);\n }\n }, Object.assign(Object.assign({}, options), { fromRoot: true }));\n result += (`\n </tbody>\n </table>\n `);\n return result;\n }\n if (lodash_1.default.isEmpty(value)) {\n return '';\n }\n return '[Complex Data]';\n }\n attach(element) {\n // Don't attach in builder.\n if (this.builderMode) {\n return super.attach(element);\n }\n return super.attach(element)\n .then(() => {\n if (this.isSubFormLazyLoad() && !this.hasLoadedForm && !this.subFormLoading) {\n this.createSubForm(true);\n }\n return this.subFormReady.then(() => {\n this.empty(element);\n if (this.options.builder) {\n this.setContent(element, this.ce('div', {\n class: 'text-muted text-center p-2'\n }, this.text(this.formObj.title)));\n return;\n }\n this.setContent(element, this.render());\n if (this.subForm) {\n if (this.isNestedWizard) {\n element = this.root.element;\n }\n this.subForm.attach(element);\n this.valueChanged = this.hasSetValue;\n if (!this.valueChanged && this.dataValue.state !== 'submitted') {\n this.setDefaultValue();\n }\n else {\n this.restoreValue();\n }\n }\n if (!this.builderMode && this.component.modalEdit) {\n const modalShouldBeOpened = this.componentModal ? this.componentModal.isOpened : false;\n const currentValue = modalShouldBeOpened ? this.componentModal.currentValue : this.dataValue;\n this.componentModal = new ComponentModal_1.default(this, element, modalShouldBeOpened, currentValue, this._referenceAttributeName);\n this.setOpenModalElement();\n }\n this.calculateValue();\n });\n });\n }\n detach() {\n if (this.subForm) {\n this.subForm.detach();\n }\n super.detach();\n }\n get currentForm() {\n return this._currentForm;\n }\n get hasLoadedForm() {\n return this.formObj\n && this.formObj.components\n && Array.isArray(this.formObj.components)\n && this.formObj.components.length;\n }\n set currentForm(instance) {\n this._currentForm = instance;\n if (!this.subForm) {\n return;\n }\n this.subForm.getComponents().forEach(component => {\n component.currentForm = this;\n });\n }\n get isRevisionChanged() {\n return lodash_1.default.isNumber(this.subFormRevision)\n && lodash_1.default.isNumber(this.formObj._vid)\n && this.formObj._vid !== this.subFormRevision;\n }\n destroy(all = false) {\n if (this.subForm) {\n this.subForm.destroy(all);\n this.subForm = null;\n this.subFormReady = null;\n }\n super.destroy(all);\n }\n redraw() {\n if (this.subForm) {\n this.subForm.form = this.formObj;\n this.setSubFormDisabled(this.subForm);\n }\n return super.redraw();\n }\n /**\n * Pass everyComponent to subform.\n * @param args\n * @returns {*|void}\n */\n everyComponent(...args) {\n if (this.subForm) {\n this.subForm.everyComponent(...args);\n }\n }\n setSubFormDisabled(subForm) {\n subForm.disabled = this.disabled; // When the Nested Form is disabled make the subForm disabled\n }\n updateSubWizards(subForm) {\n var _a, _b;\n if (this.isNestedWizard && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.subWizards) && ((_b = subForm === null || subForm === void 0 ? void 0 : subForm._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard') {\n const existedForm = this.root.subWizards.findIndex(form => form.component.form === this.component.form);\n if (existedForm !== -1) {\n this.root.subWizards[existedForm] = this;\n }\n else {\n this.root.subWizards.push(this);\n }\n this.emit('subWizardsUpdated', subForm);\n }\n }\n /**\n * Create a subform instance.\n *\n * @return {*}\n */\n createSubForm(fromAttach) {\n this.subFormReady = this.loadSubForm(fromAttach).then((form) => {\n if (!form) {\n return;\n }\n // Iterate through every component and hide the submit button.\n (0, utils_1.eachComponent)(form.components, (component) => {\n this.hideSubmitButton(component);\n });\n // If the subform is already created then destroy the old one.\n if (this.subForm) {\n this.subForm.destroy();\n }\n // Render the form.\n return (new Form_1.default(form, this.getSubOptions())).ready.then((instance) => {\n this.subForm = instance;\n this.subForm.currentForm = this;\n this.subForm.parent = this;\n this.subForm.parentVisible = this.visible;\n this.subForm.on('change', () => {\n if (this.subForm) {\n this.dataValue = this.subForm.getValue();\n this.triggerChange({\n noEmit: true\n });\n }\n });\n this.subForm.url = this.formSrc;\n this.subForm.nosubmit = true;\n this.subForm.root = this.root;\n this.subForm.localRoot = this.isNestedWizard ? this.localRoot : this.subForm;\n this.restoreValue();\n this.valueChanged = this.hasSetValue;\n this.onChange();\n return this.subForm;\n });\n }).then((subForm) => {\n this.updateSubWizards(subForm);\n return subForm;\n });\n return this.subFormReady;\n }\n hideSubmitButton(component) {\n const isSubmitButton = (component.type === 'button') &&\n ((component.action === 'submit') || !component.action);\n if (isSubmitButton) {\n component.hidden = true;\n }\n }\n /**\n * Load the subform.\n */\n loadSubForm(fromAttach) {\n var _a, _b, _c;\n if (this.builderMode || this.isHidden() || (this.isSubFormLazyLoad() && !fromAttach)) {\n return Promise.resolve();\n }\n if (this.hasLoadedForm && !this.isRevisionChanged &&\n !(this.options.pdf && ((_a = this.component) === null || _a === void 0 ? void 0 : _a.useOriginalRevision) && lodash_1.default.isNull(this.subForm) && !this.subFormLoading)) {\n // Pass config down to sub forms.\n if (this.root && this.root.form && this.root.form.config && !this.formObj.config) {\n this.formObj.config = this.root.form.config;\n }\n return Promise.resolve(this.formObj);\n }\n else if (this.formSrc) {\n this.subFormLoading = true;\n const options = ((_b = this.root.formio) === null || _b === void 0 ? void 0 : _b.base) && ((_c = this.root.formio) === null || _c === void 0 ? void 0 : _c.projectUrl)\n ? {\n base: this.root.formio.base,\n project: this.root.formio.projectUrl,\n }\n : {};\n return (new Formio_1.Formio(this.formSrc, options)).loadForm({ params: { live: 1 } })\n .then((formObj) => {\n this.formObj = formObj;\n if (this.options.pdf && this.component.useOriginalRevision) {\n this.formObj.display = 'form';\n }\n this.subFormLoading = false;\n return formObj;\n })\n .catch((err) => {\n console.log(err);\n return null;\n });\n }\n return Promise.resolve();\n }\n get subFormData() {\n var _a;\n return ((_a = this.dataValue) === null || _a === void 0 ? void 0 : _a.data) || {};\n }\n checkComponentValidity(data, dirty, row, options, errors = []) {\n options = options || {};\n const silentCheck = options.silentCheck || false;\n if (this.subForm) {\n return this.subForm.checkValidity(this.subFormData, dirty, null, silentCheck, errors);\n }\n return super.checkComponentValidity(data, dirty, row, options, errors);\n }\n checkComponentConditions(data, flags, row) {\n const visible = super.checkComponentConditions(data, flags, row);\n // Return if already hidden\n if (!visible) {\n return visible;\n }\n if (this.subForm) {\n return this.subForm.checkConditions(this.subFormData);\n }\n // There are few cases when subForm is not loaded when a change is triggered,\n // so we need to perform checkConditions after it is ready, or some conditional fields might be hidden in View mode\n else if (this.subFormReady) {\n this.subFormReady.then(() => {\n if (this.subForm) {\n return this.subForm.checkConditions(this.subFormData);\n }\n });\n }\n return visible;\n }\n calculateValue(data, flags, row) {\n if (this.subForm) {\n return this.subForm.calculateValue(this.subFormData, flags);\n }\n return super.calculateValue(data, flags, row);\n }\n setPristine(pristine) {\n super.setPristine(pristine);\n if (this.subForm) {\n this.subForm.setPristine(pristine);\n }\n }\n /**\n * Determine if the subform should be submitted.\n * @return {*|boolean}\n */\n get shouldSubmit() {\n return this.subFormReady && (!this.component.hasOwnProperty('reference') || this.component.reference) && !this.isHidden();\n }\n /**\n * Returns the data for the subform.\n *\n * @return {*}\n */\n getSubFormData() {\n if (lodash_1.default.get(this.subForm, 'form.display') === 'pdf') {\n return this.subForm.getSubmission();\n }\n else {\n return Promise.resolve(this.dataValue);\n }\n }\n /**\n * Submit the subform if configured to do so.\n *\n * @return {*}\n */\n submitSubForm() {\n // If we wish to submit the form on next page, then do that here.\n if (this.shouldSubmit) {\n return this.subFormReady.then(() => {\n if (!this.subForm) {\n return this.dataValue;\n }\n this.subForm.nosubmit = false;\n this.subForm.submitted = true;\n return this.subForm.submitForm().then(result => {\n this.subForm.loading = false;\n this.subForm.showAllErrors = false;\n this.dataValue = result.submission;\n return this.dataValue;\n }).catch(err => {\n this.subForm.showAllErrors = true;\n this.subForm.onSubmissionError(err);\n return Promise.reject(err);\n });\n });\n }\n return this.getSubFormData();\n }\n /**\n * Submit the form before the next page is triggered.\n */\n beforePage(next) {\n // Should not submit child forms if we are going to the previous page\n if (!next) {\n return super.beforePage(next);\n }\n return this.submitSubForm(true).then(() => super.beforePage(next));\n }\n /**\n * Submit the form before the whole form is triggered.\n */\n beforeSubmit() {\n var _a, _b, _c;\n const submission = this.dataValue;\n // Cancel triggered saveDraft\n if (((_a = this.subForm) === null || _a === void 0 ? void 0 : _a.draftEnabled) && ((_b = this.subForm.triggerSaveDraft) === null || _b === void 0 ? void 0 : _b.cancel)) {\n this.subForm.triggerSaveDraft.cancel();\n }\n const isAlreadySubmitted = submission && submission._id && submission.form;\n const isDraftSubmission = this.options.saveDraft && submission.state === 'draft';\n // This submission has already been submitted, so just return the reference data.\n if (isAlreadySubmitted && !((_c = this.subForm) === null || _c === void 0 ? void 0 : _c.wizard) && !isDraftSubmission) {\n this.dataValue = submission;\n return Promise.resolve(this.dataValue);\n }\n return this.submitSubForm(false)\n .then(() => {\n return this.dataValue;\n })\n .then(() => super.beforeSubmit());\n }\n isSubFormLazyLoad() {\n var _a, _b;\n return ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard' && this.component.lazyLoad;\n }\n isHidden() {\n if (!this.visible) {\n return true;\n }\n return !super.checkConditions(this.rootValue);\n }\n setValue(submission, flags = {}) {\n var _a;\n const changed = super.setValue(submission, flags);\n this.valueChanged = true;\n if (this.subForm) {\n const revisionPath = submission._frid ? '_frid' : '_vid';\n const shouldLoadOriginalRevision = this.useOriginalRevision\n && (lodash_1.default.isNumber(submission[revisionPath]) || lodash_1.default.isNumber(submission._fvid))\n && lodash_1.default.isNumber((_a = this.subForm.form) === null || _a === void 0 ? void 0 : _a[revisionPath])\n && submission._fvid !== this.subForm.form[revisionPath];\n if (shouldLoadOriginalRevision) {\n this.setFormRevision(submission._frid || submission._fvid);\n this.createSubForm().then(() => {\n this.attach(this.element);\n });\n }\n else {\n this.setSubFormValue(submission, flags);\n }\n }\n return changed;\n }\n setSubFormValue(submission, flags) {\n var _a, _b;\n const shouldLoadSubmissionById = submission\n && submission._id\n && this.subForm.formio\n && lodash_1.default.isEmpty(submission.data);\n if (shouldLoadSubmissionById) {\n const formId = submission.form || this.formObj.form || this.component.form;\n const submissionUrl = `${this.subForm.formio.formsUrl}/${formId}/submission/${submission._id}`;\n const options = ((_a = this.root.formio) === null || _a === void 0 ? void 0 : _a.base) && ((_b = this.root.formio) === null || _b === void 0 ? void 0 : _b.projectUrl)\n ? {\n base: this.root.formio.base,\n project: this.root.formio.projectUrl,\n }\n : {};\n this.subForm.setUrl(submissionUrl, Object.assign(Object.assign({}, this.options), options));\n this.subForm.loadSubmission().catch((err) => {\n console.error(`Unable to load subform submission ${submission._id}:`, err);\n });\n }\n else {\n this.subForm.setValue(submission, flags);\n }\n }\n isEmpty(value = this.dataValue) {\n return value === null || lodash_1.default.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value === null || value === void 0 ? void 0 : value.data) && !(value === null || value === void 0 ? void 0 : value._id));\n }\n areAllComponentsEmpty(data) {\n let res = true;\n if (this.subForm) {\n this.subForm.everyComponent((comp) => {\n const componentValue = lodash_1.default.get(data, comp.key);\n res &= comp.isEmpty(componentValue);\n });\n }\n else {\n res = false;\n }\n return res;\n }\n getValue() {\n if (this.subForm) {\n return this.subForm.getValue();\n }\n return this.dataValue;\n }\n get errors() {\n let errors = super.errors;\n if (this.subForm) {\n errors = errors.concat(this.subForm.errors);\n }\n return errors;\n }\n updateSubFormVisibility() {\n if (this.subForm) {\n this.subForm.parentVisible = this.visible;\n }\n }\n /**\n * Determines if this form is a Nested Wizard\n * which means it should be a Wizard itself and should be a direct child of a Wizard's page\n * @returns {boolean}\n */\n get isNestedWizard() {\n var _a, _b, _c, _d, _e;\n return ((_b = (_a = this.subForm) === null || _a === void 0 ? void 0 : _a._form) === null || _b === void 0 ? void 0 : _b.display) === 'wizard' && ((_e = (_d = (_c = this.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d._form) === null || _e === void 0 ? void 0 : _e.display) === 'wizard';\n }\n get visible() {\n return super.visible;\n }\n set visible(value) {\n const isNestedWizard = this.isNestedWizard;\n if (this._visible !== value) {\n this._visible = value;\n // Form doesn't load if hidden. If it becomes visible, create the form.\n if (!this.subForm && value) {\n this.createSubForm();\n this.subFormReady.then(() => {\n this.updateSubFormVisibility();\n this.clearOnHide();\n });\n this.redraw();\n return;\n }\n this.updateSubFormVisibility();\n this.clearOnHide();\n isNestedWizard ? this.rebuild() : this.redraw();\n }\n if (!value && isNestedWizard) {\n this.root.redraw();\n }\n }\n get parentVisible() {\n return super.parentVisible;\n }\n set parentVisible(value) {\n if (this._parentVisible !== value) {\n this._parentVisible = value;\n this.clearOnHide();\n // Form doesn't load if hidden. If it becomes visible, create the form.\n if (!this.subForm && value) {\n this.createSubForm();\n this.subFormReady.then(() => {\n this.updateSubFormVisibility();\n });\n this.redraw();\n return;\n }\n this.updateSubFormVisibility();\n this.redraw();\n }\n }\n isInternalEvent(event) {\n switch (event) {\n case 'focus':\n case 'blur':\n case 'componentChange':\n case 'componentError':\n case 'error':\n case 'formLoad':\n case 'languageChanged':\n case 'render':\n case 'checkValidity':\n case 'initialized':\n case 'submit':\n case 'submitButton':\n case 'nosubmit':\n case 'updateComponent':\n case 'submitDone':\n case 'submissionDeleted':\n case 'requestDone':\n case 'nextPage':\n case 'prevPage':\n case 'wizardNavigationClicked':\n case 'updateWizardNav':\n case 'restoreDraft':\n case 'saveDraft':\n case 'saveComponent':\n case 'pdfUploaded':\n return true;\n default:\n return false;\n }\n }\n createEmitter() {\n const emitter = new eventemitter3_1.default();\n const nativeEmit = emitter.emit;\n const that = this;\n emitter.emit = function (event, ...args) {\n const eventType = event.replace(`${that.options.namespace}.`, '');\n nativeEmit.call(this, event, ...args);\n if (!that.isInternalEvent(eventType)) {\n that.emit(eventType, ...args);\n }\n };\n return emitter;\n }\n deleteValue() {\n super.setValue(null, {\n noUpdateEvent: true,\n noDefault: true\n });\n this.unset();\n }\n}\nexports[\"default\"] = FormComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/form/Form.js?");
6723
6733
 
6724
6734
  /***/ }),
6725
6735
 
@@ -7060,7 +7070,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
7060
7070
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7061
7071
 
7062
7072
  "use strict";
7063
- 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 ListComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/list/ListComponent */ \"./lib/cjs/components/_classes/list/ListComponent.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass RadioComponent extends ListComponent_1.default {\n static schema(...extend) {\n return ListComponent_1.default.schema({\n type: 'radio',\n inputType: 'radio',\n label: 'Radio',\n key: 'radio',\n values: [{ label: '', value: '' }],\n data: {\n url: '',\n },\n fieldSet: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Radio',\n group: 'basic',\n icon: 'dot-circle-o',\n weight: 80,\n documentation: '/userguide/form-building/form-components#radio',\n schema: RadioComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: classComp.dataType || '',\n data: {\n custom() {\n return classComp.values;\n }\n },\n };\n } });\n }\n static get serverConditionSettings() {\n return Object.assign(Object.assign({}, super.serverConditionSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: classComp.dataType || '',\n data: {\n custom: `values = ${classComp && classComp.values ? JSON.stringify(classComp.values) : []}`,\n },\n };\n } });\n }\n static savedValueTypes(schema) {\n const { boolean, string, number, object, array } = utils_1.componentValueTypes;\n const { dataType } = schema;\n const types = (0, utils_1.getComponentSavedTypes)(schema);\n if (types) {\n return types;\n }\n if (dataType === 'object') {\n return [object, array];\n }\n if (utils_1.componentValueTypes[dataType]) {\n return [utils_1.componentValueTypes[dataType]];\n }\n return [boolean, string, number, object, array];\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.previousValue = this.dataValue || null;\n }\n get defaultSchema() {\n return RadioComponent.schema();\n }\n get defaultValue() {\n let defaultValue = super.defaultValue;\n if (!defaultValue && this.component.defaultValue === false) {\n defaultValue = this.component.defaultValue;\n }\n return defaultValue;\n }\n get inputInfo() {\n var _a;\n const info = super.elementInfo();\n info.type = 'input';\n info.changeEvent = 'click';\n info.attr.class = 'form-check-input';\n info.attr.name = info.attr.name += `[${(_a = this.root) === null || _a === void 0 ? void 0 : _a.id}-${this.id}]`;\n return info;\n }\n get emptyValue() {\n return '';\n }\n get isRadio() {\n return this.component.inputType === 'radio';\n }\n get optionSelectedClass() {\n return 'radio-selected';\n }\n get listData() {\n const listData = lodash_1.default.get(this.root, 'submission.metadata.listData', {});\n return lodash_1.default.get(listData, this.path);\n }\n init() {\n super.init();\n this.templateData = {};\n // Trigger an update.//\n let updateArgs = [];\n const triggerUpdate = lodash_1.default.debounce((...args) => {\n updateArgs = [];\n return this.updateItems.apply(this, args);\n }, 100);\n this.triggerUpdate = (...args) => {\n // Make sure we always resolve the previous promise before reassign it\n if (typeof this.itemsLoadedResolve === 'function') {\n this.itemsLoadedResolve();\n }\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n if (args.length) {\n updateArgs = args;\n }\n return triggerUpdate(...updateArgs);\n };\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n this.optionsLoaded = false;\n this.loadedOptions = [];\n // Get the template keys for this radio component.\n this.getTemplateKeys();\n }\n render() {\n return super.render(this.renderTemplate('radio', {\n input: this.inputInfo,\n inline: this.component.inline,\n values: this.component.dataSrc === 'values' ? this.component.values : this.loadedOptions,\n value: this.dataValue,\n row: this.row,\n }));\n }\n attach(element) {\n this.loadRefs(element, { input: 'multiple', wrapper: 'multiple' });\n this.refs.input.forEach((input, index) => {\n this.addEventListener(input, this.inputInfo.changeEvent, () => {\n this.updateValue(null, {\n modified: true,\n });\n });\n if (this.component.values[index]) {\n this.addShortcut(input, this.component.values[index].shortcut);\n }\n if (this.isRadio) {\n let dataValue = this.dataValue;\n if (!lodash_1.default.isString(this.dataValue)) {\n dataValue = lodash_1.default.toString(this.dataValue);\n }\n if (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) {\n const optionValue = this.component.dataType === 'string' ? JSON.stringify(this.loadedOptions[index].value) : this.loadedOptions[index].value;\n input.checked = lodash_1.default.isEqual(optionValue, this.dataValue);\n }\n else {\n input.checked = (dataValue === input.value && (input.value || this.component.dataSrc !== 'url'));\n }\n this.addEventListener(input, 'keyup', (event) => {\n if (event.key === ' ' && dataValue === input.value) {\n event.preventDefault();\n this.updateValue(null, {\n modified: true,\n });\n }\n });\n }\n });\n this.triggerUpdate();\n this.setSelectedClasses();\n return super.attach(element);\n }\n detach(element) {\n if (element && this.refs.input) {\n this.refs.input.forEach((input, index) => {\n if (this.component.values[index]) {\n this.removeShortcut(input, this.component.values[index].shortcut);\n }\n });\n }\n super.detach();\n }\n getValue() {\n if (this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n let value = this.dataValue;\n this.refs.input.forEach((input, index) => {\n if (input.checked) {\n value = (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) ?\n this.loadedOptions[index].value :\n input.value;\n }\n });\n return value;\n }\n validateValueProperty() {\n if (this.component.dataSrc === 'values') {\n return true;\n }\n return !lodash_1.default.some(this.refs.wrapper, (wrapper, index) => this.refs.input[index].checked && this.loadedOptions[index].invalid);\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.component.values;\n if (values) {\n return values.findIndex(({ value: optionValue }) => this.normalizeValue(optionValue) === value) !== -1;\n }\n return false;\n }\n getValueAsString(value) {\n if (lodash_1.default.isObject(value)) {\n value = JSON.stringify(value);\n }\n else if (!lodash_1.default.isString(value)) {\n value = lodash_1.default.toString(value);\n }\n if (this.component.dataSrc !== 'values') {\n return value;\n }\n const option = lodash_1.default.find(this.component.values, (v) => v.value === value);\n if (!value) {\n return lodash_1.default.get(option, 'label', '');\n }\n return lodash_1.default.get(option, 'label', '');\n }\n setValueAt(index, value) {\n if (this.refs.input && this.refs.input[index] && value !== null && value !== undefined) {\n const inputValue = this.refs.input[index].value;\n this.refs.input[index].checked = (inputValue === value.toString());\n }\n }\n loadItems(url, search, headers, options, method, body) {\n if (this.optionsLoaded) {\n return;\n }\n if (!this.shouldLoad && this.listData) {\n this.loadItemsFromMetadata();\n return;\n }\n // Ensure we have a method and remove any body if method is get\n method = method || 'GET';\n if (method.toUpperCase() === 'GET') {\n body = null;\n }\n // Set ignoreCache if it is\n options.ignoreCache = this.component.ignoreCache;\n // Make the request.\n options.header = headers;\n this.loading = true;\n Formio_1.Formio.makeRequest(this.options.formio, 'select', url, method, body, options)\n .then((response) => {\n this.loading = false;\n this.setItems(response);\n this.optionsLoaded = true;\n this.redraw();\n })\n .catch((err) => {\n this.handleLoadingError(err);\n });\n }\n loadItemsFromMetadata() {\n this.listData.forEach((item, i) => {\n this.loadedOptions[i] = {\n label: this.itemTemplate(item)\n };\n if (lodash_1.default.isEqual(item, this.selectData || lodash_1.default.pick(this.dataValue, lodash_1.default.keys(item)))) {\n this.loadedOptions[i].value = this.dataValue;\n }\n });\n this.optionsLoaded = true;\n this.redraw();\n }\n setItems(items) {\n const listData = [];\n items === null || items === void 0 ? void 0 : items.forEach((item, i) => {\n this.loadedOptions[i] = {\n value: this.component.valueProperty ? item[this.component.valueProperty] : item,\n label: this.component.valueProperty ? this.itemTemplate(item, item[this.component.valueProperty]) : this.itemTemplate(item, item, i)\n };\n listData.push(this.templateData[this.component.valueProperty ? item[this.component.valueProperty] : i]);\n if ((this.component.valueProperty || !this.isRadio) && (lodash_1.default.isUndefined(item[this.component.valueProperty]) ||\n (!this.isRadio && lodash_1.default.isObject(item[this.component.valueProperty])) ||\n (!this.isRadio && lodash_1.default.isBoolean(item[this.component.valueProperty])))) {\n this.loadedOptions[i].invalid = true;\n }\n });\n if (this.isSelectURL) {\n const submission = this.root.submission;\n if (!submission.metadata) {\n submission.metadata = {};\n }\n if (!submission.metadata.listData) {\n submission.metadata.listData = {};\n }\n lodash_1.default.set(submission.metadata.listData, this.path, listData);\n }\n }\n setSelectedClasses() {\n if (this.refs.wrapper) {\n //add/remove selected option class\n const value = this.dataValue;\n this.refs.wrapper.forEach((wrapper, index) => {\n const input = this.refs.input[index];\n const checked = (input.type === 'checkbox') ? value[input.value] : (input.value.toString() === value.toString());\n if (checked) {\n //add class to container when selected\n this.addClass(wrapper, this.optionSelectedClass);\n //change \"checked\" attribute\n input.setAttribute('checked', 'true');\n }\n else {\n this.removeClass(wrapper, this.optionSelectedClass);\n input.removeAttribute('checked');\n }\n });\n }\n }\n updateValue(value, flags) {\n const changed = super.updateValue(value, flags);\n if (changed) {\n this.setSelectedClasses();\n }\n if (!flags || !flags.modified || !this.isRadio) {\n if (changed) {\n this.previousValue = this.dataValue;\n }\n return changed;\n }\n // If they clicked on the radio that is currently selected, it needs to reset the value.\n this.currentValue = this.dataValue;\n const shouldResetValue = flags && flags.modified && !flags.noUpdateEvent && this.previousValue === this.currentValue;\n if (shouldResetValue) {\n this.resetValue();\n this.triggerChange(flags);\n this.setSelectedClasses();\n }\n this.previousValue = this.dataValue;\n return changed;\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n const dataType = this.component.dataType || 'auto';\n if (value === this.emptyValue) {\n return value;\n }\n switch (dataType) {\n case 'auto':\n if (!isNaN(parseFloat(value)) && isFinite(value) && lodash_1.default.toString(value) === Number(value).toString()) {\n value = +value;\n }\n if (value === 'true') {\n value = true;\n }\n if (value === 'false') {\n value = false;\n }\n break;\n case 'number':\n value = +value;\n break;\n case 'string':\n if (typeof value === 'object') {\n value = JSON.stringify(value);\n }\n else {\n value = String(value);\n }\n break;\n case 'boolean':\n value = !(!value || value.toString() === 'false');\n break;\n }\n if (this.isSelectURL && this.templateData && this.templateData[value]) {\n const submission = this.root.submission;\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n lodash_1.default.set(submission.metadata.selectData, this.path, this.templateData[value]);\n }\n return super.normalizeValue(value);\n }\n}\nexports[\"default\"] = RadioComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/radio/Radio.js?");
7073
+ 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 ListComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/list/ListComponent */ \"./lib/cjs/components/_classes/list/ListComponent.js\"));\nconst Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nclass RadioComponent extends ListComponent_1.default {\n static schema(...extend) {\n return ListComponent_1.default.schema({\n type: 'radio',\n inputType: 'radio',\n label: 'Radio',\n key: 'radio',\n values: [{ label: '', value: '' }],\n data: {\n url: '',\n },\n fieldSet: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Radio',\n group: 'basic',\n icon: 'dot-circle-o',\n weight: 80,\n documentation: '/userguide/form-building/form-components#radio',\n schema: RadioComponent.schema()\n };\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: classComp.dataType || '',\n data: {\n custom() {\n return classComp.values;\n }\n },\n };\n } });\n }\n static get serverConditionSettings() {\n return Object.assign(Object.assign({}, super.serverConditionSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: classComp.dataType || '',\n data: {\n custom: `values = ${classComp && classComp.values ? JSON.stringify(classComp.values) : []}`,\n },\n };\n } });\n }\n static savedValueTypes(schema) {\n const { boolean, string, number, object, array } = utils_1.componentValueTypes;\n const { dataType } = schema;\n const types = (0, utils_1.getComponentSavedTypes)(schema);\n if (types) {\n return types;\n }\n if (dataType === 'object') {\n return [object, array];\n }\n if (utils_1.componentValueTypes[dataType]) {\n return [utils_1.componentValueTypes[dataType]];\n }\n return [boolean, string, number, object, array];\n }\n constructor(component, options, data) {\n super(component, options, data);\n this.previousValue = this.dataValue || null;\n }\n get defaultSchema() {\n return RadioComponent.schema();\n }\n get defaultValue() {\n let defaultValue = super.defaultValue;\n if (!defaultValue && this.component.defaultValue === false) {\n defaultValue = this.component.defaultValue;\n }\n return defaultValue;\n }\n get inputInfo() {\n var _a;\n const info = super.elementInfo();\n info.type = 'input';\n info.changeEvent = 'click';\n info.attr.class = 'form-check-input';\n info.attr.name = info.attr.name += `[${(_a = this.root) === null || _a === void 0 ? void 0 : _a.id}-${this.id}]`;\n return info;\n }\n get emptyValue() {\n return '';\n }\n get isRadio() {\n return this.component.inputType === 'radio';\n }\n get optionSelectedClass() {\n return 'radio-selected';\n }\n get listData() {\n const listData = lodash_1.default.get(this.root, 'submission.metadata.listData', {});\n return lodash_1.default.get(listData, this.path);\n }\n init() {\n super.init();\n this.templateData = {};\n // Trigger an update.//\n let updateArgs = [];\n const triggerUpdate = lodash_1.default.debounce((...args) => {\n updateArgs = [];\n return this.updateItems.apply(this, args);\n }, 100);\n this.triggerUpdate = (...args) => {\n // Make sure we always resolve the previous promise before reassign it\n if (typeof this.itemsLoadedResolve === 'function') {\n this.itemsLoadedResolve();\n }\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n if (args.length) {\n updateArgs = args;\n }\n return triggerUpdate(...updateArgs);\n };\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n this.optionsLoaded = false;\n this.loadedOptions = [];\n // Get the template keys for this radio component.\n this.getTemplateKeys();\n }\n render() {\n return super.render(this.renderTemplate('radio', {\n input: this.inputInfo,\n inline: this.component.inline,\n values: this.component.dataSrc === 'values' ? this.component.values : this.loadedOptions,\n value: this.dataValue,\n row: this.row,\n }));\n }\n attach(element) {\n this.loadRefs(element, { input: 'multiple', wrapper: 'multiple' });\n this.refs.input.forEach((input, index) => {\n this.addEventListener(input, this.inputInfo.changeEvent, () => {\n this.updateValue(null, {\n modified: true,\n });\n });\n if (this.component.values[index]) {\n this.addShortcut(input, this.component.values[index].shortcut);\n }\n if (this.isRadio) {\n let dataValue = this.dataValue;\n if (!lodash_1.default.isString(this.dataValue)) {\n dataValue = lodash_1.default.toString(this.dataValue);\n }\n if (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) {\n const optionValue = this.component.dataType === 'string' ? JSON.stringify(this.loadedOptions[index].value) : this.loadedOptions[index].value;\n input.checked = lodash_1.default.isEqual(optionValue, this.dataValue);\n }\n else {\n input.checked = (dataValue === input.value && (input.value || this.component.dataSrc !== 'url'));\n }\n this.addEventListener(input, 'keyup', (event) => {\n if (event.key === ' ' && dataValue === input.value) {\n event.preventDefault();\n this.updateValue(null, {\n modified: true,\n });\n }\n });\n }\n });\n this.triggerUpdate();\n this.setSelectedClasses();\n return super.attach(element);\n }\n detach(element) {\n if (element && this.refs.input) {\n this.refs.input.forEach((input, index) => {\n if (this.component.values[index]) {\n this.removeShortcut(input, this.component.values[index].shortcut);\n }\n });\n }\n super.detach();\n }\n getValue() {\n if (this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n let value = this.dataValue;\n this.refs.input.forEach((input, index) => {\n if (input.checked) {\n value = (this.isSelectURL && lodash_1.default.isObject(this.loadedOptions[index].value)) ?\n this.loadedOptions[index].value :\n input.value;\n }\n });\n return value;\n }\n validateValueProperty() {\n if (this.component.dataSrc === 'values') {\n return true;\n }\n return !lodash_1.default.some(this.refs.wrapper, (wrapper, index) => this.refs.input[index].checked && this.loadedOptions[index].invalid);\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.component.values;\n if (values) {\n return values.findIndex(({ value: optionValue }) => this.normalizeValue(optionValue) === value) !== -1;\n }\n return false;\n }\n getValueAsString(value, options = {}) {\n if (lodash_1.default.isObject(value)) {\n value = JSON.stringify(value);\n }\n else if (!lodash_1.default.isString(value)) {\n value = lodash_1.default.toString(value);\n }\n const isModalPreviewWithUrlDataSource = options.modalPreview && this.component.dataSrc === 'url';\n if (this.component.dataSrc !== 'values' && !isModalPreviewWithUrlDataSource) {\n return value;\n }\n const values = isModalPreviewWithUrlDataSource ? this.loadedOptions : this.component.values;\n const option = lodash_1.default.find(values, (v) => v.value === value);\n if (!value) {\n return lodash_1.default.get(option, 'label', '');\n }\n return lodash_1.default.get(option, 'label', '');\n }\n setValueAt(index, value) {\n if (this.refs.input && this.refs.input[index] && value !== null && value !== undefined) {\n const inputValue = this.refs.input[index].value;\n this.refs.input[index].checked = (inputValue === value.toString());\n }\n }\n loadItems(url, search, headers, options, method, body) {\n if (this.optionsLoaded) {\n return;\n }\n if (!this.shouldLoad && this.listData) {\n this.loadItemsFromMetadata();\n return;\n }\n // Ensure we have a method and remove any body if method is get\n method = method || 'GET';\n if (method.toUpperCase() === 'GET') {\n body = null;\n }\n // Set ignoreCache if it is\n options.ignoreCache = this.component.ignoreCache;\n // Make the request.\n options.header = headers;\n this.loading = true;\n Formio_1.Formio.makeRequest(this.options.formio, 'select', url, method, body, options)\n .then((response) => {\n this.loading = false;\n this.setItems(response);\n this.optionsLoaded = true;\n this.redraw();\n })\n .catch((err) => {\n this.handleLoadingError(err);\n });\n }\n loadItemsFromMetadata() {\n this.listData.forEach((item, i) => {\n this.loadedOptions[i] = {\n label: this.itemTemplate(item)\n };\n if (lodash_1.default.isEqual(item, this.selectData || lodash_1.default.pick(this.dataValue, lodash_1.default.keys(item)))) {\n this.loadedOptions[i].value = this.dataValue;\n }\n });\n this.optionsLoaded = true;\n this.redraw();\n }\n setItems(items) {\n const listData = [];\n items === null || items === void 0 ? void 0 : items.forEach((item, i) => {\n this.loadedOptions[i] = {\n value: this.component.valueProperty ? item[this.component.valueProperty] : item,\n label: this.component.valueProperty ? this.itemTemplate(item, item[this.component.valueProperty]) : this.itemTemplate(item, item, i)\n };\n listData.push(this.templateData[this.component.valueProperty ? item[this.component.valueProperty] : i]);\n if ((this.component.valueProperty || !this.isRadio) && (lodash_1.default.isUndefined(item[this.component.valueProperty]) ||\n (!this.isRadio && lodash_1.default.isObject(item[this.component.valueProperty])) ||\n (!this.isRadio && lodash_1.default.isBoolean(item[this.component.valueProperty])))) {\n this.loadedOptions[i].invalid = true;\n }\n });\n if (this.isSelectURL) {\n const submission = this.root.submission;\n if (!submission.metadata) {\n submission.metadata = {};\n }\n if (!submission.metadata.listData) {\n submission.metadata.listData = {};\n }\n lodash_1.default.set(submission.metadata.listData, this.path, listData);\n }\n }\n setSelectedClasses() {\n if (this.refs.wrapper) {\n //add/remove selected option class\n const value = this.dataValue;\n this.refs.wrapper.forEach((wrapper, index) => {\n const input = this.refs.input[index];\n const checked = (input.type === 'checkbox') ? value[input.value] : (input.value.toString() === value.toString());\n if (checked) {\n //add class to container when selected\n this.addClass(wrapper, this.optionSelectedClass);\n //change \"checked\" attribute\n input.setAttribute('checked', 'true');\n }\n else {\n this.removeClass(wrapper, this.optionSelectedClass);\n input.removeAttribute('checked');\n }\n });\n }\n }\n updateValue(value, flags) {\n const changed = super.updateValue(value, flags);\n if (changed) {\n this.setSelectedClasses();\n }\n if (!flags || !flags.modified || !this.isRadio) {\n if (changed) {\n this.previousValue = this.dataValue;\n }\n return changed;\n }\n // If they clicked on the radio that is currently selected, it needs to reset the value.\n this.currentValue = this.dataValue;\n const shouldResetValue = flags && flags.modified && !flags.noUpdateEvent && this.previousValue === this.currentValue;\n if (shouldResetValue) {\n this.resetValue();\n this.triggerChange(flags);\n this.setSelectedClasses();\n }\n this.previousValue = this.dataValue;\n return changed;\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n const dataType = this.component.dataType || 'auto';\n if (value === this.emptyValue) {\n return value;\n }\n switch (dataType) {\n case 'auto':\n if (!isNaN(parseFloat(value)) && isFinite(value) && lodash_1.default.toString(value) === Number(value).toString()) {\n value = +value;\n }\n if (value === 'true') {\n value = true;\n }\n if (value === 'false') {\n value = false;\n }\n break;\n case 'number':\n value = +value;\n break;\n case 'string':\n if (typeof value === 'object') {\n value = JSON.stringify(value);\n }\n else {\n value = String(value);\n }\n break;\n case 'boolean':\n value = !(!value || value.toString() === 'false');\n break;\n }\n if (this.isSelectURL && this.templateData && this.templateData[value]) {\n const submission = this.root.submission;\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n lodash_1.default.set(submission.metadata.selectData, this.path, this.templateData[value]);\n }\n return super.normalizeValue(value);\n }\n}\nexports[\"default\"] = RadioComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/radio/Radio.js?");
7064
7074
 
7065
7075
  /***/ }),
7066
7076
 
@@ -7126,7 +7136,7 @@ eval("\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _argument
7126
7136
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7127
7137
 
7128
7138
  "use strict";
7129
- eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nexports[\"default\"] = [\n {\n key: 'eventType',\n label: 'Type of event',\n tooltip: 'Specify type of event that this reCAPTCHA would react to',\n type: 'radio',\n values: [\n {\n label: 'Form Load',\n value: 'formLoad'\n },\n {\n label: 'Button Click',\n value: 'buttonClick'\n }\n ],\n weight: 650\n },\n {\n type: 'select',\n input: true,\n label: 'Button Key',\n key: 'buttonKey',\n dataSrc: 'custom',\n valueProperty: 'value',\n tooltip: 'Specify key of button on this form that this reCAPTCHA should react to',\n weight: 660,\n customConditional(context) {\n return context.data.eventType === 'buttonClick';\n },\n data: {\n custom(context) {\n return (0, utils_1.getContextButtons)(context);\n }\n }\n },\n {\n key: 'label',\n ignore: true\n },\n {\n key: 'hideLabel',\n ignore: true\n },\n {\n key: 'labelPosition',\n ignore: true\n },\n {\n key: 'placeholder',\n ignore: true\n },\n {\n key: 'description',\n ignore: true\n },\n {\n key: 'tooltip',\n ignore: true\n },\n {\n key: 'errorLabel',\n ignore: true\n },\n {\n key: 'customClass',\n ignore: true\n },\n {\n key: 'tabindex',\n ignore: true\n },\n {\n key: 'multiple',\n ignore: true\n },\n {\n key: 'clearOnHide',\n ignore: true\n },\n {\n key: 'hidden',\n ignore: true\n },\n {\n key: 'mask',\n ignore: true\n },\n {\n key: 'dataGridLabel',\n ignore: true\n },\n {\n key: 'disabled',\n ignore: true\n },\n {\n key: 'autofocus',\n ignore: true\n },\n {\n key: 'tableView',\n ignore: true\n },\n];\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.js?");
7139
+ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __webpack_require__(/*! ../../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nexports[\"default\"] = [\n {\n key: 'eventType',\n label: 'Type of event',\n tooltip: 'Specify type of event that this reCAPTCHA would react to',\n type: 'radio',\n values: [\n {\n label: 'Form Load',\n value: 'formLoad'\n },\n {\n label: 'Button Click',\n value: 'buttonClick'\n }\n ],\n validate: {\n required: true\n },\n weight: 650\n },\n {\n type: 'select',\n input: true,\n label: 'Button Key',\n key: 'buttonKey',\n dataSrc: 'custom',\n valueProperty: 'value',\n tooltip: 'Specify key of button on this form that this reCAPTCHA should react to',\n weight: 660,\n customConditional(context) {\n return context.data.eventType === 'buttonClick';\n },\n data: {\n custom(context) {\n return (0, utils_1.getContextButtons)(context);\n }\n }\n },\n {\n key: 'label',\n ignore: true\n },\n {\n key: 'hideLabel',\n ignore: true\n },\n {\n key: 'labelPosition',\n ignore: true\n },\n {\n key: 'placeholder',\n ignore: true\n },\n {\n key: 'description',\n ignore: true\n },\n {\n key: 'tooltip',\n ignore: true\n },\n {\n key: 'errorLabel',\n ignore: true\n },\n {\n key: 'customClass',\n ignore: true\n },\n {\n key: 'tabindex',\n ignore: true\n },\n {\n key: 'multiple',\n ignore: true\n },\n {\n key: 'clearOnHide',\n ignore: true\n },\n {\n key: 'hidden',\n ignore: true\n },\n {\n key: 'mask',\n ignore: true\n },\n {\n key: 'dataGridLabel',\n ignore: true\n },\n {\n key: 'disabled',\n ignore: true\n },\n {\n key: 'autofocus',\n ignore: true\n },\n {\n key: 'tableView',\n ignore: true\n },\n];\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/recaptcha/editForm/ReCaptcha.edit.display.js?");
7130
7140
 
7131
7141
  /***/ }),
7132
7142
 
@@ -7148,7 +7158,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
7148
7158
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7149
7159
 
7150
7160
  "use strict";
7151
- 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 Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst ListComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/list/ListComponent */ \"./lib/cjs/components/_classes/list/ListComponent.js\"));\nconst Input_1 = __importDefault(__webpack_require__(/*! ../_classes/input/Input */ \"./lib/cjs/components/_classes/input/Input.js\"));\nconst Form_1 = __importDefault(__webpack_require__(/*! ../../Form */ \"./lib/cjs/Form.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst ChoicesWrapper_1 = __importDefault(__webpack_require__(/*! ../../utils/ChoicesWrapper */ \"./lib/cjs/utils/ChoicesWrapper.js\"));\nclass SelectComponent extends ListComponent_1.default {\n static schema(...extend) {\n return ListComponent_1.default.schema({\n type: 'select',\n label: 'Select',\n key: 'select',\n idPath: 'id',\n data: {\n values: [{ label: '', value: '' }],\n json: '',\n url: '',\n resource: '',\n custom: ''\n },\n clearOnRefresh: false,\n limit: 100,\n valueProperty: '',\n lazyLoad: true,\n filter: '',\n searchEnabled: true,\n searchDebounce: 0.3,\n searchField: '',\n minSearch: 0,\n readOnlyValue: false,\n selectFields: '',\n selectThreshold: 0.3,\n uniqueOptions: false,\n tableView: true,\n fuseOptions: {\n include: 'score',\n threshold: 0.3,\n },\n indexeddb: {\n filter: {}\n },\n customOptions: {},\n useExactSearch: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Select',\n group: 'basic',\n icon: 'th-list',\n weight: 70,\n documentation: '/userguide/form-building/form-components#select',\n schema: SelectComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return SelectComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n const valueComp = Object.assign(Object.assign({}, classComp), { type: 'select' });\n if ((0, utils_1.isSelectResourceWithObjectValue)(classComp)) {\n valueComp.reference = false;\n valueComp.onSetItems = `\n var templateKeys = utils.getItemTemplateKeys(component.template) || [];\n items = _.map(items || [], i => {\n var item = {};\n _.each(templateKeys, k => _.set(item, k, _.get(i, k)));\n return item;\n })\n `;\n }\n return valueComp;\n } });\n }\n static savedValueTypes(schema) {\n const { boolean, string, number, object, array } = utils_1.componentValueTypes;\n const { dataType, reference } = schema;\n const types = (0, utils_1.getComponentSavedTypes)(schema);\n if (types) {\n return types;\n }\n if (reference) {\n return [object];\n }\n if (dataType === 'object') {\n return [object, array];\n }\n if (utils_1.componentValueTypes[dataType]) {\n return [utils_1.componentValueTypes[dataType]];\n }\n return [boolean, string, number, object, array];\n }\n init() {\n super.init();\n this.templateData = {};\n // Trigger an update.\n let updateArgs = [];\n const triggerUpdate = lodash_1.default.debounce((...args) => {\n updateArgs = [];\n return this.updateItems.apply(this, args);\n }, 100);\n this.triggerUpdate = (...args) => {\n // Make sure we always resolve the previous promise before reassign it\n if (typeof this.itemsLoadedResolve === 'function') {\n this.itemsLoadedResolve();\n }\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n if (args.length) {\n updateArgs = args;\n }\n return triggerUpdate(...updateArgs);\n };\n // Keep track of the select options.\n this.selectOptions = [];\n if (this.itemsFromUrl) {\n this.isFromSearch = false;\n this.searchServerCount = null;\n this.defaultServerCount = null;\n this.isScrollLoading = false;\n this.searchDownloadedResources = [];\n this.defaultDownloadedResources = [];\n }\n // If this component has been activated.//\n this.activated = false;\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n this.shouldPositionDropdown = this.hasDataGridAncestor();\n if (this.isHtmlRenderMode()) {\n this.activate();\n }\n // Get the template keys for this select component.\n this.getTemplateKeys();\n }\n get dataReady() {\n // If the root submission has been set, and we are still not attached, then assume\n // that our data is ready.\n if (this.root &&\n this.root.submissionSet &&\n !this.attached) {\n return Promise.resolve();\n }\n return this.itemsLoaded;\n }\n get defaultSchema() {\n return SelectComponent.schema();\n }\n get emptyValue() {\n if (this.component.multiple) {\n return [];\n }\n // if select has JSON data source type, we are defining if empty value would be an object or a string by checking JSON's first item\n if (this.component.dataSrc === 'json' && this.component.data.json) {\n const firstItem = this.component.data.json[0];\n let firstValue;\n if (this.valueProperty) {\n firstValue = lodash_1.default.get(firstItem, this.valueProperty);\n }\n else {\n firstValue = firstItem;\n }\n if (firstValue && typeof firstValue === 'string') {\n return '';\n }\n else {\n return {};\n }\n }\n if (this.valueProperty) {\n return '';\n }\n return {};\n }\n get valueProperty() {\n if (this.component.valueProperty) {\n return this.component.valueProperty;\n }\n // Force values datasource to use values without actually setting it on the component settings.\n if (this.component.dataSrc === 'values') {\n return 'value';\n }\n return '';\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'select';\n info.changeEvent = 'change';\n return info;\n }\n get isSelectResource() {\n return this.component.dataSrc === 'resource';\n }\n get itemsFromUrl() {\n return this.isSelectResource || this.isSelectURL;\n }\n get isInfiniteScrollProvided() {\n return this.itemsFromUrl;\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get shouldInitialLoad() {\n if (this.component.widget === 'html5' &&\n this.isEntireObjectDisplay() &&\n this.component.searchField &&\n this.dataValue) {\n return false;\n }\n return super.shouldLoad;\n }\n get selectMetadata() {\n return super.selectData;\n }\n get selectData() {\n return this.selectMetadata || this.component.selectData;\n }\n isEntireObjectDisplay() {\n return this.component.dataSrc === 'resource' && this.valueProperty === 'data';\n }\n selectValueAndLabel(data) {\n const value = this.getOptionValue((this.isEntireObjectDisplay() && !this.itemValue(data)) ? data : this.itemValue(data));\n return {\n value,\n label: this.itemTemplate((this.isEntireObjectDisplay() && !lodash_1.default.isObject(data.data)) ? { data: data } : data, value)\n };\n }\n itemTemplate(data, value) {\n if (!lodash_1.default.isNumber(data) && lodash_1.default.isEmpty(data)) {\n return '';\n }\n // If they wish to show the value in read only mode, then just return the itemValue here.\n if (this.options.readOnly && this.component.readOnlyValue) {\n return this.itemValue(data);\n }\n // Perform a fast interpretation if we should not use the template.\n if (data && !this.component.template) {\n const itemLabel = data.label || data;\n const value = (typeof itemLabel === 'string') ? this.t(itemLabel, { _userInput: true }) : itemLabel;\n return this.sanitize(value, this.shouldSanitizeValue);\n }\n if (this.component.multiple && lodash_1.default.isArray(this.dataValue) ? this.dataValue.find((val) => value === val) : (this.dataValue === value)) {\n const selectData = this.selectData;\n if (selectData) {\n const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;\n if (!this.templateData || !this.templateData[templateValue]) {\n this.getOptionTemplate(data, value);\n }\n if (this.component.multiple) {\n if (selectData[templateValue]) {\n data = selectData[templateValue];\n }\n }\n else {\n data = selectData;\n }\n }\n }\n if (typeof data === 'string' || typeof data === 'number') {\n return this.sanitize(this.t(data, { _userInput: true }), this.shouldSanitizeValue);\n }\n if (Array.isArray(data)) {\n return data.map((val) => {\n if (typeof val === 'string' || typeof val === 'number') {\n return this.sanitize(this.t(val, { _userInput: true }), this.shouldSanitizeValue);\n }\n return val;\n });\n }\n if (data.data) {\n // checking additional fields in the template for the selected Entire Object option\n const hasNestedFields = /item\\.data\\.\\w*/g.test(this.component.template);\n data.data = this.isEntireObjectDisplay() && lodash_1.default.isObject(data.data) && !hasNestedFields\n ? JSON.stringify(data.data)\n : data.data;\n }\n return super.itemTemplate(data, value);\n }\n /**\n * Adds an option to the select dropdown.\n *\n * @param value\n * @param label\n */\n addOption(value, label, attrs = {}, id = (0, utils_1.getRandomComponentId)()) {\n if (lodash_1.default.isNil(label))\n return;\n const idPath = this.component.idPath\n ? this.component.idPath.split('.').reduceRight((obj, key) => ({ [key]: obj }), id)\n : {};\n const option = Object.assign({ value: this.getOptionValue(value), label }, idPath);\n const skipOption = this.component.uniqueOptions\n ? !!this.selectOptions.find((selectOption) => lodash_1.default.isEqual(selectOption.value, option.value))\n : false;\n if (skipOption) {\n return;\n }\n if (value) {\n this.selectOptions.push(option);\n }\n if (this.refs.selectContainer && (this.component.widget === 'html5')) {\n // Replace an empty Object value to an empty String.\n if (option.value && lodash_1.default.isObject(option.value) && lodash_1.default.isEmpty(option.value)) {\n option.value = '';\n }\n // Add element to option so we can reference it later.\n const div = document.createElement('div');\n div.innerHTML = this.sanitize(this.renderTemplate('selectOption', {\n selected: lodash_1.default.isEqual(this.getOptionValue(this.dataValue), option.value),\n option,\n attrs,\n id,\n useId: (this.valueProperty === '' || this.isEntireObjectDisplay()) && lodash_1.default.isObject(value) && id,\n }), this.shouldSanitizeValue).trim();\n option.element = div.firstChild;\n this.refs.selectContainer.appendChild(option.element);\n }\n }\n addValueOptions(items) {\n items = items || [];\n let added = false;\n let data = this.dataValue;\n // preset submission value with value property before request.\n if (this.options.pdf && !items.length && this.component.dataSrc === 'url' && this.valueProperty) {\n data = Array.isArray(data)\n ? data.map(item => lodash_1.default.set({}, this.valueProperty, item))\n : lodash_1.default.set({}, this.valueProperty, data);\n }\n if (!this.selectOptions.length) {\n // Add the currently selected choices if they don't already exist.\n const currentChoices = Array.isArray(data) && this.component.multiple ? data : [data];\n added = this.addCurrentChoices(currentChoices, items);\n if (!added && !this.component.multiple) {\n this.addPlaceholder();\n }\n }\n return added;\n }\n disableInfiniteScroll() {\n if (!this.downloadedResources) {\n return;\n }\n this.downloadedResources.serverCount = this.downloadedResources.length;\n this.serverCount = this.downloadedResources.length;\n }\n /* eslint-disable max-statements */\n setItems(items, fromSearch) {\n var _a, _b;\n this.selectItems = items;\n // If the items is a string, then parse as JSON.\n if (typeof items == 'string') {\n try {\n items = JSON.parse(items);\n }\n catch (err) {\n console.warn(err.message);\n items = [];\n }\n }\n // Allow js processing (needed for form builder)\n if (this.component.onSetItems) {\n const newItems = typeof this.component.onSetItems === 'function'\n ? this.component.onSetItems(this, items)\n : this.evaluate(this.component.onSetItems, { items: items }, 'items');\n if (newItems) {\n items = newItems;\n }\n }\n if (!this.choices && this.refs.selectContainer) {\n this.empty(this.refs.selectContainer);\n }\n // If they provided select values, then we need to get them instead.\n if (this.component.selectValues) {\n items = lodash_1.default.get(items, this.component.selectValues, items) || [];\n }\n let areItemsEqual;\n if (this.itemsFromUrl) {\n areItemsEqual = this.isSelectURL ? lodash_1.default.isEqual(items, this.downloadedResources) : false;\n const areItemsEnded = this.component.limit > items.length;\n const areItemsDownloaded = areItemsEqual\n && this.downloadedResources\n && this.downloadedResources.length === items.length;\n if (areItemsEnded) {\n this.disableInfiniteScroll();\n }\n else if (areItemsDownloaded) {\n this.selectOptions = [];\n }\n else {\n this.serverCount = items.serverCount;\n }\n }\n if (this.isScrollLoading && items) {\n if (!areItemsEqual) {\n this.downloadedResources = this.downloadedResources\n ? this.downloadedResources.concat(items)\n : items;\n }\n this.downloadedResources.serverCount = items.serverCount || this.downloadedResources.serverCount;\n }\n else {\n this.downloadedResources = items || [];\n this.selectOptions = [];\n // If there is new select option with same id as already selected, set the new one\n if (!lodash_1.default.isEmpty(this.dataValue) && this.component.idPath) {\n const selectedOptionId = lodash_1.default.get(this.dataValue, this.component.idPath, null);\n const newOptionWithSameId = !lodash_1.default.isNil(selectedOptionId) && items.find(item => {\n const itemId = lodash_1.default.get(item, this.component.idPath);\n return itemId === selectedOptionId;\n });\n if (newOptionWithSameId) {\n this.setValue(newOptionWithSameId);\n }\n }\n }\n // Add the value options.\n if (!fromSearch) {\n this.addValueOptions(items);\n }\n if (this.component.widget === 'html5' && !this.component.placeholder) {\n this.addOption(null, '');\n }\n // Iterate through each of the items.\n lodash_1.default.each(items, (item, index) => {\n // preventing references of the components inside the form to the parent form when building forms\n if (this.root && this.root.options.editForm && this.root.options.editForm._id && this.root.options.editForm._id === item._id)\n return;\n const itemValueAndLabel = this.selectValueAndLabel(item);\n this.addOption(itemValueAndLabel.value, itemValueAndLabel.label, {}, lodash_1.default.get(item, this.component.idPath, String(index)));\n });\n if (this.choices) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n else if (this.loading) {\n // Re-attach select input.\n // this.appendTo(this.refs.input[0], this.selectContainer);\n }\n // We are no longer loading.\n this.isScrollLoading = false;\n this.loading = false;\n const searching = fromSearch && ((_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.input) === null || _b === void 0 ? void 0 : _b.isFocussed);\n if (!searching) {\n // If a value is provided, then select it.\n if (!this.isEmpty() || this.isRemoveButtonPressed) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else if (this.shouldAddDefaultValue && !this.options.readOnly) {\n // If a default value is provided then select it.\n const defaultValue = this.defaultValue;\n if (!this.isEmpty(defaultValue)) {\n this.setValue(defaultValue);\n }\n }\n }\n // Say we are done loading the items.\n this.itemsLoadedResolve();\n }\n getSingleItemValueForHTMLMode(data) {\n var _a;\n const option = (_a = this.selectOptions) === null || _a === void 0 ? void 0 : _a.find(({ value }) => lodash_1.default.isEqual(value, data));\n if (option) {\n return option.label || data;\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (!this.isHtmlRenderMode()) {\n return super.itemValueForHTMLMode(value);\n }\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item)\n ? this.itemValueForHTMLMode(item)\n : this.getSingleItemValueForHTMLMode(item));\n return values.join(', ');\n }\n return this.getSingleItemValueForHTMLMode(value);\n }\n /* eslint-enable max-statements */\n get defaultValue() {\n let defaultValue = super.defaultValue;\n if (!defaultValue && (this.component.defaultValue === false || this.component.defaultValue === 0)) {\n defaultValue = this.component.defaultValue;\n }\n return defaultValue;\n }\n get loadingError() {\n return !this.component.refreshOn && !this.component.refreshOnBlur && this.networkError;\n }\n loadItems(url, search, headers, options, method, body) {\n options = options || {};\n // See if we should load items or not.\n if (!this.shouldLoad || (!this.itemsFromUrl && this.options.readOnly)) {\n this.isScrollLoading = false;\n this.loading = false;\n this.itemsLoadedResolve();\n return;\n }\n // See if they have not met the minimum search requirements.\n const minSearch = parseInt(this.component.minSearch, 10);\n if (this.component.searchField &&\n (minSearch > 0) &&\n (!search || (search.length < minSearch))) {\n // Set empty items.\n return this.setItems([]);\n }\n // Ensure we have a method and remove any body if method is get\n method = method || 'GET';\n if (method.toUpperCase() === 'GET') {\n body = null;\n }\n const limit = this.component.limit || 100;\n const skip = this.isScrollLoading ? this.selectOptions.length : 0;\n const query = this.component.disableLimit ? {} : {\n limit,\n skip,\n };\n // Allow for url interpolation.\n url = this.interpolate(url, {\n formioBase: Formio_1.Formio.getBaseUrl(),\n search,\n limit,\n skip,\n page: Math.abs(Math.floor(skip / limit))\n });\n // Add search capability.\n if (this.component.searchField && search) {\n const searchValue = Array.isArray(search)\n ? search.join(',')\n : typeof search === 'object'\n ? JSON.stringify(search)\n : search;\n query[this.component.searchField] = this.component.searchField.endsWith('__regex')\n ? lodash_1.default.escapeRegExp(searchValue)\n : searchValue;\n }\n // If they wish to return only some fields.\n if (this.component.selectFields) {\n query.select = this.component.selectFields;\n }\n // Add sort capability\n if (this.component.sort) {\n query.sort = this.component.sort;\n }\n if (!lodash_1.default.isEmpty(query)) {\n // Add the query string.\n url += (!url.includes('?') ? '?' : '&') + Formio_1.Formio.serialize(query, (item) => this.interpolate(item));\n }\n // Add filter capability\n if (this.component.filter) {\n url += (!url.includes('?') ? '?' : '&') + this.interpolate(this.component.filter);\n }\n // Set ignoreCache if it is\n options.ignoreCache = this.component.ignoreCache;\n // Make the request.\n options.header = headers;\n this.loading = true;\n Formio_1.Formio.makeRequest(this.options.formio, 'select', url, method, body, options)\n .then((response) => {\n this.loading = false;\n this.setItems(response, !!search);\n })\n .catch((err) => {\n if (this.itemsFromUrl) {\n this.setItems([]);\n this.disableInfiniteScroll();\n }\n this.isScrollLoading = false;\n this.handleLoadingError(err);\n });\n }\n handleLoadingError(err) {\n this.loading = false;\n if (err.networkError) {\n this.networkError = true;\n }\n this.itemsLoadedResolve();\n this.emit('componentError', {\n component: this.component,\n message: err.toString(),\n });\n console.warn(`Unable to load resources for ${this.key}`);\n }\n /**\n * Get the request headers for this select dropdown.\n */\n get requestHeaders() {\n // Create the headers object.\n const headers = new Formio_1.Formio.Headers();\n // Add custom headers to the url.\n if (this.component.data && this.component.data.headers) {\n try {\n lodash_1.default.each(this.component.data.headers, (header) => {\n if (header.key) {\n headers.set(header.key, this.interpolate(header.value));\n }\n });\n }\n catch (err) {\n console.warn(err.message);\n }\n }\n return headers;\n }\n getCustomItems() {\n const customItems = this.evaluate(this.component.data.custom, {\n values: []\n }, 'values');\n this.asyncValues = (0, utils_1.isPromise)(customItems);\n return customItems;\n }\n asyncCustomValues() {\n if (!lodash_1.default.isBoolean(this.asyncValues)) {\n this.getCustomItems();\n }\n return this.asyncValues;\n }\n updateCustomItems(forceUpdate) {\n if (this.asyncCustomValues()) {\n if (!forceUpdate && !this.active) {\n this.itemsLoadedResolve();\n return;\n }\n this.loading = true;\n this.getCustomItems()\n .then(items => {\n this.loading = false;\n this.setItems(items || []);\n })\n .catch(err => {\n this.handleLoadingError(err);\n });\n }\n else {\n this.setItems(this.getCustomItems() || []);\n }\n }\n isEmpty(value = this.dataValue) {\n return super.isEmpty(value) || value === undefined;\n }\n refresh(value, { instance }) {\n if (this.component.clearOnRefresh && (instance && !instance.pristine)) {\n this.setValue(this.emptyValue);\n }\n this.updateItems(null, true);\n }\n get additionalResourcesAvailable() {\n return lodash_1.default.isNil(this.serverCount) || (this.serverCount > this.downloadedResources.length);\n }\n get serverCount() {\n if (this.isFromSearch) {\n return this.searchServerCount;\n }\n return this.defaultServerCount;\n }\n set serverCount(value) {\n if (this.isFromSearch) {\n this.searchServerCount = value;\n }\n else {\n this.defaultServerCount = value;\n }\n }\n get downloadedResources() {\n if (this.isFromSearch) {\n return this.searchDownloadedResources;\n }\n return this.defaultDownloadedResources;\n }\n set downloadedResources(value) {\n if (this.isFromSearch) {\n this.searchDownloadedResources = value;\n }\n else {\n this.defaultDownloadedResources = value;\n }\n }\n addPlaceholder() {\n if (!this.component.placeholder) {\n return;\n }\n this.addOption('', this.component.placeholder, { placeholder: true });\n }\n /**\n * Activate this select control.\n */\n activate() {\n if (this.loading || !this.active) {\n this.setLoadingItem();\n }\n if (this.active) {\n return;\n }\n this.activated = true;\n this.triggerUpdate();\n }\n setLoadingItem(addToCurrentList = false) {\n if (this.choices) {\n if (addToCurrentList) {\n this.choices.setChoices([{\n value: `${this.id}-loading`,\n label: 'Loading...',\n disabled: true,\n }], 'value', 'label');\n }\n else {\n this.choices.setChoices([{\n value: '',\n label: `<i class=\"${this.iconClass('refresh')}\" style=\"font-size:1.3em;\"></i>`,\n disabled: true,\n }], 'value', 'label', true);\n }\n }\n else if (this.component.dataSrc === 'url' || this.component.dataSrc === 'resource') {\n this.addOption('', this.t('loading...'));\n }\n }\n get active() {\n return !this.component.lazyLoad || this.activated;\n }\n render() {\n const info = this.inputInfo;\n info.attr = info.attr || {};\n info.multiple = this.component.multiple;\n return super.render(this.wrapElement(this.renderTemplate('select', {\n input: info,\n selectOptions: '',\n index: null,\n })));\n }\n wrapElement(element) {\n return this.component.addResource && !this.options.readOnly\n ? (this.renderTemplate('resourceAdd', {\n element\n }))\n : element;\n }\n choicesOptions() {\n const useSearch = this.component.hasOwnProperty('searchEnabled') ? this.component.searchEnabled : true;\n const placeholderValue = this.t(this.component.placeholder, { _userInput: true });\n let customOptions = this.component.customOptions || {};\n if (typeof customOptions == 'string') {\n try {\n customOptions = JSON.parse(customOptions);\n }\n catch (err) {\n console.warn(err.message);\n customOptions = {};\n }\n }\n const commonFuseOptions = {\n maxPatternLength: 1000,\n distance: 1000,\n };\n return Object.assign({ removeItemButton: this.component.disabled ? false : lodash_1.default.get(this.component, 'removeItemButton', true), itemSelectText: '', classNames: {\n containerOuter: 'choices form-group formio-choices',\n containerInner: this.transform('class', 'form-control ui fluid selection dropdown')\n }, addItemText: false, allowHTML: true, placeholder: !!this.component.placeholder, placeholderValue: placeholderValue, noResultsText: this.t('No results found'), noChoicesText: this.t('No choices to choose from'), searchPlaceholderValue: this.t('Type to search'), shouldSort: false, position: (this.component.dropdown || 'auto'), searchEnabled: useSearch, searchChoices: !this.component.searchField, searchFields: lodash_1.default.get(this, 'component.searchFields', ['label']), shadowRoot: this.root ? this.root.shadowRoot : null, fuseOptions: this.component.useExactSearch\n ? Object.assign({ tokenize: true, matchAllTokens: true }, commonFuseOptions) : Object.assign({}, lodash_1.default.get(this, 'component.fuseOptions', {}), Object.assign({ include: 'score', threshold: lodash_1.default.get(this, 'component.selectThreshold', 0.3) }, commonFuseOptions)), valueComparer: lodash_1.default.isEqual, resetScrollPosition: false }, customOptions);\n }\n /* eslint-disable max-statements */\n attach(element) {\n var _a, _b, _c;\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n selectContainer: 'single',\n addResource: 'single',\n autocompleteInput: 'single'\n });\n //enable autocomplete for select\n const autocompleteInput = this.refs.autocompleteInput;\n if (autocompleteInput) {\n this.addEventListener(autocompleteInput, 'change', (event) => {\n this.setValue(event.target.value);\n });\n }\n const input = this.refs.selectContainer;\n if (!input) {\n return;\n }\n this.addEventListener(input, this.inputInfo.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n this.attachRefreshOnBlur();\n if (this.component.widget === 'html5') {\n this.addFocusBlurEvents(input);\n this.triggerUpdate(null, true);\n if (this.visible) {\n this.setItems(this.selectItems || []);\n }\n this.focusableElement = input;\n if (this.component.dataSrc === 'custom') {\n this.addEventListener(input, 'focus', () => this.updateCustomItems());\n }\n this.addEventListener(input, 'keydown', (event) => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n this.setValue(this.emptyValue);\n }\n });\n return;\n }\n const tabIndex = input.tabIndex;\n this.addPlaceholder();\n input.setAttribute('dir', this.i18next.dir());\n if ((_c = (_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.containerOuter) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.parentNode) {\n this.choices.destroy();\n }\n const choicesOptions = this.choicesOptions();\n if (ChoicesWrapper_1.default) {\n this.choices = new ChoicesWrapper_1.default(input, choicesOptions);\n if (this.selectOptions && this.selectOptions.length) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n if (this.component.multiple) {\n this.focusableElement = this.choices.input.element;\n }\n else {\n this.focusableElement = this.choices.containerInner.element;\n this.choices.containerOuter.element.setAttribute('tabIndex', '-1');\n this.addEventListener(this.choices.containerOuter.element, 'focus', () => this.focusableElement.focus());\n }\n Input_1.default.prototype.addFocusBlurEvents.call(this, this.focusableElement);\n if (this.itemsFromUrl && !this.component.noRefreshOnScroll) {\n this.scrollList = this.choices.choiceList.element;\n this.addEventListener(this.scrollList, 'scroll', () => this.onScroll());\n }\n if (choicesOptions.removeItemButton) {\n this.addEventListener(input, 'removeItem', () => {\n this.isRemoveButtonPressed = true;\n });\n }\n }\n if (window && this.choices && this.shouldPositionDropdown) {\n this.addEventListener(window.document, 'scroll', () => {\n this.positionDropdown(true);\n }, false, true);\n }\n this.focusableElement.setAttribute('tabIndex', tabIndex);\n // If a search field is provided, then add an event listener to update items on search.\n if (this.component.searchField) {\n // Make sure to clear the search when no value is provided.\n if (this.choices && this.choices.input && this.choices.input.element) {\n this.addEventListener(this.choices.input.element, 'input', (event) => {\n this.isFromSearch = !!event.target.value;\n if (!event.target.value) {\n this.triggerUpdate();\n }\n else {\n this.serverCount = null;\n this.downloadedResources = [];\n }\n });\n }\n this.addEventListener(input, 'choice', () => {\n if (this.component.multiple && this.component.dataSrc === 'resource' && this.isFromSearch) {\n this.triggerUpdate();\n }\n this.isFromSearch = false;\n });\n // avoid spamming the resource/url endpoint when we have server side filtering enabled.\n const debounceTimeout = this.component.searchField && (this.isSelectResource || this.isSelectURL) ?\n (this.component.searchDebounce === 0 ? 0 : this.component.searchDebounce || this.defaultSchema.searchDebounce) * 1000\n : 0;\n const updateComponent = (evt) => {\n this.triggerUpdate(evt.detail.value);\n };\n this.addEventListener(input, 'search', lodash_1.default.debounce((e) => {\n updateComponent(e);\n this.positionDropdown();\n }, debounceTimeout));\n this.addEventListener(input, 'stopSearch', () => this.triggerUpdate());\n this.addEventListener(input, 'hideDropdown', () => {\n if (this.choices && this.choices.input && this.choices.input.element) {\n this.choices.input.element.value = '';\n }\n this.updateItems(null, true);\n });\n }\n this.addEventListener(input, 'showDropdown', () => {\n this.update();\n this.positionDropdown();\n });\n if (this.shouldPositionDropdown) {\n this.addEventListener(input, 'highlightChoice', () => {\n this.positionDropdown();\n });\n }\n if (this.choices && choicesOptions.placeholderValue && this.choices._isSelectOneElement) {\n this.addPlaceholderItem(choicesOptions.placeholderValue);\n this.addEventListener(input, 'removeItem', () => {\n this.addPlaceholderItem(choicesOptions.placeholderValue);\n });\n }\n // Add value options.\n this.addValueOptions();\n this.setChoicesValue(this.dataValue);\n if (this.isSelectResource && this.refs.addResource) {\n this.addEventListener(this.refs.addResource, 'click', (event) => {\n event.preventDefault();\n const formioForm = this.ce('div');\n const dialog = this.createModal(formioForm);\n const projectUrl = lodash_1.default.get(this.root, 'formio.projectUrl', Formio_1.Formio.getProjectUrl());\n const formUrl = `${projectUrl}/form/${this.component.data.resource}`;\n new Form_1.default(formioForm, formUrl, {}).ready\n .then((form) => {\n form.on('submit', (submission) => {\n // If valueProperty is set, replace the submission with the corresponding value\n let value = this.valueProperty ? lodash_1.default.get(submission, this.valueProperty) : submission;\n if (this.component.multiple) {\n value = [...this.dataValue, value];\n }\n this.setValue(value);\n this.triggerUpdate();\n dialog.close();\n });\n });\n });\n }\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n this.triggerUpdate();\n return superAttach;\n }\n setDropdownPosition() {\n var _a, _b, _c, _d;\n const dropdown = (_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.dropdown) === null || _b === void 0 ? void 0 : _b.element;\n const container = (_d = (_c = this.choices) === null || _c === void 0 ? void 0 : _c.containerOuter) === null || _d === void 0 ? void 0 : _d.element;\n if (!dropdown || !container) {\n return;\n }\n const containerPosition = container.getBoundingClientRect();\n const isFlipped = container.classList.contains('is-flipped');\n lodash_1.default.assign(dropdown.style, {\n top: `${isFlipped ? containerPosition.top - dropdown.offsetHeight : containerPosition.top + containerPosition.height}px`,\n left: `${containerPosition.left}px`,\n width: `${containerPosition.width}px`,\n position: 'fixed',\n bottom: 'unset',\n right: 'unset',\n });\n }\n hasDataGridAncestor(comp) {\n comp = comp || this;\n if (comp.inDataGrid || comp.type === 'datagrid') {\n return true;\n }\n else if (comp.parent) {\n return this.hasDataGridAncestor(comp.parent);\n }\n else {\n return false;\n }\n }\n positionDropdown(scroll) {\n var _a;\n if (!this.shouldPositionDropdown || !this.choices || (!((_a = this.choices.dropdown) === null || _a === void 0 ? void 0 : _a.isActive) && scroll)) {\n return;\n }\n this.setDropdownPosition();\n this.itemsLoaded.then(() => {\n this.setDropdownPosition();\n });\n }\n get isLoadingAvailable() {\n return !this.isScrollLoading && this.additionalResourcesAvailable;\n }\n onScroll() {\n if (this.isLoadingAvailable) {\n this.isScrollLoading = true;\n this.setLoadingItem(true);\n this.triggerUpdate(this.choices.input.element.value);\n }\n }\n attachRefreshOnBlur() {\n if (this.component.refreshOnBlur) {\n this.on('blur', (instance) => {\n this.checkRefreshOn([{ instance, value: instance.dataValue }], { fromBlur: true });\n });\n }\n }\n addPlaceholderItem(placeholderValue) {\n const items = this.choices._store.activeItems;\n if (!items.length) {\n this.choices._addItem({\n value: '',\n label: placeholderValue,\n choiceId: 0,\n groupId: -1,\n customProperties: null,\n placeholder: true,\n keyCode: null\n });\n }\n }\n /* eslint-enable max-statements */\n update() {\n if (this.component.dataSrc === 'custom') {\n this.updateCustomItems();\n }\n // Activate the control.\n this.activate();\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.choices) {\n return;\n }\n if (disabled) {\n this.setDisabled(this.choices.containerInner.element, true);\n this.focusableElement.removeAttribute('tabIndex');\n this.choices.disable();\n }\n else {\n this.setDisabled(this.choices.containerInner.element, false);\n this.focusableElement.setAttribute('tabIndex', this.component.tabindex || 0);\n this.choices.enable();\n }\n }\n get disabled() {\n return super.disabled;\n }\n set visible(value) {\n // If we go from hidden to visible, trigger a refresh.\n if (value && (!this._visible !== !value)) {\n this.triggerUpdate();\n }\n super.visible = value;\n }\n get visible() {\n return super.visible;\n }\n /**\n * @param {*} value\n * @param {Array} items\n */\n addCurrentChoices(values, items, keyValue) {\n if (!values) {\n return false;\n }\n const notFoundValuesToAdd = [];\n const added = values.reduce((defaultAdded, value) => {\n if (!value || lodash_1.default.isEmpty(value)) {\n return defaultAdded;\n }\n let found = false;\n // Make sure that `items` and `this.selectOptions` points\n // to the same reference. Because `this.selectOptions` is\n // internal property and all items are populated by\n // `this.addOption` method, we assume that items has\n // 'label' and 'value' properties. This assumption allows\n // us to read correct value from the item.\n const isSelectOptions = items === this.selectOptions;\n if (items && items.length) {\n lodash_1.default.each(items, (choice) => {\n if (choice._id && value._id && (choice._id === value._id)) {\n found = true;\n return false;\n }\n const itemValue = keyValue ? choice.value : this.itemValue(choice, isSelectOptions);\n found |= lodash_1.default.isEqual(itemValue, value);\n return found ? false : true;\n });\n }\n // Add the default option if no item is found.\n if (!found) {\n notFoundValuesToAdd.push(this.selectValueAndLabel(value));\n return true;\n }\n return found || defaultAdded;\n }, false);\n if (notFoundValuesToAdd.length) {\n if (this.choices) {\n this.choices.setChoices(notFoundValuesToAdd, 'value', 'label');\n }\n notFoundValuesToAdd.map(notFoundValue => {\n this.addOption(notFoundValue.value, notFoundValue.label);\n });\n }\n return added;\n }\n getValueAsString(data, options) {\n return (this.component.multiple && Array.isArray(data))\n ? data.map((v) => this.asString(v, options)).join(', ')\n : this.asString(data, options);\n }\n getValue() {\n // If the widget isn't active.\n if (this.viewOnly || this.loading\n || (!this.component.lazyLoad && !this.selectOptions.length)\n || !this.element) {\n return this.dataValue;\n }\n let value = this.emptyValue;\n if (this.choices) {\n value = this.choices.getValue(true);\n // Make sure we don't get the placeholder\n if (!this.component.multiple &&\n this.component.placeholder &&\n (value === this.t(this.component.placeholder, { _userInput: true }))) {\n value = this.emptyValue;\n }\n }\n else if (this.refs.selectContainer) {\n value = this.refs.selectContainer.value;\n if (this.valueProperty === '' || this.isEntireObjectDisplay()) {\n if (value === '') {\n return {};\n }\n const option = this.selectOptions[value] ||\n this.selectOptions.find(option => option.id === value);\n if (option && lodash_1.default.isObject(option.value)) {\n value = option.value;\n }\n }\n }\n else {\n value = this.dataValue;\n }\n // Choices will return undefined if nothing is selected. We really want '' to be empty.\n if (value === undefined || value === null) {\n value = '';\n }\n return value;\n }\n redraw() {\n const done = super.redraw();\n this.triggerUpdate();\n return done;\n }\n normalizeSingleValue(value) {\n if (lodash_1.default.isNil(value)) {\n return;\n }\n const valueIsObject = lodash_1.default.isObject(value);\n //check if value equals to default emptyValue\n if (valueIsObject && Object.keys(value).length === 0) {\n return value;\n }\n const dataType = this.component.dataType || 'auto';\n const normalize = {\n value,\n number() {\n const numberValue = Number(this.value);\n const isEquivalent = value.toString() === numberValue.toString();\n if (!Number.isNaN(numberValue) && Number.isFinite(numberValue) && value !== '' && isEquivalent) {\n this.value = numberValue;\n }\n return this;\n },\n boolean() {\n if (lodash_1.default.isString(this.value)\n && (this.value.toLowerCase() === 'true'\n || this.value.toLowerCase() === 'false')) {\n this.value = (this.value.toLowerCase() === 'true');\n }\n return this;\n },\n string() {\n this.value = String(this.value);\n return this;\n },\n object() {\n return this;\n },\n auto() {\n if (lodash_1.default.isObject(this.value)) {\n this.value = this.object().value;\n }\n else {\n this.value = this.string().number().boolean().value;\n }\n return this;\n }\n };\n try {\n return normalize[dataType]().value;\n }\n catch (err) {\n console.warn('Failed to normalize value', err);\n return value;\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && Array.isArray(value)) {\n return value.map((singleValue) => this.normalizeSingleValue(singleValue));\n }\n return super.normalizeValue(this.normalizeSingleValue(value));\n }\n setMetadata(value) {\n var _a;\n if (lodash_1.default.isNil(value)) {\n return;\n }\n const valueIsObject = lodash_1.default.isObject(value);\n //check if value equals to default emptyValue\n if (valueIsObject && Object.keys(value).length === 0) {\n return value;\n }\n // Check to see if we need to save off the template data into our metadata.\n const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;\n const shouldSaveData = !valueIsObject || this.component.reference;\n if (templateValue && shouldSaveData && this.templateData && this.templateData[templateValue] && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submission)) {\n const submission = this.root.submission;\n if (!submission.metadata) {\n submission.metadata = {};\n }\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n let templateData = this.templateData[templateValue];\n if (this.component.multiple) {\n templateData = {};\n const dataValue = this.dataValue;\n if (dataValue && lodash_1.default.isArray(dataValue) && dataValue.length) {\n dataValue.forEach((dataValueItem) => {\n const dataValueItemValue = this.component.reference ? dataValueItem._id.toString() : dataValueItem;\n templateData[dataValueItemValue] = this.templateData[dataValueItemValue];\n });\n }\n templateData[value] = this.templateData[value];\n }\n lodash_1.default.set(submission.metadata.selectData, this.path, templateData);\n }\n }\n updateValue(value, flags) {\n const changed = super.updateValue(value, flags);\n if (changed || !this.selectMetadata) {\n if (this.component.multiple && Array.isArray(this.dataValue)) {\n this.dataValue.forEach(singleValue => this.setMetadata(singleValue));\n }\n else {\n this.setMetadata(this.dataValue);\n }\n }\n return changed;\n }\n setValue(value, flags = {}) {\n const previousValue = this.dataValue;\n const changed = this.updateValue(value, flags);\n if (this.component.widget === 'html5' && (lodash_1.default.isEqual(value, previousValue) || lodash_1.default.isEqual(previousValue, {}) && lodash_1.default.isEqual(flags, {})) && !flags.fromSubmission) {\n return false;\n }\n value = this.dataValue;\n const hasPreviousValue = !this.isEmpty(previousValue);\n const hasValue = !this.isEmpty(value);\n // Undo typing when searching to set the value.\n if (this.component.multiple && Array.isArray(value)) {\n value = value.map(value => {\n if (typeof value === 'boolean' || typeof value === 'number') {\n return value.toString();\n }\n return value;\n });\n }\n else {\n if (typeof value === 'boolean' || typeof value === 'number') {\n value = value.toString();\n }\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.itemsLoaded.then(() => {\n this.redraw();\n });\n return changed;\n }\n // Do not set the value if we are loading... that will happen after it is done.\n if (this.loading) {\n return changed;\n }\n // Determine if we need to perform an initial lazyLoad api call if searchField is provided.\n if (this.isInitApiCallNeeded(hasValue)) {\n this.loading = true;\n this.lazyLoadInit = true;\n const searchProperty = this.component.searchField || this.component.valueProperty;\n this.triggerUpdate(lodash_1.default.get(value.data || value, searchProperty, value), true);\n return changed;\n }\n // Add the value options.\n this.itemsLoaded.then(() => {\n this.addValueOptions();\n this.setChoicesValue(value, hasPreviousValue, flags);\n });\n return changed;\n }\n isInitApiCallNeeded(hasValue) {\n return this.component.lazyLoad &&\n !this.lazyLoadInit &&\n !this.active &&\n !this.selectOptions.length &&\n hasValue &&\n this.shouldInitialLoad &&\n this.visible && (this.component.searchField || this.component.valueProperty);\n }\n setChoicesValue(value, hasPreviousValue, flags = {}) {\n const hasValue = !this.isEmpty(value) || flags.fromSubmission;\n hasPreviousValue = (hasPreviousValue === undefined) ? true : hasPreviousValue;\n if (this.choices) {\n // Now set the value.\n if (hasValue) {\n this.choices.removeActiveItems();\n // Add the currently selected choices if they don't already exist.\n const currentChoices = Array.isArray(value) && this.component.multiple ? value : [value];\n if (!this.addCurrentChoices(currentChoices, this.selectOptions, true)) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n this.choices.setChoiceByValue(currentChoices);\n }\n else if (hasPreviousValue || flags.resetValue) {\n this.choices.removeActiveItems();\n }\n }\n else {\n if (hasValue) {\n const values = Array.isArray(value) ? value : [value];\n if (!lodash_1.default.isEqual(this.dataValue, this.defaultValue) && this.selectOptions.length < 2\n || (this.selectData && flags.fromSubmission)) {\n const { value, label } = this.selectValueAndLabel(this.dataValue);\n this.addOption(value, label);\n }\n lodash_1.default.each(this.selectOptions, (selectOption) => {\n lodash_1.default.each(values, (val) => {\n if (selectOption.value === '') {\n selectOption.value = {};\n }\n if (lodash_1.default.isEqual(val, selectOption.value) && selectOption.element) {\n selectOption.element.selected = true;\n selectOption.element.setAttribute('selected', 'selected');\n return false;\n }\n });\n });\n }\n else {\n lodash_1.default.each(this.selectOptions, (selectOption) => {\n if (selectOption.element) {\n selectOption.element.selected = false;\n selectOption.element.removeAttribute('selected');\n }\n });\n }\n }\n }\n get itemsLoaded() {\n return this._itemsLoaded || Promise.resolve();\n }\n set itemsLoaded(promise) {\n this._itemsLoaded = promise;\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.getOptionsValues();\n if (values) {\n if (lodash_1.default.isObject(value)) {\n const compareComplexValues = (optionValue) => {\n const normalizedOptionValue = this.normalizeSingleValue(optionValue);\n if (!lodash_1.default.isObject(normalizedOptionValue)) {\n return false;\n }\n try {\n return (JSON.stringify(normalizedOptionValue) === JSON.stringify(value));\n }\n catch (err) {\n console.warn.error('Error while comparing items', err);\n return false;\n }\n };\n return values.findIndex((optionValue) => compareComplexValues(optionValue)) !== -1;\n }\n return values.findIndex((optionValue) => this.normalizeSingleValue(optionValue) === value) !== -1;\n }\n return false;\n }\n /**\n * Performs required transformations on the initial value to use in selectOptions\n * @param {*} value\n */\n getOptionValue(value) {\n return lodash_1.default.isObject(value) && this.isEntireObjectDisplay()\n ? this.normalizeSingleValue(value)\n : lodash_1.default.isObject(value) && (this.valueProperty || this.component.key !== 'resource')\n ? value\n : lodash_1.default.isObject(value) && !this.valueProperty\n ? this.interpolate(this.component.template, { item: value }).replace(/<\\/?[^>]+(>|$)/g, '')\n : lodash_1.default.isNull(value)\n ? this.emptyValue\n : String(this.normalizeSingleValue(value));\n }\n /**\n * If component has static values (values, json) or custom values, returns an array of them\n * @returns {Array<*>|undefined}\n */\n getOptionsValues() {\n let rawItems = [];\n switch (this.component.dataSrc) {\n case 'values':\n rawItems = this.component.data.values;\n break;\n case 'json':\n rawItems = this.component.data.json;\n break;\n case 'custom':\n rawItems = this.getCustomItems();\n break;\n }\n if (typeof rawItems === 'string') {\n try {\n rawItems = JSON.parse(rawItems);\n }\n catch (err) {\n console.warn(err.message);\n rawItems = [];\n }\n }\n if (!Array.isArray(rawItems)) {\n return;\n }\n return rawItems.map((item) => this.getOptionValue(this.itemValue(item)));\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue('', {\n noUpdateEvent: true\n });\n this.unset();\n }\n /**\n * Check if a component is eligible for multiple validation\n *\n * @return {boolean}\n */\n validateMultiple() {\n // Select component will contain one input when flagged as multiple.\n return false;\n }\n /**\n * Output this select dropdown as a string value.\n * @return {*}\n */\n isBooleanOrNumber(value) {\n return typeof value === 'number' || typeof value === 'boolean';\n }\n getNormalizedValues() {\n if (!this.component || !this.component.data || !this.component.data.values) {\n return;\n }\n return this.component.data.values.map(value => ({ label: value.label, value: String(this.normalizeSingleValue(value.value)) }));\n }\n asString(value, options = {}) {\n var _a;\n value = value !== null && value !== void 0 ? value : this.getValue();\n //need to convert values to strings to be able to compare values with available options that are strings\n const convertToString = (data, valueProperty) => {\n if (valueProperty) {\n if (Array.isArray(data)) {\n data.forEach((item) => item[valueProperty] = item[valueProperty].toString());\n }\n else {\n data[valueProperty] = data[valueProperty].toString();\n }\n return data;\n }\n if (this.isBooleanOrNumber(data)) {\n data = data.toString();\n }\n if (Array.isArray(data) && data.some(item => this.isBooleanOrNumber(item))) {\n data = data.map(item => {\n if (this.isBooleanOrNumber(item)) {\n item = item.toString();\n }\n });\n }\n return data;\n };\n value = convertToString(value);\n if (['values', 'custom'].includes(this.component.dataSrc) && !this.asyncCustomValues()) {\n const { items, valueProperty, } = this.component.dataSrc === 'values'\n ? {\n items: convertToString(this.getNormalizedValues(), 'value'),\n valueProperty: 'value',\n }\n : {\n items: convertToString(this.getCustomItems(), this.valueProperty),\n valueProperty: this.valueProperty,\n };\n const getFromValues = () => {\n const initialValue = lodash_1.default.find(items, [valueProperty, value]);\n const values = this.defaultSchema.data.values || [];\n return lodash_1.default.isEqual(initialValue, values[0]) ? '-' : initialValue;\n };\n value = (this.component.multiple && Array.isArray(value))\n ? lodash_1.default.filter(items, (item) => value.includes(item.value))\n : valueProperty\n ? (_a = getFromValues()) !== null && _a !== void 0 ? _a : { value, label: value }\n : value;\n }\n if (lodash_1.default.isString(value)) {\n return value;\n }\n const getTemplateValue = (v) => {\n const itemTemplate = this.itemTemplate(v);\n return options.csv && itemTemplate\n ? (0, utils_1.unescapeHTML)(itemTemplate)\n : itemTemplate;\n };\n if (Array.isArray(value)) {\n const items = [];\n value.forEach(item => items.push(getTemplateValue(item)));\n if (this.component.dataSrc === 'resource' && items.length > 0) {\n return items.join(', ');\n }\n else if (items.length > 0) {\n return items.join('<br />');\n }\n else {\n return '-';\n }\n }\n if (this.isEntireObjectDisplay() && lodash_1.default.isObject(value)) {\n return JSON.stringify(value);\n }\n return !lodash_1.default.isNil(value)\n ? getTemplateValue(value)\n : '-';\n }\n detach() {\n var _a, _b;\n super.detach();\n this.off('blur');\n if (this.choices) {\n if ((_b = (_a = this.choices.containerOuter) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.parentNode) {\n this.choices.destroy();\n }\n this.choices = null;\n }\n }\n focus() {\n if (this.focusableElement) {\n super.focus.call(this);\n this.focusableElement.focus();\n }\n }\n setErrorClasses(elements, dirty, hasError, hasMessages, element = this.element) {\n super.setErrorClasses(elements, dirty, hasError, hasMessages, element);\n if (this.choices) {\n super.setErrorClasses([this.choices.containerInner.element], dirty, hasError, hasMessages, element);\n }\n else {\n super.setErrorClasses([this.refs.selectContainer], dirty, hasError, hasMessages, element);\n }\n }\n}\nexports[\"default\"] = SelectComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/select/Select.js?");
7161
+ 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 Formio_1 = __webpack_require__(/*! ../../Formio */ \"./lib/cjs/Formio.js\");\nconst ListComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/list/ListComponent */ \"./lib/cjs/components/_classes/list/ListComponent.js\"));\nconst Input_1 = __importDefault(__webpack_require__(/*! ../_classes/input/Input */ \"./lib/cjs/components/_classes/input/Input.js\"));\nconst Form_1 = __importDefault(__webpack_require__(/*! ../../Form */ \"./lib/cjs/Form.js\"));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst ChoicesWrapper_1 = __importDefault(__webpack_require__(/*! ../../utils/ChoicesWrapper */ \"./lib/cjs/utils/ChoicesWrapper.js\"));\nclass SelectComponent extends ListComponent_1.default {\n static schema(...extend) {\n return ListComponent_1.default.schema({\n type: 'select',\n label: 'Select',\n key: 'select',\n idPath: 'id',\n data: {\n values: [{ label: '', value: '' }],\n json: '',\n url: '',\n resource: '',\n custom: ''\n },\n clearOnRefresh: false,\n limit: 100,\n valueProperty: '',\n lazyLoad: true,\n filter: '',\n searchEnabled: true,\n searchDebounce: 0.3,\n searchField: '',\n minSearch: 0,\n readOnlyValue: false,\n selectFields: '',\n selectThreshold: 0.3,\n uniqueOptions: false,\n tableView: true,\n fuseOptions: {\n include: 'score',\n threshold: 0.3,\n },\n indexeddb: {\n filter: {}\n },\n customOptions: {},\n useExactSearch: false,\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Select',\n group: 'basic',\n icon: 'th-list',\n weight: 70,\n documentation: '/userguide/form-building/form-components#select',\n schema: SelectComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return SelectComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n const valueComp = Object.assign(Object.assign({}, classComp), { type: 'select' });\n if ((0, utils_1.isSelectResourceWithObjectValue)(classComp)) {\n valueComp.reference = false;\n valueComp.onSetItems = `\n var templateKeys = utils.getItemTemplateKeys(component.template) || [];\n items = _.map(items || [], i => {\n var item = {};\n _.each(templateKeys, k => _.set(item, k, _.get(i, k)));\n return item;\n })\n `;\n }\n return valueComp;\n } });\n }\n static savedValueTypes(schema) {\n const { boolean, string, number, object, array } = utils_1.componentValueTypes;\n const { dataType, reference } = schema;\n const types = (0, utils_1.getComponentSavedTypes)(schema);\n if (types) {\n return types;\n }\n if (reference) {\n return [object];\n }\n if (dataType === 'object') {\n return [object, array];\n }\n if (utils_1.componentValueTypes[dataType]) {\n return [utils_1.componentValueTypes[dataType]];\n }\n return [boolean, string, number, object, array];\n }\n init() {\n super.init();\n this.templateData = {};\n // Trigger an update.\n let updateArgs = [];\n const triggerUpdate = lodash_1.default.debounce((...args) => {\n updateArgs = [];\n return this.updateItems.apply(this, args);\n }, 100);\n this.triggerUpdate = (...args) => {\n // Make sure we always resolve the previous promise before reassign it\n if (typeof this.itemsLoadedResolve === 'function') {\n this.itemsLoadedResolve();\n }\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n if (args.length) {\n updateArgs = args;\n }\n return triggerUpdate(...updateArgs);\n };\n // Keep track of the select options.\n this.selectOptions = [];\n if (this.itemsFromUrl) {\n this.isFromSearch = false;\n this.searchServerCount = null;\n this.defaultServerCount = null;\n this.isScrollLoading = false;\n this.searchDownloadedResources = [];\n this.defaultDownloadedResources = [];\n }\n // If this component has been activated.//\n this.activated = false;\n this.itemsLoaded = new Promise((resolve) => {\n this.itemsLoadedResolve = resolve;\n });\n this.shouldPositionDropdown = this.hasDataGridAncestor();\n if (this.isHtmlRenderMode()) {\n this.activate();\n }\n // Get the template keys for this select component.\n this.getTemplateKeys();\n }\n get dataReady() {\n // If the root submission has been set, and we are still not attached, then assume\n // that our data is ready.\n if (this.root &&\n this.root.submissionSet &&\n !this.attached) {\n return Promise.resolve();\n }\n return this.itemsLoaded;\n }\n get defaultSchema() {\n return SelectComponent.schema();\n }\n get emptyValue() {\n if (this.component.multiple) {\n return [];\n }\n // if select has JSON data source type, we are defining if empty value would be an object or a string by checking JSON's first item\n if (this.component.dataSrc === 'json' && this.component.data.json) {\n const firstItem = this.component.data.json[0];\n let firstValue;\n if (this.valueProperty) {\n firstValue = lodash_1.default.get(firstItem, this.valueProperty);\n }\n else {\n firstValue = firstItem;\n }\n if (firstValue && typeof firstValue === 'string') {\n return '';\n }\n else {\n return {};\n }\n }\n if (this.valueProperty) {\n return '';\n }\n return {};\n }\n get valueProperty() {\n if (this.component.valueProperty) {\n return this.component.valueProperty;\n }\n // Force values datasource to use values without actually setting it on the component settings.\n if (this.component.dataSrc === 'values') {\n return 'value';\n }\n return '';\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.type = 'select';\n info.changeEvent = 'change';\n return info;\n }\n get isSelectResource() {\n return this.component.dataSrc === 'resource';\n }\n get itemsFromUrl() {\n return this.isSelectResource || this.isSelectURL;\n }\n get isInfiniteScrollProvided() {\n return this.itemsFromUrl;\n }\n get shouldDisabled() {\n return super.shouldDisabled || this.parentDisabled;\n }\n get shouldInitialLoad() {\n if (this.component.widget === 'html5' &&\n this.isEntireObjectDisplay() &&\n this.component.searchField &&\n this.dataValue) {\n return false;\n }\n return super.shouldLoad;\n }\n get selectMetadata() {\n return super.selectData;\n }\n get selectData() {\n return this.selectMetadata || this.component.selectData;\n }\n isEntireObjectDisplay() {\n return this.component.dataSrc === 'resource' && this.valueProperty === 'data';\n }\n selectValueAndLabel(data) {\n const value = this.getOptionValue((this.isEntireObjectDisplay() && !this.itemValue(data)) ? data : this.itemValue(data));\n const readOnlyResourceLabelData = this.options.readOnly && (this.component.dataSrc === 'resource' || this.component.dataSrc === 'url') && this.selectData;\n return {\n value,\n label: this.itemTemplate((this.isEntireObjectDisplay() && !lodash_1.default.isObject(data.data)) ? { data: data } : readOnlyResourceLabelData || data, value)\n };\n }\n itemTemplate(data, value) {\n if (!lodash_1.default.isNumber(data) && lodash_1.default.isEmpty(data)) {\n return '';\n }\n // If they wish to show the value in read only mode, then just return the itemValue here.\n if (this.options.readOnly && this.component.readOnlyValue) {\n return this.itemValue(data);\n }\n // Perform a fast interpretation if we should not use the template.\n if (data && !this.component.template) {\n const itemLabel = data.label || data;\n const value = (typeof itemLabel === 'string') ? this.t(itemLabel, { _userInput: true }) : itemLabel;\n return this.sanitize(value, this.shouldSanitizeValue);\n }\n if (this.component.multiple && lodash_1.default.isArray(this.dataValue) ? this.dataValue.find((val) => value === val) : (this.dataValue === value)) {\n const selectData = this.selectData;\n if (selectData) {\n const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;\n if (!this.templateData || !this.templateData[templateValue]) {\n this.getOptionTemplate(data, value);\n }\n if (this.component.multiple) {\n if (selectData[templateValue]) {\n data = selectData[templateValue];\n }\n }\n else {\n data = selectData;\n }\n }\n }\n if (typeof data === 'string' || typeof data === 'number') {\n return this.sanitize(this.t(data, { _userInput: true }), this.shouldSanitizeValue);\n }\n if (Array.isArray(data)) {\n return data.map((val) => {\n if (typeof val === 'string' || typeof val === 'number') {\n return this.sanitize(this.t(val, { _userInput: true }), this.shouldSanitizeValue);\n }\n return val;\n });\n }\n if (data.data) {\n // checking additional fields in the template for the selected Entire Object option\n const hasNestedFields = /item\\.data\\.\\w*/g.test(this.component.template);\n data.data = this.isEntireObjectDisplay() && lodash_1.default.isObject(data.data) && !hasNestedFields\n ? JSON.stringify(data.data)\n : data.data;\n }\n return super.itemTemplate(data, value);\n }\n /**\n * Adds an option to the select dropdown.\n *\n * @param value\n * @param label\n */\n addOption(value, label, attrs = {}, id = (0, utils_1.getRandomComponentId)()) {\n if (lodash_1.default.isNil(label))\n return;\n const idPath = this.component.idPath\n ? this.component.idPath.split('.').reduceRight((obj, key) => ({ [key]: obj }), id)\n : {};\n const option = Object.assign({ value: this.getOptionValue(value), label }, idPath);\n const skipOption = this.component.uniqueOptions\n ? !!this.selectOptions.find((selectOption) => lodash_1.default.isEqual(selectOption.value, option.value))\n : false;\n if (skipOption) {\n return;\n }\n if (value) {\n this.selectOptions.push(option);\n }\n if (this.refs.selectContainer && (this.component.widget === 'html5')) {\n // Replace an empty Object value to an empty String.\n if (option.value && lodash_1.default.isObject(option.value) && lodash_1.default.isEmpty(option.value)) {\n option.value = '';\n }\n // Add element to option so we can reference it later.\n const div = document.createElement('div');\n div.innerHTML = this.sanitize(this.renderTemplate('selectOption', {\n selected: lodash_1.default.isEqual(this.getOptionValue(this.dataValue), option.value),\n option,\n attrs,\n id,\n useId: (this.valueProperty === '' || this.isEntireObjectDisplay()) && lodash_1.default.isObject(value) && id,\n }), this.shouldSanitizeValue).trim();\n option.element = div.firstChild;\n this.refs.selectContainer.appendChild(option.element);\n }\n }\n addValueOptions(items) {\n items = items || [];\n let added = false;\n let data = this.dataValue;\n // preset submission value with value property before request.\n if (this.options.pdf && !items.length && this.component.dataSrc === 'url' && this.valueProperty) {\n data = Array.isArray(data)\n ? data.map(item => lodash_1.default.set({}, this.valueProperty, item))\n : lodash_1.default.set({}, this.valueProperty, data);\n }\n if (!this.selectOptions.length) {\n // Add the currently selected choices if they don't already exist.\n const currentChoices = Array.isArray(data) && this.component.multiple ? data : [data];\n added = this.addCurrentChoices(currentChoices, items);\n if (!added && !this.component.multiple) {\n this.addPlaceholder();\n }\n }\n return added;\n }\n disableInfiniteScroll() {\n if (!this.downloadedResources) {\n return;\n }\n this.downloadedResources.serverCount = this.downloadedResources.length;\n this.serverCount = this.downloadedResources.length;\n }\n /* eslint-disable max-statements */\n setItems(items, fromSearch) {\n var _a, _b;\n this.selectItems = items;\n // If the items is a string, then parse as JSON.\n if (typeof items == 'string') {\n try {\n items = JSON.parse(items);\n }\n catch (err) {\n console.warn(err.message);\n items = [];\n }\n }\n // Allow js processing (needed for form builder)\n if (this.component.onSetItems) {\n const newItems = typeof this.component.onSetItems === 'function'\n ? this.component.onSetItems(this, items)\n : this.evaluate(this.component.onSetItems, { items: items }, 'items');\n if (newItems) {\n items = newItems;\n }\n }\n if (!this.choices && this.refs.selectContainer) {\n this.empty(this.refs.selectContainer);\n }\n // If they provided select values, then we need to get them instead.\n if (this.component.selectValues) {\n items = lodash_1.default.get(items, this.component.selectValues, items) || [];\n }\n let areItemsEqual;\n if (this.itemsFromUrl) {\n areItemsEqual = this.isSelectURL ? lodash_1.default.isEqual(items, this.downloadedResources) : false;\n const areItemsEnded = this.component.limit > items.length;\n const areItemsDownloaded = areItemsEqual\n && this.downloadedResources\n && this.downloadedResources.length === items.length;\n if (areItemsEnded) {\n this.disableInfiniteScroll();\n }\n else if (areItemsDownloaded) {\n this.selectOptions = [];\n }\n else {\n this.serverCount = items.serverCount;\n }\n }\n if (this.isScrollLoading && items) {\n if (!areItemsEqual) {\n this.downloadedResources = this.downloadedResources\n ? this.downloadedResources.concat(items)\n : items;\n }\n this.downloadedResources.serverCount = items.serverCount || this.downloadedResources.serverCount;\n }\n else {\n this.downloadedResources = items || [];\n this.selectOptions = [];\n // If there is new select option with same id as already selected, set the new one\n if (!lodash_1.default.isEmpty(this.dataValue) && this.component.idPath) {\n const selectedOptionId = lodash_1.default.get(this.dataValue, this.component.idPath, null);\n const newOptionWithSameId = !lodash_1.default.isNil(selectedOptionId) && items.find(item => {\n const itemId = lodash_1.default.get(item, this.component.idPath);\n return itemId === selectedOptionId;\n });\n if (newOptionWithSameId) {\n this.setValue(newOptionWithSameId);\n }\n }\n }\n // Add the value options.\n if (!fromSearch) {\n this.addValueOptions(items);\n }\n if (this.component.widget === 'html5' && !this.component.placeholder) {\n this.addOption(null, '');\n }\n // Iterate through each of the items.\n lodash_1.default.each(items, (item, index) => {\n // preventing references of the components inside the form to the parent form when building forms\n if (this.root && this.root.options.editForm && this.root.options.editForm._id && this.root.options.editForm._id === item._id)\n return;\n const itemValueAndLabel = this.selectValueAndLabel(item);\n this.addOption(itemValueAndLabel.value, itemValueAndLabel.label, {}, lodash_1.default.get(item, this.component.idPath, String(index)));\n });\n if (this.choices) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n else if (this.loading) {\n // Re-attach select input.\n // this.appendTo(this.refs.input[0], this.selectContainer);\n }\n // We are no longer loading.\n this.isScrollLoading = false;\n this.loading = false;\n const searching = fromSearch && ((_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.input) === null || _b === void 0 ? void 0 : _b.isFocussed);\n if (!searching) {\n // If a value is provided, then select it.\n if (!this.isEmpty() || this.isRemoveButtonPressed) {\n this.setValue(this.dataValue, {\n noUpdateEvent: true\n });\n }\n else if (this.shouldAddDefaultValue && !this.options.readOnly) {\n // If a default value is provided then select it.\n const defaultValue = this.defaultValue;\n if (!this.isEmpty(defaultValue)) {\n this.setValue(defaultValue);\n }\n }\n }\n // Say we are done loading the items.\n this.itemsLoadedResolve();\n }\n getSingleItemValueForHTMLMode(data) {\n var _a;\n const option = (_a = this.selectOptions) === null || _a === void 0 ? void 0 : _a.find(({ value }) => lodash_1.default.isEqual(value, data));\n if (option) {\n return option.label || data;\n }\n return data;\n }\n itemValueForHTMLMode(value) {\n if (!this.isHtmlRenderMode()) {\n return super.itemValueForHTMLMode(value);\n }\n if (Array.isArray(value)) {\n const values = value.map(item => Array.isArray(item)\n ? this.itemValueForHTMLMode(item)\n : this.getSingleItemValueForHTMLMode(item));\n return values.join(', ');\n }\n return this.getSingleItemValueForHTMLMode(value);\n }\n /* eslint-enable max-statements */\n get defaultValue() {\n let defaultValue = super.defaultValue;\n if (!defaultValue && (this.component.defaultValue === false || this.component.defaultValue === 0)) {\n defaultValue = this.component.defaultValue;\n }\n return defaultValue;\n }\n get loadingError() {\n return !this.component.refreshOn && !this.component.refreshOnBlur && this.networkError;\n }\n loadItems(url, search, headers, options, method, body) {\n options = options || {};\n // See if we should load items or not.\n if (!this.shouldLoad || (!this.itemsFromUrl && this.options.readOnly)) {\n this.isScrollLoading = false;\n this.loading = false;\n this.itemsLoadedResolve();\n return;\n }\n // See if they have not met the minimum search requirements.\n const minSearch = parseInt(this.component.minSearch, 10);\n if (this.component.searchField &&\n (minSearch > 0) &&\n (!search || (search.length < minSearch))) {\n // Set empty items.\n return this.setItems([]);\n }\n // Ensure we have a method and remove any body if method is get\n method = method || 'GET';\n if (method.toUpperCase() === 'GET') {\n body = null;\n }\n const limit = this.component.limit || 100;\n const skip = this.isScrollLoading ? this.selectOptions.length : 0;\n const query = this.component.disableLimit ? {} : {\n limit,\n skip,\n };\n // Allow for url interpolation.\n url = this.interpolate(url, {\n formioBase: Formio_1.Formio.getBaseUrl(),\n search,\n limit,\n skip,\n page: Math.abs(Math.floor(skip / limit))\n });\n // Add search capability.\n if (this.component.searchField && search) {\n const searchValue = Array.isArray(search)\n ? search.join(',')\n : typeof search === 'object'\n ? JSON.stringify(search)\n : search;\n query[this.component.searchField] = this.component.searchField.endsWith('__regex')\n ? lodash_1.default.escapeRegExp(searchValue)\n : searchValue;\n }\n // If they wish to return only some fields.\n if (this.component.selectFields) {\n query.select = this.component.selectFields;\n }\n // Add sort capability\n if (this.component.sort) {\n query.sort = this.component.sort;\n }\n if (!lodash_1.default.isEmpty(query)) {\n // Add the query string.\n url += (!url.includes('?') ? '?' : '&') + Formio_1.Formio.serialize(query, (item) => this.interpolate(item));\n }\n // Add filter capability\n if (this.component.filter) {\n url += (!url.includes('?') ? '?' : '&') + this.interpolate(this.component.filter);\n }\n // Set ignoreCache if it is\n options.ignoreCache = this.component.ignoreCache;\n // Make the request.\n options.header = headers;\n this.loading = true;\n Formio_1.Formio.makeRequest(this.options.formio, 'select', url, method, body, options)\n .then((response) => {\n this.loading = false;\n this.setItems(response, !!search);\n })\n .catch((err) => {\n if (this.itemsFromUrl) {\n this.setItems([]);\n this.disableInfiniteScroll();\n }\n this.isScrollLoading = false;\n this.handleLoadingError(err);\n });\n }\n handleLoadingError(err) {\n this.loading = false;\n if (err.networkError) {\n this.networkError = true;\n }\n this.itemsLoadedResolve();\n this.emit('componentError', {\n component: this.component,\n message: err.toString(),\n });\n console.warn(`Unable to load resources for ${this.key}`);\n }\n /**\n * Get the request headers for this select dropdown.\n */\n get requestHeaders() {\n // Create the headers object.\n const headers = new Formio_1.Formio.Headers();\n // Add custom headers to the url.\n if (this.component.data && this.component.data.headers) {\n try {\n lodash_1.default.each(this.component.data.headers, (header) => {\n if (header.key) {\n headers.set(header.key, this.interpolate(header.value));\n }\n });\n }\n catch (err) {\n console.warn(err.message);\n }\n }\n return headers;\n }\n getCustomItems() {\n const customItems = this.evaluate(this.component.data.custom, {\n values: []\n }, 'values');\n this.asyncValues = (0, utils_1.isPromise)(customItems);\n return customItems;\n }\n asyncCustomValues() {\n if (!lodash_1.default.isBoolean(this.asyncValues)) {\n this.getCustomItems();\n }\n return this.asyncValues;\n }\n updateCustomItems(forceUpdate) {\n if (this.asyncCustomValues()) {\n if (!forceUpdate && !this.active) {\n this.itemsLoadedResolve();\n return;\n }\n this.loading = true;\n this.getCustomItems()\n .then(items => {\n this.loading = false;\n this.setItems(items || []);\n })\n .catch(err => {\n this.handleLoadingError(err);\n });\n }\n else {\n this.setItems(this.getCustomItems() || []);\n }\n }\n isEmpty(value = this.dataValue) {\n return super.isEmpty(value) || value === undefined;\n }\n refresh(value, { instance }) {\n if (this.component.clearOnRefresh && (instance && !instance.pristine)) {\n this.setValue(this.emptyValue);\n }\n this.updateItems(null, true);\n }\n get additionalResourcesAvailable() {\n return lodash_1.default.isNil(this.serverCount) || (this.serverCount > this.downloadedResources.length);\n }\n get serverCount() {\n if (this.isFromSearch) {\n return this.searchServerCount;\n }\n return this.defaultServerCount;\n }\n set serverCount(value) {\n if (this.isFromSearch) {\n this.searchServerCount = value;\n }\n else {\n this.defaultServerCount = value;\n }\n }\n get downloadedResources() {\n if (this.isFromSearch) {\n return this.searchDownloadedResources;\n }\n return this.defaultDownloadedResources;\n }\n set downloadedResources(value) {\n if (this.isFromSearch) {\n this.searchDownloadedResources = value;\n }\n else {\n this.defaultDownloadedResources = value;\n }\n }\n addPlaceholder() {\n if (!this.component.placeholder) {\n return;\n }\n this.addOption('', this.component.placeholder, { placeholder: true });\n }\n /**\n * Activate this select control.\n */\n activate() {\n if (this.loading || !this.active) {\n this.setLoadingItem();\n }\n if (this.active) {\n return;\n }\n this.activated = true;\n this.triggerUpdate();\n }\n setLoadingItem(addToCurrentList = false) {\n if (this.choices) {\n if (addToCurrentList) {\n this.choices.setChoices([{\n value: `${this.id}-loading`,\n label: 'Loading...',\n disabled: true,\n }], 'value', 'label');\n }\n else {\n this.choices.setChoices([{\n value: '',\n label: `<i class=\"${this.iconClass('refresh')}\" style=\"font-size:1.3em;\"></i>`,\n disabled: true,\n }], 'value', 'label', true);\n }\n }\n else if (this.component.dataSrc === 'url' || this.component.dataSrc === 'resource') {\n this.addOption('', this.t('loading...'));\n }\n }\n get active() {\n return !this.component.lazyLoad || this.activated;\n }\n render() {\n const info = this.inputInfo;\n info.attr = info.attr || {};\n info.multiple = this.component.multiple;\n return super.render(this.wrapElement(this.renderTemplate('select', {\n input: info,\n selectOptions: '',\n index: null,\n })));\n }\n wrapElement(element) {\n return this.component.addResource && !this.options.readOnly\n ? (this.renderTemplate('resourceAdd', {\n element\n }))\n : element;\n }\n choicesOptions() {\n const useSearch = this.component.hasOwnProperty('searchEnabled') ? this.component.searchEnabled : true;\n const placeholderValue = this.t(this.component.placeholder, { _userInput: true });\n let customOptions = this.component.customOptions || {};\n if (typeof customOptions == 'string') {\n try {\n customOptions = JSON.parse(customOptions);\n }\n catch (err) {\n console.warn(err.message);\n customOptions = {};\n }\n }\n const commonFuseOptions = {\n maxPatternLength: 1000,\n distance: 1000,\n };\n return Object.assign({ removeItemButton: this.component.disabled ? false : lodash_1.default.get(this.component, 'removeItemButton', true), itemSelectText: '', classNames: {\n containerOuter: 'choices form-group formio-choices',\n containerInner: this.transform('class', 'form-control ui fluid selection dropdown')\n }, addItemText: false, allowHTML: true, placeholder: !!this.component.placeholder, placeholderValue: placeholderValue, noResultsText: this.t('No results found'), noChoicesText: this.t('No choices to choose from'), searchPlaceholderValue: this.t('Type to search'), shouldSort: false, position: (this.component.dropdown || 'auto'), searchEnabled: useSearch, searchChoices: !this.component.searchField, searchFields: lodash_1.default.get(this, 'component.searchFields', ['label']), shadowRoot: this.root ? this.root.shadowRoot : null, fuseOptions: this.component.useExactSearch\n ? Object.assign({ tokenize: true, matchAllTokens: true }, commonFuseOptions) : Object.assign({}, lodash_1.default.get(this, 'component.fuseOptions', {}), Object.assign({ include: 'score', threshold: lodash_1.default.get(this, 'component.selectThreshold', 0.3) }, commonFuseOptions)), valueComparer: lodash_1.default.isEqual, resetScrollPosition: false }, customOptions);\n }\n /* eslint-disable max-statements */\n attach(element) {\n var _a, _b, _c;\n const superAttach = super.attach(element);\n this.loadRefs(element, {\n selectContainer: 'single',\n addResource: 'single',\n autocompleteInput: 'single'\n });\n //enable autocomplete for select\n const autocompleteInput = this.refs.autocompleteInput;\n if (autocompleteInput) {\n this.addEventListener(autocompleteInput, 'change', (event) => {\n this.setValue(event.target.value);\n });\n }\n const input = this.refs.selectContainer;\n if (!input) {\n return;\n }\n this.addEventListener(input, this.inputInfo.changeEvent, () => this.updateValue(null, {\n modified: true\n }));\n this.attachRefreshOnBlur();\n if (this.component.widget === 'html5') {\n this.addFocusBlurEvents(input);\n this.triggerUpdate(null, true);\n if (this.visible) {\n this.setItems(this.selectItems || []);\n }\n this.focusableElement = input;\n if (this.component.dataSrc === 'custom') {\n this.addEventListener(input, 'focus', () => this.updateCustomItems());\n }\n this.addEventListener(input, 'keydown', (event) => {\n const { key } = event;\n if (['Backspace', 'Delete'].includes(key)) {\n this.setValue(this.emptyValue);\n }\n });\n return;\n }\n const tabIndex = input.tabIndex;\n this.addPlaceholder();\n if (this.i18next) {\n input.setAttribute('dir', this.i18next.dir());\n }\n if ((_c = (_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.containerOuter) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.parentNode) {\n this.choices.destroy();\n }\n const choicesOptions = this.choicesOptions();\n if (ChoicesWrapper_1.default) {\n this.choices = new ChoicesWrapper_1.default(input, choicesOptions);\n if (this.selectOptions && this.selectOptions.length) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n if (this.component.multiple) {\n this.focusableElement = this.choices.input.element;\n }\n else {\n this.focusableElement = this.choices.containerInner.element;\n this.choices.containerOuter.element.setAttribute('tabIndex', '-1');\n this.addEventListener(this.choices.containerOuter.element, 'focus', () => this.focusableElement.focus());\n }\n Input_1.default.prototype.addFocusBlurEvents.call(this, this.focusableElement);\n if (this.itemsFromUrl && !this.component.noRefreshOnScroll) {\n this.scrollList = this.choices.choiceList.element;\n this.addEventListener(this.scrollList, 'scroll', () => this.onScroll());\n }\n if (choicesOptions.removeItemButton) {\n this.addEventListener(input, 'removeItem', () => {\n this.isRemoveButtonPressed = true;\n });\n }\n }\n if (window && this.choices && this.shouldPositionDropdown) {\n this.addEventListener(window.document, 'scroll', () => {\n this.positionDropdown(true);\n }, false, true);\n }\n this.focusableElement.setAttribute('tabIndex', tabIndex);\n // If a search field is provided, then add an event listener to update items on search.\n if (this.component.searchField) {\n // Make sure to clear the search when no value is provided.\n if (this.choices && this.choices.input && this.choices.input.element) {\n this.addEventListener(this.choices.input.element, 'input', (event) => {\n this.isFromSearch = !!event.target.value;\n if (!event.target.value) {\n this.triggerUpdate();\n }\n else {\n this.serverCount = null;\n this.downloadedResources = [];\n }\n });\n }\n this.addEventListener(input, 'choice', () => {\n if (this.component.multiple && this.component.dataSrc === 'resource' && this.isFromSearch) {\n this.triggerUpdate();\n }\n this.isFromSearch = false;\n });\n // avoid spamming the resource/url endpoint when we have server side filtering enabled.\n const debounceTimeout = this.component.searchField && (this.isSelectResource || this.isSelectURL) ?\n (this.component.searchDebounce === 0 ? 0 : this.component.searchDebounce || this.defaultSchema.searchDebounce) * 1000\n : 0;\n const updateComponent = (evt) => {\n this.triggerUpdate(evt.detail.value);\n };\n this.addEventListener(input, 'search', lodash_1.default.debounce((e) => {\n updateComponent(e);\n this.positionDropdown();\n }, debounceTimeout));\n this.addEventListener(input, 'stopSearch', () => this.triggerUpdate());\n this.addEventListener(input, 'hideDropdown', () => {\n if (this.choices && this.choices.input && this.choices.input.element) {\n this.choices.input.element.value = '';\n }\n this.updateItems(null, true);\n });\n }\n this.addEventListener(input, 'showDropdown', () => {\n this.update();\n this.positionDropdown();\n });\n if (this.shouldPositionDropdown) {\n this.addEventListener(input, 'highlightChoice', () => {\n this.positionDropdown();\n });\n }\n if (this.choices && choicesOptions.placeholderValue && this.choices._isSelectOneElement) {\n this.addPlaceholderItem(choicesOptions.placeholderValue);\n this.addEventListener(input, 'removeItem', () => {\n this.addPlaceholderItem(choicesOptions.placeholderValue);\n });\n }\n // Add value options.\n this.addValueOptions();\n this.setChoicesValue(this.dataValue);\n if (this.isSelectResource && this.refs.addResource) {\n this.addEventListener(this.refs.addResource, 'click', (event) => {\n event.preventDefault();\n const formioForm = this.ce('div');\n const dialog = this.createModal(formioForm);\n const projectUrl = lodash_1.default.get(this.root, 'formio.projectUrl', Formio_1.Formio.getProjectUrl());\n const formUrl = `${projectUrl}/form/${this.component.data.resource}`;\n new Form_1.default(formioForm, formUrl, {}).ready\n .then((form) => {\n form.on('submit', (submission) => {\n // If valueProperty is set, replace the submission with the corresponding value\n let value = this.valueProperty ? lodash_1.default.get(submission, this.valueProperty) : submission;\n if (this.component.multiple) {\n value = [...this.dataValue, value];\n }\n this.setValue(value);\n this.triggerUpdate();\n dialog.close();\n });\n });\n });\n }\n // Force the disabled state with getters and setters.\n this.disabled = this.shouldDisabled;\n this.triggerUpdate();\n return superAttach;\n }\n setDropdownPosition() {\n var _a, _b, _c, _d;\n const dropdown = (_b = (_a = this.choices) === null || _a === void 0 ? void 0 : _a.dropdown) === null || _b === void 0 ? void 0 : _b.element;\n const container = (_d = (_c = this.choices) === null || _c === void 0 ? void 0 : _c.containerOuter) === null || _d === void 0 ? void 0 : _d.element;\n if (!dropdown || !container) {\n return;\n }\n const containerPosition = container.getBoundingClientRect();\n const isFlipped = container.classList.contains('is-flipped');\n lodash_1.default.assign(dropdown.style, {\n top: `${isFlipped ? containerPosition.top - dropdown.offsetHeight : containerPosition.top + containerPosition.height}px`,\n left: `${containerPosition.left}px`,\n width: `${containerPosition.width}px`,\n position: 'fixed',\n bottom: 'unset',\n right: 'unset',\n });\n }\n hasDataGridAncestor(comp) {\n comp = comp || this;\n if (comp.inDataGrid || comp.type === 'datagrid') {\n return true;\n }\n else if (comp.parent) {\n return this.hasDataGridAncestor(comp.parent);\n }\n else {\n return false;\n }\n }\n positionDropdown(scroll) {\n var _a;\n if (!this.shouldPositionDropdown || !this.choices || (!((_a = this.choices.dropdown) === null || _a === void 0 ? void 0 : _a.isActive) && scroll)) {\n return;\n }\n this.setDropdownPosition();\n this.itemsLoaded.then(() => {\n this.setDropdownPosition();\n });\n }\n get isLoadingAvailable() {\n return !this.isScrollLoading && this.additionalResourcesAvailable;\n }\n onScroll() {\n if (this.isLoadingAvailable) {\n this.isScrollLoading = true;\n this.setLoadingItem(true);\n this.triggerUpdate(this.choices.input.element.value);\n }\n }\n attachRefreshOnBlur() {\n if (this.component.refreshOnBlur) {\n this.on('blur', (instance) => {\n this.checkRefreshOn([{ instance, value: instance.dataValue }], { fromBlur: true });\n });\n }\n }\n addPlaceholderItem(placeholderValue) {\n const items = this.choices._store.activeItems;\n if (!items.length) {\n this.choices._addItem({\n value: '',\n label: placeholderValue,\n choiceId: 0,\n groupId: -1,\n customProperties: null,\n placeholder: true,\n keyCode: null\n });\n }\n }\n /* eslint-enable max-statements */\n update() {\n if (this.component.dataSrc === 'custom') {\n this.updateCustomItems();\n }\n // Activate the control.\n this.activate();\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.choices) {\n return;\n }\n if (disabled) {\n this.setDisabled(this.choices.containerInner.element, true);\n this.focusableElement.removeAttribute('tabIndex');\n this.choices.disable();\n }\n else {\n this.setDisabled(this.choices.containerInner.element, false);\n this.focusableElement.setAttribute('tabIndex', this.component.tabindex || 0);\n this.choices.enable();\n }\n }\n get disabled() {\n return super.disabled;\n }\n set visible(value) {\n // If we go from hidden to visible, trigger a refresh.\n if (value && (!this._visible !== !value)) {\n this.triggerUpdate();\n }\n super.visible = value;\n }\n get visible() {\n return super.visible;\n }\n /**\n * @param {*} value\n * @param {Array} items\n */\n addCurrentChoices(values, items, keyValue) {\n if (!values) {\n return false;\n }\n const notFoundValuesToAdd = [];\n const added = values.reduce((defaultAdded, value) => {\n if (!value || lodash_1.default.isEmpty(value)) {\n return defaultAdded;\n }\n let found = false;\n // Make sure that `items` and `this.selectOptions` points\n // to the same reference. Because `this.selectOptions` is\n // internal property and all items are populated by\n // `this.addOption` method, we assume that items has\n // 'label' and 'value' properties. This assumption allows\n // us to read correct value from the item.\n const isSelectOptions = items === this.selectOptions;\n if (items && items.length) {\n lodash_1.default.each(items, (choice) => {\n if (choice._id && value._id && (choice._id === value._id)) {\n found = true;\n return false;\n }\n const itemValue = keyValue ? choice.value : this.itemValue(choice, isSelectOptions);\n found |= lodash_1.default.isEqual(itemValue, value);\n return found ? false : true;\n });\n }\n // Add the default option if no item is found.\n if (!found) {\n notFoundValuesToAdd.push(this.selectValueAndLabel(value));\n return true;\n }\n return found || defaultAdded;\n }, false);\n if (notFoundValuesToAdd.length) {\n if (this.choices) {\n this.choices.setChoices(notFoundValuesToAdd, 'value', 'label');\n }\n notFoundValuesToAdd.map(notFoundValue => {\n this.addOption(notFoundValue.value, notFoundValue.label);\n });\n }\n return added;\n }\n getValueAsString(data, options) {\n return (this.component.multiple && Array.isArray(data))\n ? data.map((v) => this.asString(v, options)).join(', ')\n : this.asString(data, options);\n }\n getValue() {\n // If the widget isn't active.\n if (this.viewOnly || this.loading\n || (!this.component.lazyLoad && !this.selectOptions.length)\n || !this.element) {\n return this.dataValue;\n }\n let value = this.emptyValue;\n if (this.choices) {\n value = this.choices.getValue(true);\n // Make sure we don't get the placeholder\n if (!this.component.multiple &&\n this.component.placeholder &&\n (value === this.t(this.component.placeholder, { _userInput: true }))) {\n value = this.emptyValue;\n }\n }\n else if (this.refs.selectContainer) {\n value = this.refs.selectContainer.value;\n if (this.valueProperty === '' || this.isEntireObjectDisplay()) {\n if (value === '') {\n return {};\n }\n const option = this.selectOptions[value] ||\n this.selectOptions.find(option => option.id === value);\n if (option && lodash_1.default.isObject(option.value)) {\n value = option.value;\n }\n }\n }\n else {\n value = this.dataValue;\n }\n // Choices will return undefined if nothing is selected. We really want '' to be empty.\n if (value === undefined || value === null) {\n value = '';\n }\n return value;\n }\n redraw() {\n const done = super.redraw();\n this.triggerUpdate();\n return done;\n }\n normalizeSingleValue(value) {\n if (lodash_1.default.isNil(value)) {\n return;\n }\n const valueIsObject = lodash_1.default.isObject(value);\n //check if value equals to default emptyValue\n if (valueIsObject && Object.keys(value).length === 0) {\n return value;\n }\n const dataType = this.component.dataType || 'auto';\n const normalize = {\n value,\n number() {\n const numberValue = Number(this.value);\n const isEquivalent = value.toString() === numberValue.toString();\n if (!Number.isNaN(numberValue) && Number.isFinite(numberValue) && value !== '' && isEquivalent) {\n this.value = numberValue;\n }\n return this;\n },\n boolean() {\n if (lodash_1.default.isString(this.value)\n && (this.value.toLowerCase() === 'true'\n || this.value.toLowerCase() === 'false')) {\n this.value = (this.value.toLowerCase() === 'true');\n }\n return this;\n },\n string() {\n this.value = String(this.value);\n return this;\n },\n object() {\n return this;\n },\n auto() {\n if (lodash_1.default.isObject(this.value)) {\n this.value = this.object().value;\n }\n else {\n this.value = this.string().number().boolean().value;\n }\n return this;\n }\n };\n try {\n return normalize[dataType]().value;\n }\n catch (err) {\n console.warn('Failed to normalize value', err);\n return value;\n }\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n if (this.component.multiple && Array.isArray(value)) {\n return value.map((singleValue) => this.normalizeSingleValue(singleValue));\n }\n return super.normalizeValue(this.normalizeSingleValue(value));\n }\n setMetadata(value) {\n var _a;\n if (lodash_1.default.isNil(value)) {\n return;\n }\n const valueIsObject = lodash_1.default.isObject(value);\n //check if value equals to default emptyValue\n if (valueIsObject && Object.keys(value).length === 0) {\n return value;\n }\n // Check to see if we need to save off the template data into our metadata.\n const templateValue = this.component.reference && (value === null || value === void 0 ? void 0 : value._id) ? value._id.toString() : value;\n const shouldSaveData = !valueIsObject || this.component.reference;\n if (templateValue && shouldSaveData && this.templateData && this.templateData[templateValue] && ((_a = this.root) === null || _a === void 0 ? void 0 : _a.submission)) {\n const submission = this.root.submission;\n if (!submission.metadata) {\n submission.metadata = {};\n }\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n let templateData = this.templateData[templateValue];\n if (this.component.multiple) {\n templateData = {};\n const dataValue = this.dataValue;\n if (dataValue && lodash_1.default.isArray(dataValue) && dataValue.length) {\n dataValue.forEach((dataValueItem) => {\n const dataValueItemValue = this.component.reference ? dataValueItem._id.toString() : dataValueItem;\n templateData[dataValueItemValue] = this.templateData[dataValueItemValue];\n });\n }\n templateData[value] = this.templateData[value];\n }\n lodash_1.default.set(submission.metadata.selectData, this.path, templateData);\n }\n }\n updateValue(value, flags) {\n const changed = super.updateValue(value, flags);\n if (changed || !this.selectMetadata) {\n if (this.component.multiple && Array.isArray(this.dataValue)) {\n this.dataValue.forEach(singleValue => this.setMetadata(singleValue));\n }\n else {\n this.setMetadata(this.dataValue);\n }\n }\n return changed;\n }\n setValue(value, flags = {}) {\n const previousValue = this.dataValue;\n const changed = this.updateValue(value, flags);\n if (this.component.widget === 'html5' && (lodash_1.default.isEqual(value, previousValue) || lodash_1.default.isEqual(previousValue, {}) && lodash_1.default.isEqual(flags, {})) && !flags.fromSubmission) {\n return false;\n }\n value = this.dataValue;\n const hasPreviousValue = !this.isEmpty(previousValue);\n const hasValue = !this.isEmpty(value);\n // Undo typing when searching to set the value.\n if (this.component.multiple && Array.isArray(value)) {\n value = value.map(value => {\n if (typeof value === 'boolean' || typeof value === 'number') {\n return value.toString();\n }\n return value;\n });\n }\n else {\n if (typeof value === 'boolean' || typeof value === 'number') {\n value = value.toString();\n }\n }\n if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {\n this.itemsLoaded.then(() => {\n this.redraw();\n });\n return changed;\n }\n // Do not set the value if we are loading... that will happen after it is done.\n if (this.loading) {\n return changed;\n }\n // Determine if we need to perform an initial lazyLoad api call if searchField is provided.\n if (this.isInitApiCallNeeded(hasValue)) {\n this.loading = true;\n this.lazyLoadInit = true;\n const searchProperty = this.component.searchField || this.component.valueProperty;\n this.triggerUpdate(lodash_1.default.get(value.data || value, searchProperty, value), true);\n return changed;\n }\n // Add the value options.\n this.itemsLoaded.then(() => {\n this.addValueOptions();\n this.setChoicesValue(value, hasPreviousValue, flags);\n });\n return changed;\n }\n isInitApiCallNeeded(hasValue) {\n return this.component.lazyLoad &&\n !this.lazyLoadInit &&\n !this.active &&\n !this.selectOptions.length &&\n hasValue &&\n this.shouldInitialLoad &&\n this.visible && (this.component.searchField || this.component.valueProperty);\n }\n setChoicesValue(value, hasPreviousValue, flags = {}) {\n const hasValue = !this.isEmpty(value) || flags.fromSubmission;\n hasPreviousValue = (hasPreviousValue === undefined) ? true : hasPreviousValue;\n if (this.choices) {\n // Now set the value.\n if (hasValue) {\n this.choices.removeActiveItems();\n // Add the currently selected choices if they don't already exist.\n const currentChoices = Array.isArray(value) && this.component.multiple ? value : [value];\n if (!this.addCurrentChoices(currentChoices, this.selectOptions, true)) {\n this.choices.setChoices(this.selectOptions, 'value', 'label', true);\n }\n this.choices.setChoiceByValue(currentChoices);\n }\n else if (hasPreviousValue || flags.resetValue) {\n this.choices.removeActiveItems();\n }\n }\n else {\n if (hasValue) {\n const values = Array.isArray(value) ? value : [value];\n if (!lodash_1.default.isEqual(this.dataValue, this.defaultValue) && this.selectOptions.length < 2\n || (this.selectData && flags.fromSubmission)) {\n const { value, label } = this.selectValueAndLabel(this.dataValue);\n this.addOption(value, label);\n }\n lodash_1.default.each(this.selectOptions, (selectOption) => {\n lodash_1.default.each(values, (val) => {\n if (selectOption.value === '') {\n selectOption.value = {};\n }\n if (lodash_1.default.isEqual(val, selectOption.value) && selectOption.element) {\n selectOption.element.selected = true;\n selectOption.element.setAttribute('selected', 'selected');\n return false;\n }\n });\n });\n }\n else {\n lodash_1.default.each(this.selectOptions, (selectOption) => {\n if (selectOption.element) {\n selectOption.element.selected = false;\n selectOption.element.removeAttribute('selected');\n }\n });\n }\n }\n }\n get itemsLoaded() {\n return this._itemsLoaded || Promise.resolve();\n }\n set itemsLoaded(promise) {\n this._itemsLoaded = promise;\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.getOptionsValues();\n if (values) {\n if (lodash_1.default.isObject(value)) {\n const compareComplexValues = (optionValue) => {\n const normalizedOptionValue = this.normalizeSingleValue(optionValue);\n if (!lodash_1.default.isObject(normalizedOptionValue)) {\n return false;\n }\n try {\n return (JSON.stringify(normalizedOptionValue) === JSON.stringify(value));\n }\n catch (err) {\n console.warn.error('Error while comparing items', err);\n return false;\n }\n };\n return values.findIndex((optionValue) => compareComplexValues(optionValue)) !== -1;\n }\n return values.findIndex((optionValue) => this.normalizeSingleValue(optionValue) === value) !== -1;\n }\n return false;\n }\n /**\n * Performs required transformations on the initial value to use in selectOptions\n * @param {*} value\n */\n getOptionValue(value) {\n return lodash_1.default.isObject(value) && this.isEntireObjectDisplay()\n ? this.normalizeSingleValue(value)\n : lodash_1.default.isObject(value) && (this.valueProperty || this.component.key !== 'resource')\n ? value\n : lodash_1.default.isObject(value) && !this.valueProperty\n ? this.interpolate(this.component.template, { item: value }).replace(/<\\/?[^>]+(>|$)/g, '')\n : lodash_1.default.isNull(value)\n ? this.emptyValue\n : String(this.normalizeSingleValue(value));\n }\n /**\n * If component has static values (values, json) or custom values, returns an array of them\n * @returns {Array<*>|undefined}\n */\n getOptionsValues() {\n let rawItems = [];\n switch (this.component.dataSrc) {\n case 'values':\n rawItems = this.component.data.values;\n break;\n case 'json':\n rawItems = this.component.data.json;\n break;\n case 'custom':\n rawItems = this.getCustomItems();\n break;\n }\n if (typeof rawItems === 'string') {\n try {\n rawItems = JSON.parse(rawItems);\n }\n catch (err) {\n console.warn(err.message);\n rawItems = [];\n }\n }\n if (!Array.isArray(rawItems)) {\n return;\n }\n return rawItems.map((item) => this.getOptionValue(this.itemValue(item)));\n }\n /**\n * Deletes the value of the component.\n */\n deleteValue() {\n this.setValue('', {\n noUpdateEvent: true\n });\n this.unset();\n }\n /**\n * Check if a component is eligible for multiple validation\n *\n * @return {boolean}\n */\n validateMultiple() {\n // Select component will contain one input when flagged as multiple.\n return false;\n }\n /**\n * Output this select dropdown as a string value.\n * @return {*}\n */\n isBooleanOrNumber(value) {\n return typeof value === 'number' || typeof value === 'boolean';\n }\n getNormalizedValues() {\n if (!this.component || !this.component.data || !this.component.data.values) {\n return;\n }\n return this.component.data.values.map(value => ({ label: value.label, value: String(this.normalizeSingleValue(value.value)) }));\n }\n asString(value, options = {}) {\n var _a;\n value = value !== null && value !== void 0 ? value : this.getValue();\n if (options.modalPreview && this.selectData) {\n const { label } = this.selectValueAndLabel(value);\n return label;\n }\n //need to convert values to strings to be able to compare values with available options that are strings\n const convertToString = (data, valueProperty) => {\n if (valueProperty) {\n if (Array.isArray(data)) {\n data.forEach((item) => item[valueProperty] = item[valueProperty].toString());\n }\n else {\n data[valueProperty] = data[valueProperty].toString();\n }\n return data;\n }\n if (this.isBooleanOrNumber(data)) {\n data = data.toString();\n }\n if (Array.isArray(data) && data.some(item => this.isBooleanOrNumber(item))) {\n data = data.map(item => {\n if (this.isBooleanOrNumber(item)) {\n item = item.toString();\n }\n });\n }\n return data;\n };\n value = convertToString(value);\n if (['values', 'custom'].includes(this.component.dataSrc) && !this.asyncCustomValues()) {\n const { items, valueProperty, } = this.component.dataSrc === 'values'\n ? {\n items: convertToString(this.getNormalizedValues(), 'value'),\n valueProperty: 'value',\n }\n : {\n items: convertToString(this.getCustomItems(), this.valueProperty),\n valueProperty: this.valueProperty,\n };\n const getFromValues = () => {\n const initialValue = lodash_1.default.find(items, [valueProperty, value]);\n const values = this.defaultSchema.data.values || [];\n return lodash_1.default.isEqual(initialValue, values[0]) ? '-' : initialValue;\n };\n value = (this.component.multiple && Array.isArray(value))\n ? lodash_1.default.filter(items, (item) => value.includes(item.value))\n : valueProperty\n ? (_a = getFromValues()) !== null && _a !== void 0 ? _a : { value, label: value }\n : value;\n }\n if (lodash_1.default.isString(value)) {\n return value;\n }\n const getTemplateValue = (v) => {\n const itemTemplate = this.itemTemplate(v);\n return options.csv && itemTemplate\n ? (0, utils_1.unescapeHTML)(itemTemplate)\n : itemTemplate;\n };\n if (Array.isArray(value)) {\n const items = [];\n value.forEach(item => items.push(getTemplateValue(item)));\n if (this.component.dataSrc === 'resource' && items.length > 0) {\n return items.join(', ');\n }\n else if (items.length > 0) {\n return items.join('<br />');\n }\n else {\n return '-';\n }\n }\n if (this.isEntireObjectDisplay() && lodash_1.default.isObject(value)) {\n return JSON.stringify(value);\n }\n return !lodash_1.default.isNil(value)\n ? getTemplateValue(value)\n : '-';\n }\n detach() {\n var _a, _b;\n this.off('blur');\n if (this.choices) {\n if ((_b = (_a = this.choices.containerOuter) === null || _a === void 0 ? void 0 : _a.element) === null || _b === void 0 ? void 0 : _b.parentNode) {\n this.choices.destroy();\n }\n this.choices = null;\n }\n super.detach();\n }\n focus() {\n if (this.focusableElement) {\n super.focus.call(this);\n this.focusableElement.focus();\n }\n }\n setErrorClasses(elements, dirty, hasError, hasMessages, element = this.element) {\n super.setErrorClasses(elements, dirty, hasError, hasMessages, element);\n if (this.choices) {\n super.setErrorClasses([this.choices.containerInner.element], dirty, hasError, hasMessages, element);\n }\n else {\n super.setErrorClasses([this.refs.selectContainer], dirty, hasError, hasMessages, element);\n }\n }\n}\nexports[\"default\"] = SelectComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/select/Select.js?");
7152
7162
 
7153
7163
  /***/ }),
7154
7164
 
@@ -7203,7 +7213,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
7203
7213
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7204
7214
 
7205
7215
  "use strict";
7206
- 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 utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Radio_1 = __importDefault(__webpack_require__(/*! ../radio/Radio */ \"./lib/cjs/components/radio/Radio.js\"));\nclass SelectBoxesComponent extends Radio_1.default {\n static schema(...extend) {\n return Radio_1.default.schema({\n type: 'selectboxes',\n label: 'Select Boxes',\n key: 'selectBoxes',\n inline: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Select Boxes',\n group: 'basic',\n icon: 'plus-square',\n weight: 60,\n documentation: '/userguide/form-building/form-components#select-box',\n schema: SelectBoxesComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return SelectBoxesComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: 'string',\n data: {\n custom: `values = ${classComp && classComp.values ? JSON.stringify(classComp.values) : []}`\n },\n };\n } });\n }\n static savedValueTypes(schema) {\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n constructor(...args) {\n super(...args);\n }\n init() {\n super.init();\n this.component.inputType = 'checkbox';\n }\n get defaultSchema() {\n return SelectBoxesComponent.schema();\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.attr.name += '[]';\n info.attr.type = 'checkbox';\n info.attr.class = 'form-check-input';\n return info;\n }\n get emptyValue() {\n return this.component.values.reduce((prev, value) => {\n if (value.value) {\n prev[value.value] = false;\n }\n return prev;\n }, {});\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (!lodash_1.default.isEmpty(this.component.defaultValue)) {\n defaultValue = this.component.defaultValue;\n }\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n /**\n * Only empty if the values are all false.\n *\n * @param value\n * @return {boolean}\n */\n isEmpty(value = this.dataValue) {\n let empty = true;\n for (const key in value) {\n if (value.hasOwnProperty(key) && value[key]) {\n empty = false;\n break;\n }\n }\n return empty;\n }\n getValue() {\n if (this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const value = {};\n lodash_1.default.each(this.refs.input, (input) => {\n value[input.value] = !!input.checked;\n });\n return value;\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n value = value || {};\n if (typeof value !== 'object') {\n if (typeof value === 'string') {\n value = {\n [value]: true\n };\n }\n else {\n value = {};\n }\n }\n if (Array.isArray(value)) {\n lodash_1.default.each(value, (val) => {\n value[val] = true;\n });\n }\n const checkedValues = lodash_1.default.keys(lodash_1.default.pickBy(value, (val) => val));\n if (this.isSelectURL && this.templateData && lodash_1.default.every(checkedValues, (val) => this.templateData[val])) {\n const submission = this.root.submission;\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n const selectData = [];\n checkedValues.forEach((value) => selectData.push(this.templateData[value]));\n lodash_1.default.set(submission.metadata.selectData, this.path, selectData);\n }\n return value;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (this.isHtmlRenderMode()) {\n if (changed) {\n this.redraw();\n }\n }\n else {\n lodash_1.default.each(this.refs.input, (input) => {\n if (lodash_1.default.isUndefined(value[input.value])) {\n value[input.value] = false;\n }\n input.checked = !!value[input.value];\n });\n }\n return changed;\n }\n getValueAsString(value) {\n if (!value) {\n return '';\n }\n if (this.isSelectURL) {\n return (0, lodash_1.default)(value).pickBy((val) => val).keys().join(', ');\n }\n return (0, lodash_1.default)(this.component.values || [])\n .filter((v) => value[v.value])\n .map('label')\n .join(', ');\n }\n setSelectedClasses() {\n if (this.refs.wrapper) {\n //add/remove selected option class\n const value = this.dataValue;\n const valuesKeys = Object.keys(value);\n this.refs.wrapper.forEach((wrapper, index) => {\n let key = valuesKeys[index];\n const input = this.refs.input[index];\n if ((input === null || input === void 0 ? void 0 : input.value.toString()) !== key) {\n key = valuesKeys.find((k) => (input === null || input === void 0 ? void 0 : input.value.toString()) === k);\n }\n const isChecked = value[key];\n if ((isChecked && key) || (this.isSelectURL && !this.shouldLoad && this.listData && lodash_1.default.findIndex(this.selectData, this.listData[index]) !== -1)) {\n //add class to container when selected\n this.addClass(wrapper, this.optionSelectedClass);\n //change \"checked\" attribute\n input.setAttribute('checked', 'true');\n }\n else if (!isChecked && key) {\n this.removeClass(wrapper, this.optionSelectedClass);\n input.removeAttribute('checked');\n }\n });\n }\n }\n setInputsDisabled(value, onlyUnchecked) {\n if (this.refs.input) {\n this.refs.input.forEach(item => {\n if (onlyUnchecked && !item.checked || !onlyUnchecked) {\n item.disabled = value;\n }\n });\n }\n }\n checkComponentValidity(data, dirty, rowData, options, errors = []) {\n const minCount = this.component.validate.minSelectedCount;\n const maxCount = this.component.validate.maxSelectedCount;\n if (!this.shouldSkipValidation(data, rowData, options)) {\n const isValid = this.isValid(data, dirty);\n if ((maxCount || minCount)) {\n const count = Object.keys(this.validationValue).reduce((total, key) => {\n if (this.validationValue[key]) {\n total++;\n }\n return total;\n }, 0);\n // Disable the rest of inputs if the max amount is already checked\n if (maxCount && count >= maxCount) {\n this.setInputsDisabled(true, true);\n }\n else if (maxCount && !this.shouldDisabled) {\n this.setInputsDisabled(false);\n }\n if (!isValid && maxCount && count > maxCount) {\n const message = this.t(this.component.maxSelectedCountMessage || 'You may only select up to {{maxCount}} items', { maxCount });\n this.errors.push({ message });\n this.setCustomValidity(message, dirty);\n return false;\n }\n else if (!isValid && minCount && count < minCount) {\n this.setInputsDisabled(false);\n const message = this.t(this.component.minSelectedCountMessage || 'You must select at least {{minCount}} items', { minCount });\n this.errors.push({ message });\n this.setCustomValidity(message, dirty);\n return false;\n }\n }\n }\n return super.checkComponentValidity(data, dirty, rowData, options, errors);\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.component.values;\n const availableValueKeys = (values || []).map(({ value: optionValue }) => optionValue);\n const valueKeys = Object.keys(value);\n return valueKeys.every((key) => availableValueKeys.includes(key));\n }\n}\nexports[\"default\"] = SelectBoxesComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/selectboxes/SelectBoxes.js?");
7216
+ 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 utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Radio_1 = __importDefault(__webpack_require__(/*! ../radio/Radio */ \"./lib/cjs/components/radio/Radio.js\"));\nclass SelectBoxesComponent extends Radio_1.default {\n static schema(...extend) {\n return Radio_1.default.schema({\n type: 'selectboxes',\n label: 'Select Boxes',\n key: 'selectBoxes',\n inline: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Select Boxes',\n group: 'basic',\n icon: 'plus-square',\n weight: 60,\n documentation: '/userguide/form-building/form-components#select-box',\n schema: SelectBoxesComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return SelectBoxesComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { valueComponent(classComp) {\n return {\n type: 'select',\n dataSrc: 'custom',\n valueProperty: 'value',\n dataType: 'string',\n data: {\n custom: `values = ${classComp && classComp.values ? JSON.stringify(classComp.values) : []}`\n },\n };\n } });\n }\n static savedValueTypes(schema) {\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.object];\n }\n constructor(...args) {\n super(...args);\n }\n init() {\n super.init();\n this.component.inputType = 'checkbox';\n }\n get defaultSchema() {\n return SelectBoxesComponent.schema();\n }\n get inputInfo() {\n const info = super.elementInfo();\n info.attr.name += '[]';\n info.attr.type = 'checkbox';\n info.attr.class = 'form-check-input';\n return info;\n }\n get emptyValue() {\n return this.component.values.reduce((prev, value) => {\n if (value.value) {\n prev[value.value] = false;\n }\n return prev;\n }, {});\n }\n get defaultValue() {\n let defaultValue = this.emptyValue;\n if (!lodash_1.default.isEmpty(this.component.defaultValue)) {\n defaultValue = this.component.defaultValue;\n }\n if (this.component.customDefaultValue && !this.options.preview) {\n defaultValue = this.evaluate(this.component.customDefaultValue, { value: '' }, 'value');\n }\n return defaultValue;\n }\n /**\n * Only empty if the values are all false.\n *\n * @param value\n * @return {boolean}\n */\n isEmpty(value = this.dataValue) {\n let empty = true;\n for (const key in value) {\n if (value.hasOwnProperty(key) && value[key]) {\n empty = false;\n break;\n }\n }\n return empty;\n }\n getValue() {\n if (this.viewOnly || !this.refs.input || !this.refs.input.length) {\n return this.dataValue;\n }\n const value = {};\n lodash_1.default.each(this.refs.input, (input) => {\n value[input.value] = !!input.checked;\n });\n return value;\n }\n /**\n * Normalize values coming into updateValue.\n *\n * @param value\n * @return {*}\n */\n normalizeValue(value) {\n value = value || {};\n if (typeof value !== 'object') {\n if (typeof value === 'string') {\n value = {\n [value]: true\n };\n }\n else {\n value = {};\n }\n }\n if (Array.isArray(value)) {\n lodash_1.default.each(value, (val) => {\n value[val] = true;\n });\n }\n const checkedValues = lodash_1.default.keys(lodash_1.default.pickBy(value, (val) => val));\n if (this.isSelectURL && this.templateData && lodash_1.default.every(checkedValues, (val) => this.templateData[val])) {\n const submission = this.root.submission;\n if (!submission.metadata.selectData) {\n submission.metadata.selectData = {};\n }\n const selectData = [];\n checkedValues.forEach((value) => selectData.push(this.templateData[value]));\n lodash_1.default.set(submission.metadata.selectData, this.path, selectData);\n }\n return value;\n }\n /**\n * Set the value of this component.\n *\n * @param value\n * @param flags\n */\n setValue(value, flags = {}) {\n const changed = this.updateValue(value, flags);\n value = this.dataValue;\n if (this.isHtmlRenderMode()) {\n if (changed) {\n this.redraw();\n }\n }\n else {\n lodash_1.default.each(this.refs.input, (input) => {\n if (lodash_1.default.isUndefined(value[input.value])) {\n value[input.value] = false;\n }\n input.checked = !!value[input.value];\n });\n }\n return changed;\n }\n getValueAsString(value, options = {}) {\n if (!value) {\n return '';\n }\n if (this.isSelectURL) {\n if (options.modalPreview && this.loadedOptions) {\n return this.loadedOptions.filter((option) => value[option.value]).map((option) => option.label).join(', ');\n }\n return (0, lodash_1.default)(value).pickBy((val) => val).keys().join(', ');\n }\n return (0, lodash_1.default)(this.component.values || [])\n .filter((v) => value[v.value])\n .map('label')\n .join(', ');\n }\n setSelectedClasses() {\n if (this.refs.wrapper) {\n //add/remove selected option class\n const value = this.dataValue;\n const valuesKeys = Object.keys(value);\n this.refs.wrapper.forEach((wrapper, index) => {\n let key = valuesKeys[index];\n const input = this.refs.input[index];\n if ((input === null || input === void 0 ? void 0 : input.value.toString()) !== key) {\n key = valuesKeys.find((k) => (input === null || input === void 0 ? void 0 : input.value.toString()) === k);\n }\n const isChecked = value[key];\n if ((isChecked && key) || (this.isSelectURL && !this.shouldLoad && this.listData && lodash_1.default.findIndex(this.selectData, this.listData[index]) !== -1)) {\n //add class to container when selected\n this.addClass(wrapper, this.optionSelectedClass);\n //change \"checked\" attribute\n input.setAttribute('checked', 'true');\n }\n else if (!isChecked && key) {\n this.removeClass(wrapper, this.optionSelectedClass);\n input.removeAttribute('checked');\n }\n });\n }\n }\n setInputsDisabled(value, onlyUnchecked) {\n if (this.refs.input) {\n this.refs.input.forEach(item => {\n if (onlyUnchecked && !item.checked || !onlyUnchecked) {\n item.disabled = value;\n }\n });\n }\n }\n checkComponentValidity(data, dirty, rowData, options, errors = []) {\n const minCount = this.component.validate.minSelectedCount;\n const maxCount = this.component.validate.maxSelectedCount;\n if (!this.shouldSkipValidation(data, rowData, options)) {\n const isValid = this.isValid(data, dirty);\n if ((maxCount || minCount)) {\n const count = Object.keys(this.validationValue).reduce((total, key) => {\n if (this.validationValue[key]) {\n total++;\n }\n return total;\n }, 0);\n // Disable the rest of inputs if the max amount is already checked\n if (maxCount && count >= maxCount) {\n this.setInputsDisabled(true, true);\n }\n else if (maxCount && !this.shouldDisabled) {\n this.setInputsDisabled(false);\n }\n if (!isValid && maxCount && count > maxCount) {\n const message = this.t(this.component.maxSelectedCountMessage || 'You may only select up to {{maxCount}} items', { maxCount });\n this.errors.push({ message });\n this.setCustomValidity(message, dirty);\n return false;\n }\n else if (!isValid && minCount && count < minCount) {\n this.setInputsDisabled(false);\n const message = this.t(this.component.minSelectedCountMessage || 'You must select at least {{minCount}} items', { minCount });\n this.errors.push({ message });\n this.setCustomValidity(message, dirty);\n return false;\n }\n }\n }\n return super.checkComponentValidity(data, dirty, rowData, options, errors);\n }\n validateValueAvailability(setting, value) {\n if (!(0, utils_1.boolValue)(setting) || !value) {\n return true;\n }\n const values = this.component.values;\n const availableValueKeys = (values || []).map(({ value: optionValue }) => optionValue);\n const valueKeys = Object.keys(value);\n return valueKeys.every((key) => availableValueKeys.includes(key));\n }\n}\nexports[\"default\"] = SelectBoxesComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/selectboxes/SelectBoxes.js?");
7207
7217
 
7208
7218
  /***/ }),
7209
7219
 
@@ -7346,7 +7356,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
7346
7356
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7347
7357
 
7348
7358
  "use strict";
7349
- 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 builder_1 = __importDefault(__webpack_require__(/*! ../../utils/builder */ \"./lib/cjs/utils/builder.js\"));\nconst NestedComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nested/NestedComponent */ \"./lib/cjs/components/_classes/nested/NestedComponent.js\"));\nclass TableComponent extends NestedComponent_1.default {\n static emptyTable(numRows, numCols) {\n const rows = [];\n for (let i = 0; i < numRows; i++) {\n const cols = [];\n for (let j = 0; j < numCols; j++) {\n cols.push({ components: [] });\n }\n rows.push(cols);\n }\n return rows;\n }\n static schema(...extend) {\n return NestedComponent_1.default.schema({\n label: 'Table',\n type: 'table',\n input: false,\n key: 'table',\n numRows: 3,\n numCols: 3,\n rows: TableComponent.emptyTable(3, 3),\n header: [],\n caption: '',\n cloneRows: false,\n striped: false,\n bordered: false,\n hover: false,\n condensed: false,\n persistent: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Table',\n group: 'layout',\n icon: 'table',\n weight: 40,\n documentation: '/userguide/form-building/layout-components#table',\n showPreview: false,\n schema: TableComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n get defaultSchema() {\n return TableComponent.schema();\n }\n get schema() {\n const schema = lodash_1.default.omit(super.schema, 'components');\n schema.rows = [];\n this.eachComponent((component) => {\n if (!schema.rows || !schema.rows.length) {\n schema.rows = TableComponent.emptyTable(this.component.numRows, this.component.numCols);\n }\n if (!schema.rows[component.tableRow]) {\n schema.rows[component.tableRow] = [];\n }\n if (!schema.rows[component.tableRow][component.tableColumn]) {\n schema.rows[component.tableRow][component.column] = { components: [] };\n }\n schema.rows[component.tableRow][component.tableColumn].components.push(component.schema);\n });\n if (!schema.rows.length) {\n schema.rows = TableComponent.emptyTable(this.component.numRows, this.component.numCols);\n }\n return schema;\n }\n get className() {\n let name = `table-responsive ${super.className}`;\n if (!this.component.bordered) {\n name += ' no-top-border-table';\n }\n return name;\n }\n get cellClassName() {\n let name = '';\n if (this.component.cellAlignment) {\n name = `cell-align-${this.component.cellAlignment}`;\n }\n return name;\n }\n get tableKey() {\n return `table-${this.key}`;\n }\n get colWidth() {\n const { numCols } = this.component;\n if (!numCols || typeof numCols !== 'number') {\n return '';\n }\n return Math.floor(12 / numCols).toString();\n }\n constructor(...args) {\n super(...args);\n this.noField = true;\n }\n init() {\n super.init();\n // Ensure component.rows has the correct number of rows and columns.\n for (let rowIndex = 0; rowIndex < this.component.numRows; rowIndex++) {\n this.component.rows[rowIndex] = this.component.rows[rowIndex] || [];\n for (let colIndex = 0; colIndex < this.component.numCols; colIndex++) {\n this.component.rows[rowIndex][colIndex] = this.component.rows[rowIndex][colIndex] || { components: [] };\n }\n this.component.rows[rowIndex] = this.component.rows[rowIndex].slice(0, this.component.numCols);\n }\n this.component.rows = this.component.rows.slice(0, this.component.numRows);\n const lastNonEmptyRow = [];\n this.table = [];\n lodash_1.default.each(this.component.rows, (row, rowIndex) => {\n this.table[rowIndex] = [];\n lodash_1.default.each(row, (column, colIndex) => {\n this.table[rowIndex][colIndex] = [];\n if (this.component.cloneRows) {\n if (column.components.length) {\n lastNonEmptyRow[colIndex] = column;\n }\n else if (lastNonEmptyRow[colIndex]) {\n column.components = lodash_1.default.cloneDeep(lastNonEmptyRow[colIndex].components);\n builder_1.default.uniquify(this.root._form.components, column);\n }\n }\n lodash_1.default.each(column.components, (comp) => {\n let columnComponent;\n if (this.builderMode) {\n comp.id = comp.id + rowIndex;\n columnComponent = comp;\n }\n else {\n columnComponent = Object.assign(Object.assign({}, comp), { id: (comp.id + rowIndex) });\n }\n const component = this.createComponent(columnComponent);\n component.tableRow = rowIndex;\n component.tableColumn = colIndex;\n this.table[rowIndex][colIndex].push(component);\n });\n });\n });\n }\n render() {\n return super.render(this.renderTemplate('table', {\n cellClassName: this.cellClassName,\n tableKey: this.tableKey,\n colWidth: this.colWidth,\n tableComponents: this.table.map(row => row.map(column => this.renderComponents(column)))\n }));\n }\n attach(element) {\n const keys = this.table.reduce((prev, row, rowIndex) => {\n prev[`${this.tableKey}-${rowIndex}`] = 'multiple';\n return prev;\n }, {});\n this.loadRefs(element, keys);\n const superAttach = super.attach(element);\n this.table.forEach((row, rowIndex) => {\n row.forEach((column, columnIndex) => {\n this.attachComponents(this.refs[`${this.tableKey}-${rowIndex}`][columnIndex], this.table[rowIndex][columnIndex], this.component.rows[rowIndex][columnIndex].components);\n });\n });\n return superAttach;\n }\n destroy(all) {\n super.destroy(all);\n delete this.table;\n }\n}\nexports[\"default\"] = TableComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/table/Table.js?");
7359
+ 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 builder_1 = __importDefault(__webpack_require__(/*! ../../utils/builder */ \"./lib/cjs/utils/builder.js\"));\nconst NestedComponent_1 = __importDefault(__webpack_require__(/*! ../_classes/nested/NestedComponent */ \"./lib/cjs/components/_classes/nested/NestedComponent.js\"));\nclass TableComponent extends NestedComponent_1.default {\n static emptyTable(numRows, numCols) {\n const rows = [];\n for (let i = 0; i < numRows; i++) {\n const cols = [];\n for (let j = 0; j < numCols; j++) {\n cols.push({ components: [] });\n }\n rows.push(cols);\n }\n return rows;\n }\n static schema(...extend) {\n return NestedComponent_1.default.schema({\n label: 'Table',\n type: 'table',\n input: false,\n key: 'table',\n numRows: 3,\n numCols: 3,\n rows: TableComponent.emptyTable(3, 3),\n header: [],\n caption: '',\n cloneRows: false,\n striped: false,\n bordered: false,\n hover: false,\n condensed: false,\n persistent: false\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Table',\n group: 'layout',\n icon: 'table',\n weight: 40,\n documentation: '/userguide/form-building/layout-components#table',\n showPreview: false,\n schema: TableComponent.schema()\n };\n }\n static savedValueTypes() {\n return [];\n }\n get defaultSchema() {\n return TableComponent.schema();\n }\n get schema() {\n const schema = lodash_1.default.omit(super.schema, 'components');\n schema.rows = [];\n this.eachComponent((component) => {\n if (!schema.rows || !schema.rows.length) {\n schema.rows = TableComponent.emptyTable(this.component.numRows, this.component.numCols);\n }\n if (!schema.rows[component.tableRow]) {\n schema.rows[component.tableRow] = [];\n }\n if (!schema.rows[component.tableRow][component.tableColumn]) {\n schema.rows[component.tableRow][component.column] = { components: [] };\n }\n schema.rows[component.tableRow][component.tableColumn].components.push(component.schema);\n });\n if (!schema.rows.length) {\n schema.rows = TableComponent.emptyTable(this.component.numRows, this.component.numCols);\n }\n return schema;\n }\n get className() {\n let name = `table-responsive ${super.className}`;\n if (!this.component.bordered) {\n name += ' no-top-border-table';\n }\n return name;\n }\n get cellClassName() {\n let name = '';\n if (this.component.cellAlignment) {\n name = `cell-align-${this.component.cellAlignment}`;\n }\n return name;\n }\n get tableKey() {\n return `table-${this.key}`;\n }\n get colWidth() {\n const { numCols } = this.component;\n if (!numCols || typeof numCols !== 'number') {\n return '';\n }\n return Math.floor(12 / numCols).toString();\n }\n constructor(...args) {\n super(...args);\n this.noField = true;\n }\n init() {\n super.init();\n // Ensure component.rows has the correct number of rows and columns.\n for (let rowIndex = 0; rowIndex < this.component.numRows; rowIndex++) {\n this.component.rows[rowIndex] = this.component.rows[rowIndex] || [];\n for (let colIndex = 0; colIndex < this.component.numCols; colIndex++) {\n this.component.rows[rowIndex][colIndex] = this.component.rows[rowIndex][colIndex] || { components: [] };\n }\n this.component.rows[rowIndex] = this.component.rows[rowIndex].slice(0, this.component.numCols);\n }\n this.component.rows = this.component.rows.slice(0, this.component.numRows);\n const lastNonEmptyRow = [];\n this.table = [];\n lodash_1.default.each(this.component.rows, (row, rowIndex) => {\n this.table[rowIndex] = [];\n lodash_1.default.each(row, (column, colIndex) => {\n this.table[rowIndex][colIndex] = [];\n if (this.component.cloneRows) {\n if (column.components.length) {\n lastNonEmptyRow[colIndex] = column;\n }\n else if (lastNonEmptyRow[colIndex]) {\n column.components = lodash_1.default.cloneDeep(lastNonEmptyRow[colIndex].components);\n builder_1.default.uniquify(this.root._form.components, column);\n }\n }\n lodash_1.default.each(column.components, (comp) => {\n let columnComponent;\n if (this.builderMode) {\n comp.id = comp.id + rowIndex;\n columnComponent = comp;\n }\n else {\n columnComponent = Object.assign(Object.assign({}, comp), { id: (comp.id + rowIndex) });\n }\n const component = this.createComponent(columnComponent);\n component.tableRow = rowIndex;\n component.tableColumn = colIndex;\n this.table[rowIndex][colIndex].push(component);\n });\n });\n });\n }\n render() {\n return super.render(this.renderTemplate('table', {\n cellClassName: this.cellClassName,\n tableKey: this.tableKey,\n colWidth: this.colWidth,\n tableComponents: this.table.map(row => row.map(column => this.renderComponents(column)))\n }));\n }\n attach(element) {\n const keys = this.table.reduce((prev, row, rowIndex) => {\n prev[`${this.tableKey}-${rowIndex}`] = 'multiple';\n return prev;\n }, {});\n this.loadRefs(element, keys);\n const superAttach = super.attach(element);\n this.table.forEach((row, rowIndex) => {\n row.forEach((column, columnIndex) => {\n this.attachComponents(this.refs[`${this.tableKey}-${rowIndex}`][columnIndex], this.table[rowIndex][columnIndex], this.component.rows[rowIndex][columnIndex].components);\n });\n });\n return superAttach;\n }\n destroy(all = false) {\n super.destroy(all);\n delete this.table;\n }\n}\nexports[\"default\"] = TableComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/table/Table.js?");
7350
7360
 
7351
7361
  /***/ }),
7352
7362
 
@@ -7412,7 +7422,7 @@ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {
7412
7422
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
7413
7423
 
7414
7424
  "use strict";
7415
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Input_1 = __importDefault(__webpack_require__(/*! ../_classes/input/Input */ \"./lib/cjs/components/_classes/input/Input.js\"));\nconst choices_js_1 = __importDefault(__webpack_require__(/*! @formio/choices.js */ \"./node_modules/@formio/choices.js/public/assets/scripts/choices.js\"));\nclass TagsComponent extends Input_1.default {\n static schema(...extend) {\n return Input_1.default.schema({\n type: 'tags',\n label: 'Tags',\n key: 'tags',\n delimeter: ',',\n storeas: 'string',\n maxTags: 0\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Tags',\n icon: 'tags',\n group: 'advanced',\n documentation: '/userguide/form-building/advanced-components#tags',\n weight: 30,\n schema: TagsComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return TagsComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: [...super.conditionOperatorsSettings.operators, 'includes', 'notIncludes'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes[schema.storeas] || utils_1.componentValueTypes.string];\n }\n init() {\n super.init();\n }\n get emptyValue() {\n return (this.component.storeas === 'string') ? '' : [];\n }\n get defaultSchema() {\n return TagsComponent.schema();\n }\n get inputInfo() {\n const info = super.inputInfo;\n info.type = 'input';\n info.attr.type = 'text';\n info.changeEvent = 'change';\n return info;\n }\n get delimiter() {\n return this.component.delimeter || ',';\n }\n attachElement(element, index) {\n super.attachElement(element, index);\n if (!element) {\n return;\n }\n element.setAttribute('dir', this.i18next.dir());\n if (this.choices) {\n this.choices.destroy();\n }\n if (!choices_js_1.default) {\n return;\n }\n const hasPlaceholder = !!this.component.placeholder;\n this.choices = new choices_js_1.default(element, {\n delimiter: this.delimiter,\n editItems: true,\n allowHTML: true,\n maxItemCount: this.component.maxTags,\n removeItemButton: true,\n duplicateItemsAllowed: false,\n shadowRoot: this.root ? this.root.shadowRoot : null,\n placeholder: hasPlaceholder,\n placeholderValue: hasPlaceholder ? this.t(this.component.placeholder, { _userInput: true }) : null,\n });\n this.choices.itemList.element.tabIndex = element.tabIndex;\n this.addEventListener(this.choices.input.element, 'blur', () => {\n // Emit event to the native Formio input, so the listener attached in the Input.js will be invoked\n element.dispatchEvent(new Event('blur'));\n const value = this.choices.input.value;\n const maxTagsNumber = this.component.maxTags;\n const valuesCount = this.choices.getValue(true).length;\n const isRepeatedValue = this.choices.getValue(true).some(existingValue => existingValue.trim() === value.trim());\n if (value) {\n if (maxTagsNumber && valuesCount === maxTagsNumber) {\n this.choices.addItems = false;\n this.choices.clearInput();\n }\n else if (isRepeatedValue) {\n this.choices.clearInput();\n }\n else {\n this.choices.setValue([value]);\n this.choices.clearInput();\n this.choices.hideDropdown(true);\n this.updateValue(null, {\n modified: true\n });\n }\n }\n });\n }\n detach() {\n super.detach();\n if (this.choices) {\n this.choices.destroy();\n this.choices = null;\n }\n }\n normalizeValue(value) {\n if (this.component.storeas === 'string' && Array.isArray(value)) {\n return value.join(this.delimiter);\n }\n else if (this.component.storeas === 'array' && typeof value === 'string') {\n return value.split(this.delimiter).filter(result => result);\n }\n return value;\n }\n setValue(value, flags = {}) {\n const changed = super.setValue(value, flags);\n if (this.choices) {\n let dataValue = this.dataValue;\n this.choices.removeActiveItems();\n if (dataValue) {\n if (typeof dataValue === 'string') {\n dataValue = dataValue.split(this.delimiter).filter(result => result);\n }\n const value = Array.isArray(dataValue) ? dataValue : [dataValue];\n this.choices.setValue(value.map((val) => this.sanitize(val, this.shouldSanitizeValue)));\n }\n }\n return changed;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.choices) {\n return;\n }\n if (disabled) {\n this.choices.disable();\n }\n else {\n this.choices.enable();\n }\n }\n get disabled() {\n return super.disabled;\n }\n focus() {\n if (this.refs.input && this.refs.input.length) {\n this.refs.input[0].parentNode.lastChild.focus();\n }\n }\n getValueAsString(value) {\n if (!value) {\n return '';\n }\n if (Array.isArray(value)) {\n return value.join(`${this.delimiter || ','} `);\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue, this.shouldSanitizeValue);\n }\n}\nexports[\"default\"] = TagsComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/tags/Tags.js?");
7425
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst utils_1 = __webpack_require__(/*! ../../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst Input_1 = __importDefault(__webpack_require__(/*! ../_classes/input/Input */ \"./lib/cjs/components/_classes/input/Input.js\"));\nconst choices_js_1 = __importDefault(__webpack_require__(/*! @formio/choices.js */ \"./node_modules/@formio/choices.js/public/assets/scripts/choices.js\"));\nclass TagsComponent extends Input_1.default {\n static schema(...extend) {\n return Input_1.default.schema({\n type: 'tags',\n label: 'Tags',\n key: 'tags',\n delimeter: ',',\n storeas: 'string',\n maxTags: 0\n }, ...extend);\n }\n static get builderInfo() {\n return {\n title: 'Tags',\n icon: 'tags',\n group: 'advanced',\n documentation: '/userguide/form-building/advanced-components#tags',\n weight: 30,\n schema: TagsComponent.schema()\n };\n }\n static get serverConditionSettings() {\n return TagsComponent.conditionOperatorsSettings;\n }\n static get conditionOperatorsSettings() {\n return Object.assign(Object.assign({}, super.conditionOperatorsSettings), { operators: [...super.conditionOperatorsSettings.operators, 'includes', 'notIncludes'] });\n }\n static savedValueTypes(schema) {\n schema = schema || {};\n return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes[schema.storeas] || utils_1.componentValueTypes.string];\n }\n init() {\n super.init();\n }\n get emptyValue() {\n return (this.component.storeas === 'string') ? '' : [];\n }\n get defaultSchema() {\n return TagsComponent.schema();\n }\n get inputInfo() {\n const info = super.inputInfo;\n info.type = 'input';\n info.attr.type = 'text';\n info.changeEvent = 'change';\n return info;\n }\n get delimiter() {\n return this.component.delimeter || ',';\n }\n attachElement(element, index) {\n super.attachElement(element, index);\n if (!element) {\n return;\n }\n if (this.i18next) {\n element.setAttribute('dir', this.i18next.dir());\n }\n if (this.choices) {\n this.choices.destroy();\n }\n if (!choices_js_1.default) {\n return;\n }\n const hasPlaceholder = !!this.component.placeholder;\n this.choices = new choices_js_1.default(element, {\n delimiter: this.delimiter,\n editItems: true,\n allowHTML: true,\n maxItemCount: this.component.maxTags,\n removeItemButton: true,\n duplicateItemsAllowed: false,\n shadowRoot: this.root ? this.root.shadowRoot : null,\n placeholder: hasPlaceholder,\n placeholderValue: hasPlaceholder ? this.t(this.component.placeholder, { _userInput: true }) : null,\n });\n this.choices.itemList.element.tabIndex = element.tabIndex;\n this.addEventListener(this.choices.input.element, 'blur', () => {\n // Emit event to the native Formio input, so the listener attached in the Input.js will be invoked\n element.dispatchEvent(new Event('blur'));\n const value = this.choices.input.value;\n const maxTagsNumber = this.component.maxTags;\n const valuesCount = this.choices.getValue(true).length;\n const isRepeatedValue = this.choices.getValue(true).some(existingValue => existingValue.trim() === value.trim());\n if (value) {\n if (maxTagsNumber && valuesCount === maxTagsNumber) {\n this.choices.addItems = false;\n this.choices.clearInput();\n }\n else if (isRepeatedValue) {\n this.choices.clearInput();\n }\n else {\n this.choices.setValue([value]);\n this.choices.clearInput();\n this.choices.hideDropdown(true);\n this.updateValue(null, {\n modified: true\n });\n }\n }\n });\n }\n detach() {\n if (this.choices) {\n this.choices.destroy();\n this.choices = null;\n }\n super.detach();\n }\n normalizeValue(value) {\n if (this.component.storeas === 'string' && Array.isArray(value)) {\n return value.join(this.delimiter);\n }\n else if (this.component.storeas === 'array' && typeof value === 'string') {\n return value.split(this.delimiter).filter(result => result);\n }\n return value;\n }\n setValue(value, flags = {}) {\n const changed = super.setValue(value, flags);\n if (this.choices) {\n let dataValue = this.dataValue;\n this.choices.removeActiveItems();\n if (dataValue) {\n if (typeof dataValue === 'string') {\n dataValue = dataValue.split(this.delimiter).filter(result => result);\n }\n const value = Array.isArray(dataValue) ? dataValue : [dataValue];\n this.choices.setValue(value.map((val) => this.sanitize(val, this.shouldSanitizeValue)));\n }\n }\n return changed;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (!this.choices) {\n return;\n }\n if (disabled) {\n this.choices.disable();\n }\n else {\n this.choices.enable();\n }\n }\n get disabled() {\n return super.disabled;\n }\n focus() {\n if (this.refs.input && this.refs.input.length) {\n this.refs.input[0].parentNode.lastChild.focus();\n }\n }\n getValueAsString(value) {\n if (!value) {\n return '';\n }\n if (Array.isArray(value)) {\n return value.join(`${this.delimiter || ','} `);\n }\n const stringValue = value.toString();\n return this.sanitize(stringValue, this.shouldSanitizeValue);\n }\n}\nexports[\"default\"] = TagsComponent;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/components/tags/Tags.js?");
7416
7426
 
7417
7427
  /***/ }),
7418
7428
 
@@ -8325,7 +8335,7 @@ eval("\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexpo
8325
8335
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
8326
8336
 
8327
8337
  "use strict";
8328
- eval("\n/* global jQuery */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.observeOverload = exports.withSwitch = exports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.ConditionOperators = exports.moment = exports.jsonLogic = void 0;\nexports.isSelectResourceWithObjectValue = exports.getItemTemplateKeys = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isInsideScopingComponent = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nexports._ = lodash_1.default;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst json_logic_js_1 = __importDefault(__webpack_require__(/*! json-logic-js */ \"./node_modules/json-logic-js/logic.js\"));\nexports.jsonLogic = json_logic_js_1.default;\nconst moment_timezone_1 = __importDefault(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nexports.moment = moment_timezone_1.default;\nconst jstimezonedetect_1 = __importDefault(__webpack_require__(/*! jstimezonedetect */ \"./node_modules/jstimezonedetect/dist/jstz.min.js\"));\nconst operators_1 = __webpack_require__(/*! ./jsonlogic/operators */ \"./lib/cjs/utils/jsonlogic/operators.js\");\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.js\"));\nconst formUtils_1 = __webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nexports.Evaluator = Evaluator_1.default;\nconst conditionOperators_1 = __importDefault(__webpack_require__(/*! ./conditionOperators */ \"./lib/cjs/utils/conditionOperators/index.js\"));\nexports.ConditionOperators = conditionOperators_1.default;\nconst interpolate = Evaluator_1.default.interpolate;\nexports.interpolate = interpolate;\nconst { fetch } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\n__exportStar(__webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\"), exports);\n// Configure JsonLogic\noperators_1.lodashOperators.forEach((name) => json_logic_js_1.default.add_operation(`_${name}`, lodash_1.default[name]));\n// Retrieve Any Date\njson_logic_js_1.default.add_operation('getDate', (date) => {\n return (0, moment_timezone_1.default)(date).toISOString();\n});\n// Set Relative Minimum Date\njson_logic_js_1.default.add_operation('relativeMinDate', (relativeMinDate) => {\n return (0, moment_timezone_1.default)().subtract(relativeMinDate, 'days').toISOString();\n});\n// Set Relative Maximum Date\njson_logic_js_1.default.add_operation('relativeMaxDate', (relativeMaxDate) => {\n return (0, moment_timezone_1.default)().add(relativeMaxDate, 'days').toISOString();\n});\nfunction setPathToComponentAndPerentSchema(component) {\n component.path = getComponentPath(component);\n const dataParent = getDataParentComponent(component);\n if (dataParent && typeof dataParent === 'object') {\n dataParent.path = getComponentPath(dataParent);\n }\n}\n/**\n * Evaluate a method.\n *\n * @param func\n * @param args\n * @return {*}\n */\nfunction evaluate(func, args, ret, tokenize) {\n let returnVal = null;\n const component = args.component ? args.component : { key: 'unknown' };\n if (!args.form && args.instance) {\n args.form = lodash_1.default.get(args.instance, 'root._form', {});\n }\n const componentKey = component.key;\n if (typeof func === 'string') {\n if (ret) {\n func += `;return ${ret}`;\n }\n if (tokenize) {\n // Replace all {{ }} references with actual data.\n func = func.replace(/({{\\s+(.*)\\s+}})/, (match, $1, $2) => {\n if ($2.indexOf('data.') === 0) {\n return lodash_1.default.get(args.data, $2.replace('data.', ''));\n }\n else if ($2.indexOf('row.') === 0) {\n return lodash_1.default.get(args.row, $2.replace('row.', ''));\n }\n // Support legacy...\n return lodash_1.default.get(args.data, $2);\n });\n }\n try {\n func = Evaluator_1.default.evaluator(func, args);\n args = lodash_1.default.values(args);\n }\n catch (err) {\n console.warn(`An error occured within the custom function for ${componentKey}`, err);\n returnVal = null;\n func = false;\n }\n }\n if (typeof func === 'function') {\n try {\n returnVal = Evaluator_1.default.evaluate(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (typeof func === 'object') {\n try {\n returnVal = json_logic_js_1.default.apply(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (func) {\n console.warn(`Unknown function type for ${componentKey}`);\n }\n return returnVal;\n}\nexports.evaluate = evaluate;\nfunction getRandomComponentId() {\n return `e${Math.random().toString(36).substring(7)}`;\n}\nexports.getRandomComponentId = getRandomComponentId;\n/**\n * Get a property value of an element.\n *\n * @param style\n * @param prop\n * @return {number}\n */\nfunction getPropertyValue(style, prop) {\n let value = style.getPropertyValue(prop);\n value = value ? value.replace(/[^0-9.]/g, '') : '0';\n return parseFloat(value);\n}\nexports.getPropertyValue = getPropertyValue;\n/**\n * Get an elements bounding rectagle.\n *\n * @param element\n * @return {{x: string, y: string, width: string, height: string}}\n */\nfunction getElementRect(element) {\n const style = window.getComputedStyle(element, null);\n return {\n x: getPropertyValue(style, 'left'),\n y: getPropertyValue(style, 'top'),\n width: getPropertyValue(style, 'width'),\n height: getPropertyValue(style, 'height')\n };\n}\nexports.getElementRect = getElementRect;\n/**\n * Determines the boolean value of a setting.\n *\n * @param value\n * @return {boolean}\n */\nfunction boolValue(value) {\n if (lodash_1.default.isBoolean(value)) {\n return value;\n }\n else if (lodash_1.default.isString(value)) {\n return (value.toLowerCase() === 'true');\n }\n else {\n return !!value;\n }\n}\nexports.boolValue = boolValue;\n/**\n * Check to see if an ID is a mongoID.\n * @param text\n * @return {Array|{index: number, input: string}|Boolean|*}\n */\nfunction isMongoId(text) {\n return text.toString().match(/^[0-9a-fA-F]{24}$/);\n}\nexports.isMongoId = isMongoId;\n/**\n * Checks the calculated value for a provided component and data.\n *\n * @param {Object} component\n * The component to check for the calculated value.\n * @param {Object} submission\n * A submission object.\n * @param data\n * The full submission data.\n */\nfunction checkCalculated(component, submission, rowData) {\n // Process calculated value stuff if present.\n if (component.calculateValue) {\n lodash_1.default.set(rowData, component.key, evaluate(component.calculateValue, {\n value: undefined,\n data: submission ? submission.data : rowData,\n row: rowData,\n util: this,\n component\n }, 'value'));\n }\n}\nexports.checkCalculated = checkCalculated;\n/**\n * Check if a simple conditional evaluates to true.\n *\n * @param condition\n * @param condition\n * @param row\n * @param data\n * @param instance\n * @returns {boolean}\n */\nfunction checkSimpleConditional(component, condition, row, data, instance) {\n if (condition.when) {\n const value = getComponentActualValue(condition.when, data, row);\n const eq = String(condition.eq);\n const show = String(condition.show);\n // Special check for selectboxes component.\n if (lodash_1.default.isObject(value) && lodash_1.default.has(value, condition.eq)) {\n return String(value[condition.eq]) === show;\n }\n // FOR-179 - Check for multiple values.\n if (Array.isArray(value) && value.map(String).includes(eq)) {\n return show === 'true';\n }\n return (String(value) === eq) === (show === 'true');\n }\n else {\n const { conditions = [], conjunction = 'all', show = true } = condition;\n if (!conditions.length) {\n return true;\n }\n const conditionsResult = lodash_1.default.map(conditions, (cond) => {\n const { value: comparedValue, operator, component: conditionComponentPath } = cond;\n if (!conditionComponentPath) {\n return true;\n }\n const value = getComponentActualValue(conditionComponentPath, data, row);\n const ConditionOperator = conditionOperators_1.default[operator];\n return ConditionOperator\n ? new ConditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath })\n : true;\n });\n let result = false;\n switch (conjunction) {\n case 'any':\n result = lodash_1.default.some(conditionsResult, res => !!res);\n break;\n default:\n result = lodash_1.default.every(conditionsResult, res => !!res);\n }\n return show ? result : !result;\n }\n}\nexports.checkSimpleConditional = checkSimpleConditional;\nfunction getComponentActualValue(compPath, data, row) {\n let value = null;\n if (row) {\n value = (0, formUtils_1.getValue)({ data: row }, compPath);\n }\n if (data && lodash_1.default.isNil(value)) {\n value = (0, formUtils_1.getValue)({ data }, compPath);\n }\n // FOR-400 - Fix issue where falsey values were being evaluated as show=true\n if (lodash_1.default.isNil(value) || (lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value))) {\n value = '';\n }\n return value;\n}\nexports.getComponentActualValue = getComponentActualValue;\n/**\n * Check custom javascript conditional.\n *\n * @param component\n * @param custom\n * @param row\n * @param data\n * @returns {*}\n */\nfunction checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {\n if (typeof custom === 'string') {\n custom = `var ${variable} = true; ${custom}; return ${variable};`;\n }\n const value = (instance && instance.evaluate) ?\n instance.evaluate(custom, { row, data, form }) :\n evaluate(custom, { row, data, form });\n if (value === null) {\n return onError;\n }\n return value;\n}\nexports.checkCustomConditional = checkCustomConditional;\nfunction checkJsonConditional(component, json, row, data, form, onError) {\n try {\n return json_logic_js_1.default.apply(json, {\n data,\n row,\n form,\n _: lodash_1.default,\n });\n }\n catch (err) {\n console.warn(`An error occurred in jsonLogic advanced condition for ${component.key}`, err);\n return onError;\n }\n}\nexports.checkJsonConditional = checkJsonConditional;\nfunction getRow(component, row, instance, conditional) {\n var _a;\n const condition = conditional || component.conditional;\n // If no component's instance passed (happens only in 6.x server), calculate its path based on the schema\n if (!instance) {\n instance = lodash_1.default.cloneDeep(component);\n setPathToComponentAndPerentSchema(instance);\n }\n const dataParent = getDataParentComponent(instance);\n const parentPath = dataParent ? getComponentPath(dataParent) : null;\n const isTriggerCondtionComponentPath = condition.when || !condition.conditions\n ? (_a = condition.when) === null || _a === void 0 ? void 0 : _a.startsWith(parentPath)\n : lodash_1.default.some(condition.conditions, cond => cond.component.startsWith(parentPath));\n if (dataParent && isTriggerCondtionComponentPath) {\n const newRow = {};\n lodash_1.default.set(newRow, parentPath, row);\n row = newRow;\n }\n return row;\n}\n/**\n * Checks the conditions for a provided component and data.\n *\n * @param component\n * The component to check for the condition.\n * @param row\n * The data within a row\n * @param data\n * The full submission data.\n *\n * @returns {boolean}\n */\nfunction checkCondition(component, row, data, form, instance) {\n const { customConditional, conditional } = component;\n if (customConditional) {\n return checkCustomConditional(component, customConditional, row, data, form, 'show', true, instance);\n }\n else if (conditional && (conditional.when || lodash_1.default.some(conditional.conditions || [], condition => condition.component && condition.operator))) {\n row = getRow(component, row, instance);\n return checkSimpleConditional(component, conditional, row, data, instance);\n }\n else if (conditional && conditional.json) {\n return checkJsonConditional(component, conditional.json, row, data, form, true);\n }\n // Default to show.\n return true;\n}\nexports.checkCondition = checkCondition;\n/**\n * Test a trigger on a component.\n *\n * @param component\n * @param action\n * @param data\n * @param row\n * @returns {mixed}\n */\nfunction checkTrigger(component, trigger, row, data, form, instance) {\n // If trigger is empty, don't fire it\n if (!trigger || !trigger[trigger.type]) {\n return false;\n }\n switch (trigger.type) {\n case 'simple':\n row = getRow(component, row, instance, trigger.simple);\n return checkSimpleConditional(component, trigger.simple, row, data, instance);\n case 'javascript':\n return checkCustomConditional(component, trigger.javascript, row, data, form, 'result', false, instance);\n case 'json':\n return checkJsonConditional(component, trigger.json, row, data, form, false);\n }\n // If none of the types matched, don't fire the trigger.\n return false;\n}\nexports.checkTrigger = checkTrigger;\nfunction setActionProperty(component, action, result, row, data, instance) {\n const property = action.property.value;\n switch (action.property.type) {\n case 'boolean': {\n const currentValue = lodash_1.default.get(component, property, false).toString();\n const newValue = action.state.toString();\n if (currentValue !== newValue) {\n lodash_1.default.set(component, property, newValue === 'true');\n }\n break;\n }\n case 'string': {\n const evalData = {\n data,\n row,\n component,\n result,\n };\n const textValue = action.property.component ? action[action.property.component] : action.text;\n const currentValue = lodash_1.default.get(component, property, '');\n const newValue = (instance && instance.interpolate)\n ? instance.interpolate(textValue, evalData)\n : Evaluator_1.default.interpolate(textValue, evalData);\n if (newValue !== currentValue) {\n lodash_1.default.set(component, property, newValue);\n }\n break;\n }\n }\n return component;\n}\nexports.setActionProperty = setActionProperty;\n/**\n * Unescape HTML characters like &lt, &gt, &amp and etc.\n * @param str\n * @returns {string}\n */\nfunction unescapeHTML(str) {\n if (typeof window === 'undefined' || !('DOMParser' in window)) {\n return str;\n }\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.documentElement.textContent;\n}\nexports.unescapeHTML = unescapeHTML;\n/**\n * Make HTML element from string\n * @param str\n * @param selector\n * @returns {HTMLElement}\n */\nfunction convertStringToHTMLElement(str, selector) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.body.querySelector(selector);\n}\nexports.convertStringToHTMLElement = convertStringToHTMLElement;\n/**\n * Make a filename guaranteed to be unique.\n * @param name\n * @param template\n * @param evalContext\n * @returns {string}\n */\nfunction uniqueName(name, template, evalContext) {\n template = template || '{{fileName}}-{{guid}}';\n //include guid in template anyway, to prevent overwriting issue if filename matches existing file\n if (!template.includes('{{guid}}')) {\n template = `${template}-{{guid}}`;\n }\n const parts = name.split('.');\n let fileName = parts.slice(0, parts.length - 1).join('.');\n const extension = parts.length > 1\n ? `.${lodash_1.default.last(parts)}`\n : '';\n //allow only 100 characters from original name to avoid issues with filename length restrictions\n fileName = fileName.substr(0, 100);\n evalContext = Object.assign(evalContext || {}, {\n fileName,\n guid: guid()\n });\n //only letters, numbers, dots, dashes, underscores and spaces are allowed. Anything else will be replaced with dash\n const uniqueName = `${Evaluator_1.default.interpolate(template, evalContext)}${extension}`.replace(/[^0-9a-zA-Z.\\-_ ]/g, '-');\n return uniqueName;\n}\nexports.uniqueName = uniqueName;\nfunction guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x'\n ? r\n : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\nexports.guid = guid;\n/**\n * Return a translated date setting.\n *\n * @param date\n * @return {(null|Date)}\n */\nfunction getDateSetting(date) {\n if (lodash_1.default.isNil(date) || lodash_1.default.isNaN(date) || date === '') {\n return null;\n }\n if (date instanceof Date) {\n return date;\n }\n else if (typeof date.toDate === 'function') {\n return date.isValid() ? date.toDate() : null;\n }\n let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? (0, moment_timezone_1.default)(date) : null;\n if (dateSetting && dateSetting.isValid()) {\n return dateSetting.toDate();\n }\n dateSetting = null;\n try {\n const value = Evaluator_1.default.evaluator(`return ${date};`, 'moment')(moment_timezone_1.default);\n if (typeof value === 'string') {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n else if (typeof value.toDate === 'function') {\n dateSetting = (0, moment_timezone_1.default)(value.toDate().toUTCString());\n }\n else if (value instanceof Date) {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n }\n catch (e) {\n return null;\n }\n if (!dateSetting) {\n return null;\n }\n // Ensure this is a date.\n if (!dateSetting.isValid()) {\n return null;\n }\n return dateSetting.toDate();\n}\nexports.getDateSetting = getDateSetting;\nfunction isValidDate(date) {\n return lodash_1.default.isDate(date) && !lodash_1.default.isNaN(date.getDate());\n}\nexports.isValidDate = isValidDate;\n/**\n * Get the current timezone string.\n *\n * @return {string}\n */\nfunction currentTimezone() {\n if (moment_timezone_1.default.currentTimezone) {\n return moment_timezone_1.default.currentTimezone;\n }\n moment_timezone_1.default.currentTimezone = jstimezonedetect_1.default.determine().name();\n return moment_timezone_1.default.currentTimezone;\n}\nexports.currentTimezone = currentTimezone;\n/**\n * Get an offset date provided a date object and timezone object.\n *\n * @param date\n * @param timezone\n * @return {Date}\n */\nfunction offsetDate(date, timezone) {\n if (timezone === 'UTC') {\n return {\n date: new Date(date.getTime() + (date.getTimezoneOffset() * 60000)),\n abbr: 'UTC'\n };\n }\n const dateMoment = (0, moment_timezone_1.default)(date).tz(timezone);\n return {\n date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)),\n abbr: dateMoment.format('z')\n };\n}\nexports.offsetDate = offsetDate;\n/**\n * Returns if the zones are loaded.\n *\n * @return {boolean}\n */\nfunction zonesLoaded() {\n return moment_timezone_1.default.zonesLoaded;\n}\nexports.zonesLoaded = zonesLoaded;\n/**\n * Returns if we should load the zones.\n *\n * @param timezone\n * @return {boolean}\n */\nfunction shouldLoadZones(timezone) {\n if (timezone === currentTimezone() || timezone === 'UTC') {\n return false;\n }\n return true;\n}\nexports.shouldLoadZones = shouldLoadZones;\n/**\n * Externally load the timezone data.\n *\n * @return {Promise<any> | *}\n */\nfunction loadZones(url, timezone) {\n if (timezone && !shouldLoadZones(timezone)) {\n // Return non-resolving promise.\n return new Promise(lodash_1.default.noop);\n }\n if (moment_timezone_1.default.zonesPromise) {\n return moment_timezone_1.default.zonesPromise;\n }\n return moment_timezone_1.default.zonesPromise = fetch(url)\n .then(resp => resp.json().then(zones => {\n moment_timezone_1.default.tz.load(zones);\n moment_timezone_1.default.zonesLoaded = true;\n // Trigger a global event that the timezones have finished loading.\n if (document && document.createEvent && document.body && document.body.dispatchEvent) {\n var event = document.createEvent('Event');\n event.initEvent('zonesLoaded', true, true);\n document.body.dispatchEvent(event);\n }\n }));\n}\nexports.loadZones = loadZones;\n/**\n * Get the moment date object for translating dates with timezones.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {*}\n */\nfunction momentDate(value, format, timezone) {\n const momentDate = (0, moment_timezone_1.default)(value);\n if (!timezone) {\n return momentDate;\n }\n if (timezone === 'UTC') {\n timezone = 'Etc/UTC';\n }\n if ((timezone !== currentTimezone() || (format && format.match(/\\s(z$|z\\s)/))) && moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone);\n }\n return momentDate;\n}\nexports.momentDate = momentDate;\n/**\n * Format a date provided a value, format, and timezone object.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) {\n const momentDate = (0, moment_timezone_1.default)(value, flatPickrInputFormat || undefined);\n if (timezone === currentTimezone()) {\n // See if our format contains a \"z\" timezone character.\n if (format.match(/\\s(z$|z\\s)/)) {\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone).format(convertFormatToMoment(format));\n }\n else {\n return momentDate.format(convertFormatToMoment(format.replace(/\\s(z$|z\\s)/, '')));\n }\n }\n // Return the standard format.\n return momentDate.format(convertFormatToMoment(format));\n }\n if (timezone === 'UTC') {\n const offset = offsetDate(momentDate.toDate(), 'UTC');\n return `${(0, moment_timezone_1.default)(offset.date).format(convertFormatToMoment(format))} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded && timezone) {\n return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`);\n }\n else {\n return momentDate.format(convertFormatToMoment(format));\n }\n}\nexports.formatDate = formatDate;\n/**\n * Pass a format function to format within a timezone.\n *\n * @param formatFn\n * @param date\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatOffset(timezonesUrl, formatFn, date, format, timezone) {\n if (timezone === currentTimezone()) {\n return formatFn(date, format);\n }\n if (timezone === 'UTC') {\n return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n const offset = offsetDate(date, timezone);\n return `${formatFn(offset.date, format)} ${offset.abbr}`;\n }\n else {\n return formatFn(date, format);\n }\n}\nexports.formatOffset = formatOffset;\nfunction getLocaleDateFormatInfo(locale) {\n const formatInfo = {};\n const day = 21;\n const exampleDate = new Date(2017, 11, day);\n const localDateString = exampleDate.toLocaleDateString(locale);\n formatInfo.dayFirst = localDateString.slice(0, 2) === day.toString();\n return formatInfo;\n}\nexports.getLocaleDateFormatInfo = getLocaleDateFormatInfo;\n/**\n * Convert the format from the angular-datepicker module to flatpickr format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToFlatpickr(format) {\n return format\n // Remove the Z timezone offset, not supported by flatpickr.\n .replace(/Z/g, '')\n // Year conversion.\n .replace(/y/g, 'Y')\n .replace('YYYY', 'Y')\n .replace('YY', 'y')\n // Month conversion.\n .replace('MMMM', 'F')\n .replace(/M/g, 'n')\n .replace('nnn', 'M')\n .replace('nn', 'm')\n // Day in month.\n .replace(/d/g, 'j')\n .replace(/jj/g, 'd')\n // Day in week.\n .replace('EEEE', 'l')\n .replace('EEE', 'D')\n // Hours, minutes, seconds\n .replace('HH', 'H')\n .replace('hh', 'G')\n .replace('mm', 'i')\n .replace('ss', 'S')\n .replace(/a/g, 'K');\n}\nexports.convertFormatToFlatpickr = convertFormatToFlatpickr;\n/**\n * Convert the format from the angular-datepicker module to moment format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToMoment(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y')\n // Day in month.\n .replace(/d/g, 'D')\n // Day in week.\n .replace(/E/g, 'd')\n // AM/PM marker\n .replace(/a/g, 'A')\n // Unix Timestamp\n .replace(/U/g, 'X');\n}\nexports.convertFormatToMoment = convertFormatToMoment;\nfunction convertFormatToMask(format) {\n return format\n // Long month replacement.\n .replace(/M{4}/g, 'MM')\n // Initial short month conversion.\n .replace(/M{3}/g, '***')\n // Short month conversion if input as text.\n .replace(/e/g, 'Q')\n // Month number conversion.\n .replace(/W/g, '99')\n // Year conversion.\n .replace(/[ydhmswHMG]/g, '9')\n // AM/PM conversion.\n .replace(/a/g, 'AA');\n}\nexports.convertFormatToMask = convertFormatToMask;\n/**\n * Returns an input mask that is compatible with the input mask library.\n * @param {string} mask - The Form.io input mask.\n * @param {string} placeholderChar - Char which is used as a placeholder.\n * @returns {Array} - The input mask for the mask library.\n */\nfunction getInputMask(mask, placeholderChar) {\n if (mask instanceof Array) {\n return mask;\n }\n const maskArray = [];\n maskArray.numeric = true;\n for (let i = 0; i < mask.length; i++) {\n switch (mask[i]) {\n case '9':\n maskArray.push(/\\d/);\n break;\n case 'A':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z]/);\n break;\n case 'a':\n maskArray.numeric = false;\n maskArray.push(/[a-z]/);\n break;\n case '*':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z0-9]/);\n break;\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n case placeholderChar:\n maskArray.numeric = false;\n maskArray.push(' ');\n break;\n default:\n maskArray.numeric = false;\n maskArray.push(mask[i]);\n break;\n }\n }\n return maskArray;\n}\nexports.getInputMask = getInputMask;\nfunction unmaskValue(value, mask, placeholderChar) {\n if (!mask || !value || value.length > mask.length) {\n return value;\n }\n let unmaskedValue = value.split('');\n for (let i = 0; i < mask.length; i++) {\n const char = value[i] || '';\n const charPart = mask[i];\n if (!lodash_1.default.isRegExp(charPart) && char === charPart) {\n unmaskedValue[i] = '';\n }\n }\n unmaskedValue = unmaskedValue.join('').replace(placeholderChar, '');\n return unmaskedValue;\n}\nexports.unmaskValue = unmaskValue;\nfunction matchInputMask(value, inputMask) {\n if (!inputMask) {\n return true;\n }\n // If value is longer than mask, it isn't valid.\n if (value.length > inputMask.length) {\n return false;\n }\n for (let i = 0; i < inputMask.length; i++) {\n const char = value[i] || '';\n const charPart = inputMask[i];\n if (!(lodash_1.default.isRegExp(charPart) && charPart.test(char) || charPart === char)) {\n return false;\n }\n }\n return true;\n}\nexports.matchInputMask = matchInputMask;\nfunction getNumberSeparators(lang = 'en') {\n const formattedNumberString = (12345.6789).toLocaleString(lang);\n const delimeters = formattedNumberString.match(/..(.)...(.)../);\n if (!delimeters) {\n return {\n delimiter: ',',\n decimalSeparator: '.'\n };\n }\n return {\n delimiter: (delimeters.length > 1) ? delimeters[1] : ',',\n decimalSeparator: (delimeters.length > 2) ? delimeters[2] : '.',\n };\n}\nexports.getNumberSeparators = getNumberSeparators;\nfunction getNumberDecimalLimit(component, defaultLimit) {\n if (lodash_1.default.has(component, 'decimalLimit')) {\n return lodash_1.default.get(component, 'decimalLimit');\n }\n // Determine the decimal limit. Defaults to 20 but can be overridden by validate.step or decimalLimit settings.\n let decimalLimit = defaultLimit || 20;\n const step = lodash_1.default.get(component, 'validate.step', 'any');\n if (step !== 'any') {\n const parts = step.toString().split('.');\n if (parts.length > 1) {\n decimalLimit = parts[1].length;\n }\n }\n return decimalLimit;\n}\nexports.getNumberDecimalLimit = getNumberDecimalLimit;\nfunction getCurrencyAffixes({ currency, decimalLimit, decimalSeparator, lang, }) {\n // Get the prefix and suffix from the localized string.\n let regex = `(.*)?${(100).toLocaleString(lang)}`;\n if (decimalLimit) {\n regex += `${decimalSeparator === '.' ? '\\\\.' : decimalSeparator}${(0).toLocaleString(lang)}{${decimalLimit}}`;\n }\n regex += '(.*)?';\n const parts = (100).toLocaleString(lang, {\n style: 'currency',\n currency: currency ? currency : 'USD',\n useGrouping: true,\n maximumFractionDigits: decimalLimit || 0,\n minimumFractionDigits: decimalLimit || 0\n }).replace('.', decimalSeparator).match(new RegExp(regex));\n return {\n prefix: (parts === null || parts === void 0 ? void 0 : parts[1]) || '',\n suffix: (parts === null || parts === void 0 ? void 0 : parts[2]) || ''\n };\n}\nexports.getCurrencyAffixes = getCurrencyAffixes;\n/**\n * Fetch the field data provided a component.\n *\n * @param data\n * @param component\n * @return {*}\n */\nfunction fieldData(data, component) {\n if (!data) {\n return '';\n }\n if (!component || !component.key) {\n return data;\n }\n if (component.key.includes('.')) {\n let value = data;\n const parts = component.key.split('.');\n let key = '';\n for (let i = 0; i < parts.length; i++) {\n key = parts[i];\n // Handle nested resources\n if (value.hasOwnProperty('_id')) {\n value = value.data;\n }\n // Return if the key is not found on the value.\n if (!value.hasOwnProperty(key)) {\n return;\n }\n // Convert old single field data in submissions to multiple\n if (key === parts[parts.length - 1] && component.multiple && !Array.isArray(value[key])) {\n value[key] = [value[key]];\n }\n // Set the value of this key.\n value = value[key];\n }\n return value;\n }\n else {\n // Convert old single field data in submissions to multiple\n if (component.multiple && !Array.isArray(data[component.key])) {\n data[component.key] = [data[component.key]];\n }\n // Fix for checkbox type radio submission values in tableView\n if (component.type === 'checkbox' && component.inputType === 'radio') {\n return data[component.name] === component.value;\n }\n return data[component.key];\n }\n}\nexports.fieldData = fieldData;\n/**\n * Delays function execution with possibility to execute function synchronously or cancel it.\n *\n * @param fn Function to delay\n * @param delay Delay time\n * @return {*}\n */\nfunction delay(fn, delay = 0, ...args) {\n const timer = setTimeout(fn, delay, ...args);\n function cancel() {\n clearTimeout(timer);\n }\n function earlyCall() {\n cancel();\n return fn(...args);\n }\n earlyCall.timer = timer;\n earlyCall.cancel = cancel;\n return earlyCall;\n}\nexports.delay = delay;\n/**\n * Iterate the given key to make it unique.\n *\n * @param {String} key\n * Modify the component key to be unique.\n *\n * @returns {String}\n * The new component key.\n */\nfunction iterateKey(key) {\n if (!key.match(/(\\d+)$/)) {\n return `${key}1`;\n }\n return key.replace(/(\\d+)$/, function (suffix) {\n return Number(suffix) + 1;\n });\n}\nexports.iterateKey = iterateKey;\n/**\n * Determines a unique key within a map provided the base key.\n *\n * @param map\n * @param base\n * @return {*}\n */\nfunction uniqueKey(map, base) {\n let newKey = base;\n while (map.hasOwnProperty(newKey)) {\n newKey = iterateKey(newKey);\n }\n return newKey;\n}\nexports.uniqueKey = uniqueKey;\n/**\n * Determines the major version number of bootstrap.\n *\n * @return {number}\n */\nfunction bootstrapVersion(options) {\n if (options.bootstrap) {\n return options.bootstrap;\n }\n if ((typeof jQuery === 'function') && (typeof jQuery().collapse === 'function')) {\n return parseInt(jQuery.fn.collapse.Constructor.VERSION.split('.')[0], 10);\n }\n if (window.bootstrap && window.bootstrap.Collapse) {\n return parseInt(window.bootstrap.Collapse.VERSION.split('.')[0], 10);\n }\n return 0;\n}\nexports.bootstrapVersion = bootstrapVersion;\n/**\n * Retrun provided argument.\n * If argument is a function, returns the result of a function call.\n * @param {*} e;\n *\n * @return {*}\n */\nfunction unfold(e) {\n if (typeof e === 'function') {\n return e();\n }\n return e;\n}\nexports.unfold = unfold;\n/**\n * Map values through unfold and return first non-nil value.\n * @param {Array<T>} collection;\n *\n * @return {T}\n */\nexports.firstNonNil = lodash_1.default.flow([\n lodash_1.default.partialRight(lodash_1.default.map, unfold),\n lodash_1.default.partialRight(lodash_1.default.find, v => !lodash_1.default.isUndefined(v))\n]);\n/*\n * Create enclosed state.\n * Returns functions to getting and cycling between states.\n * @param {*} a - initial state.\n * @param {*} b - next state.\n * @return {Functions[]} -- [get, toggle];\n */\nfunction withSwitch(a, b) {\n let state = a;\n let next = b;\n function get() {\n return state;\n }\n function toggle() {\n const prev = state;\n state = next;\n next = prev;\n }\n return [get, toggle];\n}\nexports.withSwitch = withSwitch;\nfunction observeOverload(callback, options = {}) {\n const { limit = 50, delay = 500 } = options;\n let callCount = 0;\n let timeoutID = 0;\n const reset = () => callCount = 0;\n return () => {\n if (timeoutID !== 0) {\n clearTimeout(timeoutID);\n timeoutID = 0;\n }\n timeoutID = setTimeout(reset, delay);\n callCount += 1;\n if (callCount >= limit) {\n clearTimeout(timeoutID);\n reset();\n return callback();\n }\n };\n}\nexports.observeOverload = observeOverload;\nfunction getContextComponents(context, excludeNested, excludedTypes = []) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component, path) => {\n const addToContextComponents = excludeNested ? !component.tree : true;\n if (component.key !== context.data.key && addToContextComponents && !lodash_1.default.includes(excludedTypes, component.type)) {\n values.push({\n label: `${component.label || component.key} (${path})`,\n value: path,\n });\n }\n });\n return values;\n}\nexports.getContextComponents = getContextComponents;\nfunction getContextButtons(context) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component) => {\n if (component.type === 'button') {\n values.push({\n label: `${component.key} (${component.label})`,\n value: component.key,\n });\n }\n });\n return values;\n}\nexports.getContextButtons = getContextButtons;\n// Tags that could be in text, that should be ommited or handled in a special way\nconst inTextTags = ['#text', 'A', 'B', 'EM', 'I', 'SMALL', 'STRONG', 'SUB', 'SUP', 'INS', 'DEL', 'MARK', 'CODE'];\n/**\n * Helper function for 'translateHTMLTemplate'. Translates text value of the passed html element.\n *\n * @param {HTMLElement} elem\n * @param {Function} translate\n *\n * @returns {String}\n * Translated element template.\n */\nfunction translateElemValue(elem, translate) {\n if (!elem.innerText) {\n return elem.innerHTML;\n }\n const elemValue = elem.innerText.replace(Evaluator_1.default.templateSettings.interpolate, '').replace(/\\s\\s+/g, ' ').trim();\n const translatedValue = translate(elemValue);\n if (elemValue !== translatedValue) {\n const links = elem.innerHTML.match(/<a[^>]*>(.*?)<\\/a>/g);\n if (links && links.length) {\n if (links.length === 1 && links[0].length === elem.innerHTML.length) {\n return elem.innerHTML.replace(elemValue, translatedValue);\n }\n const translatedLinks = links.map(link => {\n const linkElem = document.createElement('a');\n linkElem.innerHTML = link;\n return translateElemValue(linkElem, translate);\n });\n return `${translatedValue} (${translatedLinks.join(', ')})`;\n }\n else {\n return elem.innerText.replace(elemValue, translatedValue);\n }\n }\n else {\n return elem.innerHTML;\n }\n}\n/**\n * Helper function for 'translateHTMLTemplate'. Goes deep through html tag children and calls function to translate their text values.\n *\n * @param {HTMLElement} tag\n * @param {Function} translate\n *\n * @returns {void}\n */\nfunction translateDeepTag(tag, translate) {\n const children = tag.children.length && [...tag.children];\n const shouldTranslateEntireContent = children && children.every(child => child.children.length === 0\n && inTextTags.some(tag => child.nodeName === tag));\n if (!children || shouldTranslateEntireContent) {\n tag.innerHTML = translateElemValue(tag, translate);\n }\n else {\n children.forEach(child => translateDeepTag(child, translate));\n }\n}\n/**\n * Translates text values in html template.\n *\n * @param {String} template\n * @param {Function} translate\n *\n * @returns {String}\n * Html template with translated values.\n */\nfunction translateHTMLTemplate(template, translate) {\n const isHTML = /<[^>]*>/.test(template);\n if (!isHTML) {\n return translate(template);\n }\n const tempElem = document.createElement('div');\n tempElem.innerHTML = template;\n if (tempElem.innerText && tempElem.children.length) {\n translateDeepTag(tempElem, translate);\n return tempElem.innerHTML;\n }\n return template;\n}\nexports.translateHTMLTemplate = translateHTMLTemplate;\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n if (typeof dompurify_1.default.sanitize !== 'function') {\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target'],\n USE_PROFILES: { html: true }\n };\n // Use profiles\n if (options.sanitizeConfig && options.sanitizeConfig.useProfiles) {\n Object.keys(options.sanitizeConfig.useProfiles).forEach(key => {\n sanitizeOptions.USE_PROFILES[key] = options.sanitizeConfig.useProfiles[key];\n });\n }\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n const allowedUriRegex = options.sanitizeConfig.allowedUriRegex;\n sanitizeOptions.ALLOWED_URI_REGEXP = lodash_1.default.isString(allowedUriRegex) ? new RegExp(allowedUriRegex) : allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify_1.default.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n/**\n * Fast cloneDeep for JSON objects only.\n */\nfunction fastCloneDeep(obj) {\n return obj ? JSON.parse(JSON.stringify(obj)) : obj;\n}\nexports.fastCloneDeep = fastCloneDeep;\nfunction isInputComponent(componentJson) {\n if (componentJson.input === false || componentJson.input === true) {\n return componentJson.input;\n }\n switch (componentJson.type) {\n case 'htmlelement':\n case 'content':\n case 'columns':\n case 'fieldset':\n case 'panel':\n case 'table':\n case 'tabs':\n case 'well':\n case 'button':\n return false;\n default:\n return true;\n }\n}\nexports.isInputComponent = isInputComponent;\nfunction getArrayFromComponentPath(pathStr) {\n if (!pathStr || !lodash_1.default.isString(pathStr)) {\n if (!lodash_1.default.isArray(pathStr)) {\n return [pathStr];\n }\n return pathStr;\n }\n return pathStr.replace(/[[\\]]/g, '.')\n .replace(/\\.\\./g, '.')\n .replace(/(^\\.)|(\\.$)/g, '')\n .split('.')\n .map(part => lodash_1.default.defaultTo(lodash_1.default.toNumber(part), part));\n}\nexports.getArrayFromComponentPath = getArrayFromComponentPath;\nfunction isChildOf(child, parent) {\n while (child && child.parent) {\n if (child.parent === parent) {\n return true;\n }\n child = child.parent;\n }\n return false;\n}\nexports.isChildOf = isChildOf;\nfunction getStringFromComponentPath(path) {\n if (!lodash_1.default.isArray(path)) {\n return path;\n }\n let strPath = '';\n path.forEach((part, i) => {\n if (lodash_1.default.isNumber(part)) {\n strPath += `[${part}]`;\n }\n else {\n strPath += i === 0 ? part : `.${part}`;\n }\n });\n return strPath;\n}\nexports.getStringFromComponentPath = getStringFromComponentPath;\nfunction round(number, precision) {\n if (lodash_1.default.isNumber(number)) {\n return number.toFixed(precision);\n }\n return number;\n}\nexports.round = round;\n/**\n * Check for Internet Explorer browser version\n *\n * @return {(number|null)}\n */\nfunction getIEBrowserVersion() {\n const { ie, version } = getBrowserInfo();\n return ie ? version : null;\n}\nexports.getIEBrowserVersion = getIEBrowserVersion;\n/**\n * Get browser name and version (modified from 'jquery-browser-plugin')\n *\n * @return {Object} -- {{browser name, version, isWebkit?}}\n * Possible browser names: chrome, safari, ie, edge, opera, mozilla, yabrowser\n */\nfunction getBrowserInfo() {\n const browser = {};\n if (typeof window === 'undefined') {\n return browser;\n }\n const ua = window.navigator.userAgent.toLowerCase();\n const match = /(edge|edg)\\/([\\w.]+)/.exec(ua) ||\n /(opr)[/]([\\w.]+)/.exec(ua) ||\n /(yabrowser)[ /]([\\w.]+)/.exec(ua) ||\n /(chrome)[ /]([\\w.]+)/.exec(ua) ||\n /(iemobile)[/]([\\w.]+)/.exec(ua) ||\n /(version)(applewebkit)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+).*(version)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+)/.exec(ua) ||\n /(opera)(?:.*version|)[ /]([\\w.]+)/.exec(ua) ||\n /(msie) ([\\w.]+)/.exec(ua) ||\n ua.indexOf('trident') >= 0 && /(rv)(?::| )([\\w.]+)/.exec(ua) ||\n ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n [];\n const matched = {\n browser: match[5] || match[3] || match[1] || '',\n version: match[4] || match[2] || '0'\n };\n if (matched.browser) {\n browser[matched.browser] = true;\n browser.version = parseInt(matched.version, 10);\n }\n // Chrome, Opera 15+, Safari and Yandex.Browser are webkit based browsers\n if (browser.chrome || browser.opr || browser.safari || browser.edg || browser.yabrowser) {\n browser.isWebkit = true;\n }\n // IE11 has a new token so we will assign it ie to avoid breaking changes\n if (browser.rv || browser.iemobile) {\n browser.ie = true;\n }\n // Edge has a new token since it became webkit based\n if (browser.edg) {\n browser.edge = true;\n }\n // Opera 15+ are identified as opr\n if (browser.opr) {\n browser.opera = true;\n }\n return browser;\n}\nexports.getBrowserInfo = getBrowserInfo;\nfunction getComponentPathWithoutIndicies(path = '') {\n return path.replace(/\\[\\d+\\]/, '');\n}\nexports.getComponentPathWithoutIndicies = getComponentPathWithoutIndicies;\n/**\n * Returns a path to the component which based on its schema\n * @param {*} component is a component's schema containing link to its parent's schema in the 'parent' property\n */\nfunction getComponentPath(component, path = '') {\n var _a;\n if (!component || !component.key || ((_a = component === null || component === void 0 ? void 0 : component._form) === null || _a === void 0 ? void 0 : _a.display) === 'wizard') { // unlike the Webform, the Wizard has the key and it is a duplicate of the panel key\n return path;\n }\n path = component.isInputComponent || component.input === true ? `${component.key}${path ? '.' : ''}${path}` : path;\n return getComponentPath(component.parent, path);\n}\nexports.getComponentPath = getComponentPath;\n/**\n * Returns a parent component of the passed component instance skipping all the Layout components\n * @param {*} componentInstance\n * @return {(Component|undefined)}\n */\nfunction getDataParentComponent(componentInstance) {\n if (!componentInstance) {\n return;\n }\n const { parent } = componentInstance;\n if (parent && (parent.isInputComponent || parent.input)) {\n return parent;\n }\n else {\n return getDataParentComponent(parent);\n }\n}\nexports.getDataParentComponent = getDataParentComponent;\n/**\n * Returns whether the value is a promise\n * @param value\n * @return {boolean}\n */\nfunction isPromise(value) {\n return value\n && value.then\n && typeof value.then === 'function'\n && Object.prototype.toString.call(value) === '[object Promise]';\n}\nexports.isPromise = isPromise;\n/**\n * Determines if the component has a scoping parent in tree (a component which scopes its children and manages its\n * changes by itself, e.g. EditGrid)\n * @param componentInstance\n * @param firstPass\n * @returns {boolean|boolean|*}\n */\nfunction isInsideScopingComponent(componentInstance, firstPass = true) {\n if (!firstPass && (componentInstance === null || componentInstance === void 0 ? void 0 : componentInstance.hasScopedChildren)) {\n return true;\n }\n const dataParent = getDataParentComponent(componentInstance);\n if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.hasScopedChildren) {\n return true;\n }\n else if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.parent) {\n return isInsideScopingComponent(dataParent.parent, false);\n }\n return false;\n}\nexports.isInsideScopingComponent = isInsideScopingComponent;\nfunction getFocusableElements(element) {\n const focusableSelector = `button:not([disabled]), input:not([disabled]), select:not([disabled]),\n textarea:not([disabled]), button:not([disabled]), [href]`;\n return element.querySelectorAll(focusableSelector);\n}\nexports.getFocusableElements = getFocusableElements;\nexports.componentValueTypes = {\n number: 'number',\n string: 'string',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n date: 'date',\n any: 'any',\n};\nfunction getComponentSavedTypes(fullSchema) {\n const schema = fullSchema || {};\n if (schema.persistent !== true) {\n return [];\n }\n if (schema.multiple) {\n return [exports.componentValueTypes.array];\n }\n return null;\n}\nexports.getComponentSavedTypes = getComponentSavedTypes;\n/**\n * Interpolates @formio/core errors so that they are compatible with the renderer\n * @param {FieldError[]} errors\n * @param firstPass\n * @returns {[]}\n */\nconst interpolateErrors = (component, errors, interpolateFn) => {\n return errors.map((error) => {\n error.component = component;\n const { errorKeyOrMessage, context } = error;\n const toInterpolate = component.errors && component.errors[errorKeyOrMessage] ? component.errors[errorKeyOrMessage] : errorKeyOrMessage;\n return Object.assign(Object.assign({}, error), { message: unescapeHTML(interpolateFn(toInterpolate, context)), context: Object.assign({}, context) });\n });\n};\nexports.interpolateErrors = interpolateErrors;\nfunction getItemTemplateKeys(template) {\n const templateKeys = [];\n if (!template) {\n return templateKeys;\n }\n const keys = template.match(/({{\\s*(.*?)\\s*}})/g);\n if (keys) {\n keys.forEach((key) => {\n const propKey = key.match(/{{\\s*item\\.(.*?)\\s*}}/);\n if (propKey && propKey.length > 1) {\n templateKeys.push(propKey[1]);\n }\n });\n }\n return templateKeys;\n}\nexports.getItemTemplateKeys = getItemTemplateKeys;\nfunction isSelectResourceWithObjectValue(comp = {}) {\n const { reference, dataSrc, valueProperty } = comp;\n return reference || (dataSrc === 'resource' && (!valueProperty || valueProperty === 'data'));\n}\nexports.isSelectResourceWithObjectValue = isSelectResourceWithObjectValue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/utils.js?");
8338
+ eval("\n/* global jQuery */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.withSwitch = exports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.moment = exports.ConditionOperators = exports.jsonLogic = void 0;\nexports.isSelectResourceWithObjectValue = exports.getItemTemplateKeys = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isInsideScopingComponent = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = void 0;\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nexports._ = lodash_1.default;\nconst fetch_ponyfill_1 = __importDefault(__webpack_require__(/*! fetch-ponyfill */ \"./node_modules/fetch-ponyfill/build/fetch-browser.js\"));\nconst json_logic_js_1 = __importDefault(__webpack_require__(/*! json-logic-js */ \"./node_modules/json-logic-js/logic.js\"));\nexports.jsonLogic = json_logic_js_1.default;\nconst moment_timezone_1 = __importDefault(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nconst jstimezonedetect_1 = __importDefault(__webpack_require__(/*! jstimezonedetect */ \"./node_modules/jstimezonedetect/dist/jstz.min.js\"));\nconst operators_1 = __webpack_require__(/*! ./jsonlogic/operators */ \"./lib/cjs/utils/jsonlogic/operators.js\");\nconst dompurify_1 = __importDefault(__webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.js\"));\nconst formUtils_1 = __webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\");\nconst Evaluator_1 = __importDefault(__webpack_require__(/*! ./Evaluator */ \"./lib/cjs/utils/Evaluator.js\"));\nexports.Evaluator = Evaluator_1.default;\nconst conditionOperators_1 = __importDefault(__webpack_require__(/*! ./conditionOperators */ \"./lib/cjs/utils/conditionOperators/index.js\"));\nexports.ConditionOperators = conditionOperators_1.default;\nconst interpolate = Evaluator_1.default.interpolate;\nexports.interpolate = interpolate;\nconst { fetch } = (0, fetch_ponyfill_1.default)({\n Promise: Promise\n});\n__exportStar(__webpack_require__(/*! ./formUtils */ \"./lib/cjs/utils/formUtils.js\"), exports);\n// Configure JsonLogic\noperators_1.lodashOperators.forEach((name) => json_logic_js_1.default.add_operation(`_${name}`, lodash_1.default[name]));\n// Retrieve Any Date\njson_logic_js_1.default.add_operation('getDate', (date) => {\n return (0, moment_timezone_1.default)(date).toISOString();\n});\n// Set Relative Minimum Date\njson_logic_js_1.default.add_operation('relativeMinDate', (relativeMinDate) => {\n return (0, moment_timezone_1.default)().subtract(relativeMinDate, 'days').toISOString();\n});\n// Set Relative Maximum Date\njson_logic_js_1.default.add_operation('relativeMaxDate', (relativeMaxDate) => {\n return (0, moment_timezone_1.default)().add(relativeMaxDate, 'days').toISOString();\n});\nexports.moment = __importStar(__webpack_require__(/*! moment-timezone/moment-timezone */ \"./node_modules/moment-timezone/moment-timezone.js\"));\nfunction setPathToComponentAndPerentSchema(component) {\n component.path = getComponentPath(component);\n const dataParent = getDataParentComponent(component);\n if (dataParent && typeof dataParent === 'object') {\n dataParent.path = getComponentPath(dataParent);\n }\n}\n/**\n * Evaluate a method.\n *\n * @param func\n * @param args\n * @return {*}\n */\nfunction evaluate(func, args, ret, tokenize) {\n let returnVal = null;\n const component = args.component ? args.component : { key: 'unknown' };\n if (!args.form && args.instance) {\n args.form = lodash_1.default.get(args.instance, 'root._form', {});\n }\n const componentKey = component.key;\n if (typeof func === 'string') {\n if (ret) {\n func += `;return ${ret}`;\n }\n if (tokenize) {\n // Replace all {{ }} references with actual data.\n func = func.replace(/({{\\s+(.*)\\s+}})/, (match, $1, $2) => {\n if ($2.indexOf('data.') === 0) {\n return lodash_1.default.get(args.data, $2.replace('data.', ''));\n }\n else if ($2.indexOf('row.') === 0) {\n return lodash_1.default.get(args.row, $2.replace('row.', ''));\n }\n // Support legacy...\n return lodash_1.default.get(args.data, $2);\n });\n }\n try {\n func = Evaluator_1.default.evaluator(func, args);\n args = lodash_1.default.values(args);\n }\n catch (err) {\n console.warn(`An error occured within the custom function for ${componentKey}`, err);\n returnVal = null;\n func = false;\n }\n }\n if (typeof func === 'function') {\n try {\n returnVal = Evaluator_1.default.evaluate(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (typeof func === 'object') {\n try {\n returnVal = json_logic_js_1.default.apply(func, args);\n }\n catch (err) {\n returnVal = null;\n console.warn(`An error occured within custom function for ${componentKey}`, err);\n }\n }\n else if (func) {\n console.warn(`Unknown function type for ${componentKey}`);\n }\n return returnVal;\n}\nexports.evaluate = evaluate;\nfunction getRandomComponentId() {\n return `e${Math.random().toString(36).substring(7)}`;\n}\nexports.getRandomComponentId = getRandomComponentId;\n/**\n * Get a property value of an element.\n *\n * @param style\n * @param prop\n * @return {number}\n */\nfunction getPropertyValue(style, prop) {\n let value = style.getPropertyValue(prop);\n value = value ? value.replace(/[^0-9.]/g, '') : '0';\n return parseFloat(value);\n}\nexports.getPropertyValue = getPropertyValue;\n/**\n * Get an elements bounding rectagle.\n *\n * @param element\n * @return {{x: string, y: string, width: string, height: string}}\n */\nfunction getElementRect(element) {\n const style = window.getComputedStyle(element, null);\n return {\n x: getPropertyValue(style, 'left'),\n y: getPropertyValue(style, 'top'),\n width: getPropertyValue(style, 'width'),\n height: getPropertyValue(style, 'height')\n };\n}\nexports.getElementRect = getElementRect;\n/**\n * Get non HTMLElement property in the window object\n * @param {String} property\n * @return {any || undefined}\n */\nfunction getScriptPlugin(property) {\n const obj = window[property];\n if (typeof HTMLElement === 'object' ? obj instanceof HTMLElement : //DOM2\n obj && typeof obj === 'object' && true && obj.nodeType === 1 && typeof obj.nodeName === 'string') {\n return undefined;\n }\n return obj;\n}\nexports.getScriptPlugin = getScriptPlugin;\n/**\n * Determines the boolean value of a setting.\n *\n * @param value\n * @return {boolean}\n */\nfunction boolValue(value) {\n if (lodash_1.default.isBoolean(value)) {\n return value;\n }\n else if (lodash_1.default.isString(value)) {\n return (value.toLowerCase() === 'true');\n }\n else {\n return !!value;\n }\n}\nexports.boolValue = boolValue;\n/**\n * Check to see if an ID is a mongoID.\n * @param text\n * @return {Array|{index: number, input: string}|Boolean|*}\n */\nfunction isMongoId(text) {\n return text.toString().match(/^[0-9a-fA-F]{24}$/);\n}\nexports.isMongoId = isMongoId;\n/**\n * Checks the calculated value for a provided component and data.\n *\n * @param {Object} component\n * The component to check for the calculated value.\n * @param {Object} submission\n * A submission object.\n * @param data\n * The full submission data.\n */\nfunction checkCalculated(component, submission, rowData) {\n // Process calculated value stuff if present.\n if (component.calculateValue) {\n lodash_1.default.set(rowData, component.key, evaluate(component.calculateValue, {\n value: undefined,\n data: submission ? submission.data : rowData,\n row: rowData,\n util: this,\n component\n }, 'value'));\n }\n}\nexports.checkCalculated = checkCalculated;\n/**\n * Check if a simple conditional evaluates to true.\n *\n * @param condition\n * @param condition\n * @param row\n * @param data\n * @param instance\n * @returns {boolean}\n */\nfunction checkSimpleConditional(component, condition, row, data, instance) {\n if (condition.when) {\n const value = getComponentActualValue(condition.when, data, row);\n const eq = String(condition.eq);\n const show = String(condition.show);\n // Special check for selectboxes component.\n if (lodash_1.default.isObject(value) && lodash_1.default.has(value, condition.eq)) {\n return String(value[condition.eq]) === show;\n }\n // FOR-179 - Check for multiple values.\n if (Array.isArray(value) && value.map(String).includes(eq)) {\n return show === 'true';\n }\n return (String(value) === eq) === (show === 'true');\n }\n else {\n const { conditions = [], conjunction = 'all', show = true } = condition;\n if (!conditions.length) {\n return true;\n }\n const conditionsResult = lodash_1.default.map(conditions, (cond) => {\n const { value: comparedValue, operator, component: conditionComponentPath } = cond;\n if (!conditionComponentPath) {\n return true;\n }\n const value = getComponentActualValue(conditionComponentPath, data, row);\n const ConditionOperator = conditionOperators_1.default[operator];\n return ConditionOperator\n ? new ConditionOperator().getResult({ value, comparedValue, instance, component, conditionComponentPath })\n : true;\n });\n let result = false;\n switch (conjunction) {\n case 'any':\n result = lodash_1.default.some(conditionsResult, res => !!res);\n break;\n default:\n result = lodash_1.default.every(conditionsResult, res => !!res);\n }\n return show ? result : !result;\n }\n}\nexports.checkSimpleConditional = checkSimpleConditional;\nfunction getComponentActualValue(compPath, data, row) {\n let value = null;\n if (row) {\n value = (0, formUtils_1.getValue)({ data: row }, compPath);\n }\n if (data && lodash_1.default.isNil(value)) {\n value = (0, formUtils_1.getValue)({ data }, compPath);\n }\n // FOR-400 - Fix issue where falsey values were being evaluated as show=true\n if (lodash_1.default.isNil(value) || (lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value))) {\n value = '';\n }\n return value;\n}\nexports.getComponentActualValue = getComponentActualValue;\n/**\n * Check custom javascript conditional.\n *\n * @param component\n * @param custom\n * @param row\n * @param data\n * @returns {*}\n */\nfunction checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {\n if (typeof custom === 'string') {\n custom = `var ${variable} = true; ${custom}; return ${variable};`;\n }\n const value = (instance && instance.evaluate) ?\n instance.evaluate(custom, { row, data, form }) :\n evaluate(custom, { row, data, form });\n if (value === null) {\n return onError;\n }\n return value;\n}\nexports.checkCustomConditional = checkCustomConditional;\nfunction checkJsonConditional(component, json, row, data, form, onError) {\n try {\n return json_logic_js_1.default.apply(json, {\n data,\n row,\n form,\n _: lodash_1.default,\n });\n }\n catch (err) {\n console.warn(`An error occurred in jsonLogic advanced condition for ${component.key}`, err);\n return onError;\n }\n}\nexports.checkJsonConditional = checkJsonConditional;\nfunction getRow(component, row, instance, conditional) {\n var _a;\n const condition = conditional || component.conditional;\n // If no component's instance passed (happens only in 6.x server), calculate its path based on the schema\n if (!instance) {\n instance = lodash_1.default.cloneDeep(component);\n setPathToComponentAndPerentSchema(instance);\n }\n const dataParent = getDataParentComponent(instance);\n const parentPath = dataParent ? getComponentPath(dataParent) : null;\n const isTriggerCondtionComponentPath = condition.when || !condition.conditions\n ? (_a = condition.when) === null || _a === void 0 ? void 0 : _a.startsWith(parentPath)\n : lodash_1.default.some(condition.conditions, cond => cond.component.startsWith(parentPath));\n if (dataParent && isTriggerCondtionComponentPath) {\n const newRow = {};\n lodash_1.default.set(newRow, parentPath, row);\n row = newRow;\n }\n return row;\n}\n/**\n * Checks the conditions for a provided component and data.\n *\n * @param component\n * The component to check for the condition.\n * @param row\n * The data within a row\n * @param data\n * The full submission data.\n *\n * @returns {boolean}\n */\nfunction checkCondition(component, row, data, form, instance) {\n const { customConditional, conditional } = component;\n if (customConditional) {\n return checkCustomConditional(component, customConditional, row, data, form, 'show', true, instance);\n }\n else if (conditional && (conditional.when || lodash_1.default.some(conditional.conditions || [], condition => condition.component && condition.operator))) {\n row = getRow(component, row, instance);\n return checkSimpleConditional(component, conditional, row, data, instance);\n }\n else if (conditional && conditional.json) {\n return checkJsonConditional(component, conditional.json, row, data, form, true);\n }\n // Default to show.\n return true;\n}\nexports.checkCondition = checkCondition;\n/**\n * Test a trigger on a component.\n *\n * @param component\n * @param action\n * @param data\n * @param row\n * @returns {mixed}\n */\nfunction checkTrigger(component, trigger, row, data, form, instance) {\n // If trigger is empty, don't fire it\n if (!trigger || !trigger[trigger.type]) {\n return false;\n }\n switch (trigger.type) {\n case 'simple':\n row = getRow(component, row, instance, trigger.simple);\n return checkSimpleConditional(component, trigger.simple, row, data, instance);\n case 'javascript':\n return checkCustomConditional(component, trigger.javascript, row, data, form, 'result', false, instance);\n case 'json':\n return checkJsonConditional(component, trigger.json, row, data, form, false);\n }\n // If none of the types matched, don't fire the trigger.\n return false;\n}\nexports.checkTrigger = checkTrigger;\nfunction setActionProperty(component, action, result, row, data, instance) {\n const property = action.property.value;\n switch (action.property.type) {\n case 'boolean': {\n const currentValue = lodash_1.default.get(component, property, false).toString();\n const newValue = action.state.toString();\n if (currentValue !== newValue) {\n lodash_1.default.set(component, property, newValue === 'true');\n }\n break;\n }\n case 'string': {\n const evalData = {\n data,\n row,\n component,\n result,\n };\n const textValue = action.property.component ? action[action.property.component] : action.text;\n const currentValue = lodash_1.default.get(component, property, '');\n const newValue = (instance && instance.interpolate)\n ? instance.interpolate(textValue, evalData)\n : Evaluator_1.default.interpolate(textValue, evalData);\n if (newValue !== currentValue) {\n lodash_1.default.set(component, property, newValue);\n }\n break;\n }\n }\n return component;\n}\nexports.setActionProperty = setActionProperty;\n/**\n * Unescape HTML characters like &lt, &gt, &amp and etc.\n * @param str\n * @returns {string}\n */\nfunction unescapeHTML(str) {\n if (typeof window === 'undefined' || !('DOMParser' in window)) {\n return str;\n }\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.documentElement.textContent;\n}\nexports.unescapeHTML = unescapeHTML;\n/**\n * Make HTML element from string\n * @param str\n * @param selector\n * @returns {HTMLElement}\n */\nfunction convertStringToHTMLElement(str, selector) {\n const doc = new window.DOMParser().parseFromString(str, 'text/html');\n return doc.body.querySelector(selector);\n}\nexports.convertStringToHTMLElement = convertStringToHTMLElement;\n/**\n * Make a filename guaranteed to be unique.\n * @param name\n * @param template\n * @param evalContext\n * @returns {string}\n */\nfunction uniqueName(name, template, evalContext) {\n template = template || '{{fileName}}-{{guid}}';\n //include guid in template anyway, to prevent overwriting issue if filename matches existing file\n if (!template.includes('{{guid}}')) {\n template = `${template}-{{guid}}`;\n }\n const parts = name.split('.');\n let fileName = parts.slice(0, parts.length - 1).join('.');\n const extension = parts.length > 1\n ? `.${lodash_1.default.last(parts)}`\n : '';\n //allow only 100 characters from original name to avoid issues with filename length restrictions\n fileName = fileName.substr(0, 100);\n evalContext = Object.assign(evalContext || {}, {\n fileName,\n guid: guid()\n });\n //only letters, numbers, dots, dashes, underscores and spaces are allowed. Anything else will be replaced with dash\n const uniqueName = `${Evaluator_1.default.interpolate(template, evalContext)}${extension}`.replace(/[^0-9a-zA-Z.\\-_ ]/g, '-');\n return uniqueName;\n}\nexports.uniqueName = uniqueName;\nfunction guid() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x'\n ? r\n : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\nexports.guid = guid;\n/**\n * Return a translated date setting.\n *\n * @param date\n * @return {(null|Date)}\n */\nfunction getDateSetting(date) {\n if (lodash_1.default.isNil(date) || lodash_1.default.isNaN(date) || date === '') {\n return null;\n }\n if (date instanceof Date) {\n return date;\n }\n else if (typeof date.toDate === 'function') {\n return date.isValid() ? date.toDate() : null;\n }\n let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? (0, moment_timezone_1.default)(date) : null;\n if (dateSetting && dateSetting.isValid()) {\n return dateSetting.toDate();\n }\n dateSetting = null;\n try {\n const value = Evaluator_1.default.evaluator(`return ${date};`, 'moment')(moment_timezone_1.default);\n if (typeof value === 'string') {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n else if (typeof value.toDate === 'function') {\n dateSetting = (0, moment_timezone_1.default)(value.toDate().toUTCString());\n }\n else if (value instanceof Date) {\n dateSetting = (0, moment_timezone_1.default)(value);\n }\n }\n catch (e) {\n return null;\n }\n if (!dateSetting) {\n return null;\n }\n // Ensure this is a date.\n if (!dateSetting.isValid()) {\n return null;\n }\n return dateSetting.toDate();\n}\nexports.getDateSetting = getDateSetting;\nfunction isValidDate(date) {\n return lodash_1.default.isDate(date) && !lodash_1.default.isNaN(date.getDate());\n}\nexports.isValidDate = isValidDate;\n/**\n * Get the current timezone string.\n *\n * @return {string}\n */\nfunction currentTimezone() {\n if (moment_timezone_1.default.currentTimezone) {\n return moment_timezone_1.default.currentTimezone;\n }\n moment_timezone_1.default.currentTimezone = jstimezonedetect_1.default.determine().name();\n return moment_timezone_1.default.currentTimezone;\n}\nexports.currentTimezone = currentTimezone;\n/**\n * Get an offset date provided a date object and timezone object.\n *\n * @param date\n * @param timezone\n * @return {Date}\n */\nfunction offsetDate(date, timezone) {\n if (timezone === 'UTC') {\n return {\n date: new Date(date.getTime() + (date.getTimezoneOffset() * 60000)),\n abbr: 'UTC'\n };\n }\n const dateMoment = (0, moment_timezone_1.default)(date).tz(timezone);\n return {\n date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)),\n abbr: dateMoment.format('z')\n };\n}\nexports.offsetDate = offsetDate;\n/**\n * Returns if the zones are loaded.\n *\n * @return {boolean}\n */\nfunction zonesLoaded() {\n return moment_timezone_1.default.zonesLoaded;\n}\nexports.zonesLoaded = zonesLoaded;\n/**\n * Returns if we should load the zones.\n *\n * @param timezone\n * @return {boolean}\n */\nfunction shouldLoadZones(timezone) {\n if (timezone === currentTimezone() || timezone === 'UTC') {\n return false;\n }\n return true;\n}\nexports.shouldLoadZones = shouldLoadZones;\n/**\n * Externally load the timezone data.\n *\n * @return {Promise<any> | *}\n */\nfunction loadZones(url, timezone) {\n if (timezone && !shouldLoadZones(timezone)) {\n // Return non-resolving promise.\n return new Promise(lodash_1.default.noop);\n }\n if (moment_timezone_1.default.zonesPromise) {\n return moment_timezone_1.default.zonesPromise;\n }\n return moment_timezone_1.default.zonesPromise = fetch(url)\n .then(resp => resp.json().then(zones => {\n moment_timezone_1.default.tz.load(zones);\n moment_timezone_1.default.zonesLoaded = true;\n // Trigger a global event that the timezones have finished loading.\n if (document && document.createEvent && document.body && document.body.dispatchEvent) {\n var event = document.createEvent('Event');\n event.initEvent('zonesLoaded', true, true);\n document.body.dispatchEvent(event);\n }\n }));\n}\nexports.loadZones = loadZones;\n/**\n * Get the moment date object for translating dates with timezones.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {*}\n */\nfunction momentDate(value, format, timezone) {\n const momentDate = (0, moment_timezone_1.default)(value);\n if (!timezone) {\n return momentDate;\n }\n if (timezone === 'UTC') {\n timezone = 'Etc/UTC';\n }\n if ((timezone !== currentTimezone() || (format && format.match(/\\s(z$|z\\s)/))) && moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone);\n }\n return momentDate;\n}\nexports.momentDate = momentDate;\n/**\n * Format a date provided a value, format, and timezone object.\n *\n * @param value\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) {\n const momentDate = (0, moment_timezone_1.default)(value, flatPickrInputFormat || undefined);\n if (timezone === currentTimezone()) {\n // See if our format contains a \"z\" timezone character.\n if (format.match(/\\s(z$|z\\s)/)) {\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n return momentDate.tz(timezone).format(convertFormatToMoment(format));\n }\n else {\n return momentDate.format(convertFormatToMoment(format.replace(/\\s(z$|z\\s)/, '')));\n }\n }\n // Return the standard format.\n return momentDate.format(convertFormatToMoment(format));\n }\n if (timezone === 'UTC') {\n const offset = offsetDate(momentDate.toDate(), 'UTC');\n return `${(0, moment_timezone_1.default)(offset.date).format(convertFormatToMoment(format))} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded && timezone) {\n return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`);\n }\n else {\n return momentDate.format(convertFormatToMoment(format));\n }\n}\nexports.formatDate = formatDate;\n/**\n * Pass a format function to format within a timezone.\n *\n * @param formatFn\n * @param date\n * @param format\n * @param timezone\n * @return {string}\n */\nfunction formatOffset(timezonesUrl, formatFn, date, format, timezone) {\n if (timezone === currentTimezone()) {\n return formatFn(date, format);\n }\n if (timezone === 'UTC') {\n return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`;\n }\n // Load the zones since we need timezone information.\n loadZones(timezonesUrl);\n if (moment_timezone_1.default.zonesLoaded) {\n const offset = offsetDate(date, timezone);\n return `${formatFn(offset.date, format)} ${offset.abbr}`;\n }\n else {\n return formatFn(date, format);\n }\n}\nexports.formatOffset = formatOffset;\nfunction getLocaleDateFormatInfo(locale) {\n const formatInfo = {};\n const day = 21;\n const exampleDate = new Date(2017, 11, day);\n const localDateString = exampleDate.toLocaleDateString(locale);\n formatInfo.dayFirst = localDateString.slice(0, 2) === day.toString();\n return formatInfo;\n}\nexports.getLocaleDateFormatInfo = getLocaleDateFormatInfo;\n/**\n * Convert the format from the angular-datepicker module to flatpickr format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToFlatpickr(format) {\n return format\n // Remove the Z timezone offset, not supported by flatpickr.\n .replace(/Z/g, '')\n // Year conversion.\n .replace(/y/g, 'Y')\n .replace('YYYY', 'Y')\n .replace('YY', 'y')\n // Month conversion.\n .replace('MMMM', 'F')\n .replace(/M/g, 'n')\n .replace('nnn', 'M')\n .replace('nn', 'm')\n // Day in month.\n .replace(/d/g, 'j')\n .replace(/jj/g, 'd')\n // Day in week.\n .replace('EEEE', 'l')\n .replace('EEE', 'D')\n // Hours, minutes, seconds\n .replace('HH', 'H')\n .replace('hh', 'G')\n .replace('mm', 'i')\n .replace('ss', 'S')\n .replace(/a/g, 'K');\n}\nexports.convertFormatToFlatpickr = convertFormatToFlatpickr;\n/**\n * Convert the format from the angular-datepicker module to moment format.\n * @param format\n * @return {string}\n */\nfunction convertFormatToMoment(format) {\n return format\n // Year conversion.\n .replace(/y/g, 'Y')\n // Day in month.\n .replace(/d/g, 'D')\n // Day in week.\n .replace(/E/g, 'd')\n // AM/PM marker\n .replace(/a/g, 'A')\n // Unix Timestamp\n .replace(/U/g, 'X');\n}\nexports.convertFormatToMoment = convertFormatToMoment;\nfunction convertFormatToMask(format) {\n return format\n // Long month replacement.\n .replace(/M{4}/g, 'MM')\n // Initial short month conversion.\n .replace(/M{3}/g, '***')\n // Short month conversion if input as text.\n .replace(/e/g, 'Q')\n // Month number conversion.\n .replace(/W/g, '99')\n // Year conversion.\n .replace(/[ydhmswHMG]/g, '9')\n // AM/PM conversion.\n .replace(/a/g, 'AA');\n}\nexports.convertFormatToMask = convertFormatToMask;\n/**\n * Returns an input mask that is compatible with the input mask library.\n * @param {string} mask - The Form.io input mask.\n * @param {string} placeholderChar - Char which is used as a placeholder.\n * @returns {Array} - The input mask for the mask library.\n */\nfunction getInputMask(mask, placeholderChar) {\n if (mask instanceof Array) {\n return mask;\n }\n const maskArray = [];\n maskArray.numeric = true;\n for (let i = 0; i < mask.length; i++) {\n switch (mask[i]) {\n case '9':\n maskArray.push(/\\d/);\n break;\n case 'A':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z]/);\n break;\n case 'a':\n maskArray.numeric = false;\n maskArray.push(/[a-z]/);\n break;\n case '*':\n maskArray.numeric = false;\n maskArray.push(/[a-zA-Z0-9]/);\n break;\n // If char which is used inside mask placeholder was used in the mask, replace it with space to prevent errors\n case placeholderChar:\n maskArray.numeric = false;\n maskArray.push(' ');\n break;\n default:\n maskArray.numeric = false;\n maskArray.push(mask[i]);\n break;\n }\n }\n return maskArray;\n}\nexports.getInputMask = getInputMask;\nfunction unmaskValue(value, mask, placeholderChar) {\n if (!mask || !value || value.length > mask.length) {\n return value;\n }\n let unmaskedValue = value.split('');\n for (let i = 0; i < mask.length; i++) {\n const char = value[i] || '';\n const charPart = mask[i];\n if (!lodash_1.default.isRegExp(charPart) && char === charPart) {\n unmaskedValue[i] = '';\n }\n }\n unmaskedValue = unmaskedValue.join('').replace(placeholderChar, '');\n return unmaskedValue;\n}\nexports.unmaskValue = unmaskValue;\nfunction matchInputMask(value, inputMask) {\n if (!inputMask) {\n return true;\n }\n // If value is longer than mask, it isn't valid.\n if (value.length > inputMask.length) {\n return false;\n }\n for (let i = 0; i < inputMask.length; i++) {\n const char = value[i] || '';\n const charPart = inputMask[i];\n if (!(lodash_1.default.isRegExp(charPart) && charPart.test(char) || charPart === char)) {\n return false;\n }\n }\n return true;\n}\nexports.matchInputMask = matchInputMask;\nfunction getNumberSeparators(lang = 'en') {\n const formattedNumberString = (12345.6789).toLocaleString(lang);\n const delimeters = formattedNumberString.match(/..(.)...(.)../);\n if (!delimeters) {\n return {\n delimiter: ',',\n decimalSeparator: '.'\n };\n }\n return {\n delimiter: (delimeters.length > 1) ? delimeters[1] : ',',\n decimalSeparator: (delimeters.length > 2) ? delimeters[2] : '.',\n };\n}\nexports.getNumberSeparators = getNumberSeparators;\nfunction getNumberDecimalLimit(component, defaultLimit) {\n if (lodash_1.default.has(component, 'decimalLimit')) {\n return lodash_1.default.get(component, 'decimalLimit');\n }\n // Determine the decimal limit. Defaults to 20 but can be overridden by validate.step or decimalLimit settings.\n let decimalLimit = defaultLimit || 20;\n const step = lodash_1.default.get(component, 'validate.step', 'any');\n if (step !== 'any') {\n const parts = step.toString().split('.');\n if (parts.length > 1) {\n decimalLimit = parts[1].length;\n }\n }\n return decimalLimit;\n}\nexports.getNumberDecimalLimit = getNumberDecimalLimit;\nfunction getCurrencyAffixes({ currency, decimalLimit, decimalSeparator, lang, }) {\n // Get the prefix and suffix from the localized string.\n let regex = `(.*)?${(100).toLocaleString(lang)}`;\n if (decimalLimit) {\n regex += `${decimalSeparator === '.' ? '\\\\.' : decimalSeparator}${(0).toLocaleString(lang)}{${decimalLimit}}`;\n }\n regex += '(.*)?';\n const parts = (100).toLocaleString(lang, {\n style: 'currency',\n currency: currency ? currency : 'USD',\n useGrouping: true,\n maximumFractionDigits: decimalLimit || 0,\n minimumFractionDigits: decimalLimit || 0\n }).replace('.', decimalSeparator).match(new RegExp(regex));\n return {\n prefix: (parts === null || parts === void 0 ? void 0 : parts[1]) || '',\n suffix: (parts === null || parts === void 0 ? void 0 : parts[2]) || ''\n };\n}\nexports.getCurrencyAffixes = getCurrencyAffixes;\n/**\n * Fetch the field data provided a component.\n *\n * @param data\n * @param component\n * @return {*}\n */\nfunction fieldData(data, component) {\n if (!data) {\n return '';\n }\n if (!component || !component.key) {\n return data;\n }\n if (component.key.includes('.')) {\n let value = data;\n const parts = component.key.split('.');\n let key = '';\n for (let i = 0; i < parts.length; i++) {\n key = parts[i];\n // Handle nested resources\n if (value.hasOwnProperty('_id')) {\n value = value.data;\n }\n // Return if the key is not found on the value.\n if (!value.hasOwnProperty(key)) {\n return;\n }\n // Convert old single field data in submissions to multiple\n if (key === parts[parts.length - 1] && component.multiple && !Array.isArray(value[key])) {\n value[key] = [value[key]];\n }\n // Set the value of this key.\n value = value[key];\n }\n return value;\n }\n else {\n // Convert old single field data in submissions to multiple\n if (component.multiple && !Array.isArray(data[component.key])) {\n data[component.key] = [data[component.key]];\n }\n // Fix for checkbox type radio submission values in tableView\n if (component.type === 'checkbox' && component.inputType === 'radio') {\n return data[component.name] === component.value;\n }\n return data[component.key];\n }\n}\nexports.fieldData = fieldData;\n/**\n * Delays function execution with possibility to execute function synchronously or cancel it.\n *\n * @param fn Function to delay\n * @param delay Delay time\n * @return {*}\n */\nfunction delay(fn, delay = 0, ...args) {\n const timer = setTimeout(fn, delay, ...args);\n function cancel() {\n clearTimeout(timer);\n }\n function earlyCall() {\n cancel();\n return fn(...args);\n }\n earlyCall.timer = timer;\n earlyCall.cancel = cancel;\n return earlyCall;\n}\nexports.delay = delay;\n/**\n * Iterate the given key to make it unique.\n *\n * @param {String} key\n * Modify the component key to be unique.\n *\n * @returns {String}\n * The new component key.\n */\nfunction iterateKey(key) {\n if (!key.match(/(\\d+)$/)) {\n return `${key}1`;\n }\n return key.replace(/(\\d+)$/, function (suffix) {\n return Number(suffix) + 1;\n });\n}\nexports.iterateKey = iterateKey;\n/**\n * Determines a unique key within a map provided the base key.\n *\n * @param map\n * @param base\n * @return {*}\n */\nfunction uniqueKey(map, base) {\n let newKey = base;\n while (map.hasOwnProperty(newKey)) {\n newKey = iterateKey(newKey);\n }\n return newKey;\n}\nexports.uniqueKey = uniqueKey;\n/**\n * Determines the major version number of bootstrap.\n *\n * @return {number}\n */\nfunction bootstrapVersion(options) {\n if (options.bootstrap) {\n return options.bootstrap;\n }\n if ((typeof jQuery === 'function') && (typeof jQuery().collapse === 'function')) {\n return parseInt(jQuery.fn.collapse.Constructor.VERSION.split('.')[0], 10);\n }\n if (window.bootstrap && window.bootstrap.Collapse) {\n return parseInt(window.bootstrap.Collapse.VERSION.split('.')[0], 10);\n }\n return 0;\n}\nexports.bootstrapVersion = bootstrapVersion;\n/**\n * Retrun provided argument.\n * If argument is a function, returns the result of a function call.\n * @param {*} e;\n *\n * @return {*}\n */\nfunction unfold(e) {\n if (typeof e === 'function') {\n return e();\n }\n return e;\n}\nexports.unfold = unfold;\n/**\n * Map values through unfold and return first non-nil value.\n * @param {Array<T>} collection;\n *\n * @return {T}\n */\nexports.firstNonNil = lodash_1.default.flow([\n lodash_1.default.partialRight(lodash_1.default.map, unfold),\n lodash_1.default.partialRight(lodash_1.default.find, v => !lodash_1.default.isUndefined(v))\n]);\n/*\n * Create enclosed state.\n * Returns functions to getting and cycling between states.\n * @param {*} a - initial state.\n * @param {*} b - next state.\n * @return {Functions[]} -- [get, toggle];\n */\nfunction withSwitch(a, b) {\n let state = a;\n let next = b;\n function get() {\n return state;\n }\n function toggle() {\n const prev = state;\n state = next;\n next = prev;\n }\n return [get, toggle];\n}\nexports.withSwitch = withSwitch;\nfunction observeOverload(callback, options = {}) {\n const { limit = 50, delay = 500 } = options;\n let callCount = 0;\n let timeoutID = 0;\n const reset = () => callCount = 0;\n return () => {\n if (timeoutID !== 0) {\n clearTimeout(timeoutID);\n timeoutID = 0;\n }\n timeoutID = setTimeout(reset, delay);\n callCount += 1;\n if (callCount >= limit) {\n clearTimeout(timeoutID);\n reset();\n return callback();\n }\n };\n}\nexports.observeOverload = observeOverload;\nfunction getContextComponents(context, excludeNested, excludedTypes = []) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component, path) => {\n const addToContextComponents = excludeNested ? !component.tree : true;\n if (component.key !== context.data.key && addToContextComponents && !lodash_1.default.includes(excludedTypes, component.type)) {\n values.push({\n label: `${component.label || component.key} (${path})`,\n value: path,\n });\n }\n });\n return values;\n}\nexports.getContextComponents = getContextComponents;\nfunction getContextButtons(context) {\n const values = [];\n context.utils.eachComponent(context.instance.options.editForm.components, (component) => {\n if (component.type === 'button') {\n values.push({\n label: `${component.key} (${component.label})`,\n value: component.key,\n });\n }\n });\n return values;\n}\nexports.getContextButtons = getContextButtons;\n// Tags that could be in text, that should be ommited or handled in a special way\nconst inTextTags = ['#text', 'A', 'B', 'EM', 'I', 'SMALL', 'STRONG', 'SUB', 'SUP', 'INS', 'DEL', 'MARK', 'CODE'];\n/**\n * Helper function for 'translateHTMLTemplate'. Translates text value of the passed html element.\n *\n * @param {HTMLElement} elem\n * @param {Function} translate\n *\n * @returns {String}\n * Translated element template.\n */\nfunction translateElemValue(elem, translate) {\n if (!elem.innerText) {\n return elem.innerHTML;\n }\n const elemValue = elem.innerText.replace(Evaluator_1.default.templateSettings.interpolate, '').replace(/\\s\\s+/g, ' ').trim();\n const translatedValue = translate(elemValue);\n if (elemValue !== translatedValue) {\n const links = elem.innerHTML.match(/<a[^>]*>(.*?)<\\/a>/g);\n if (links && links.length) {\n if (links.length === 1 && links[0].length === elem.innerHTML.length) {\n return elem.innerHTML.replace(elemValue, translatedValue);\n }\n const translatedLinks = links.map(link => {\n const linkElem = document.createElement('a');\n linkElem.innerHTML = link;\n return translateElemValue(linkElem, translate);\n });\n return `${translatedValue} (${translatedLinks.join(', ')})`;\n }\n else {\n return elem.innerText.replace(elemValue, translatedValue);\n }\n }\n else {\n return elem.innerHTML;\n }\n}\n/**\n * Helper function for 'translateHTMLTemplate'. Goes deep through html tag children and calls function to translate their text values.\n *\n * @param {HTMLElement} tag\n * @param {Function} translate\n *\n * @returns {void}\n */\nfunction translateDeepTag(tag, translate) {\n const children = tag.children.length && [...tag.children];\n const shouldTranslateEntireContent = children && children.every(child => child.children.length === 0\n && inTextTags.some(tag => child.nodeName === tag));\n if (!children || shouldTranslateEntireContent) {\n tag.innerHTML = translateElemValue(tag, translate);\n }\n else {\n children.forEach(child => translateDeepTag(child, translate));\n }\n}\n/**\n * Translates text values in html template.\n *\n * @param {String} template\n * @param {Function} translate\n *\n * @returns {String}\n * Html template with translated values.\n */\nfunction translateHTMLTemplate(template, translate) {\n const isHTML = /<[^>]*>/.test(template);\n if (!isHTML) {\n return translate(template);\n }\n const tempElem = document.createElement('div');\n tempElem.innerHTML = template;\n if (tempElem.innerText && tempElem.children.length) {\n translateDeepTag(tempElem, translate);\n return tempElem.innerHTML;\n }\n return template;\n}\nexports.translateHTMLTemplate = translateHTMLTemplate;\n/**\n * Sanitize an html string.\n *\n * @param string\n * @returns {*}\n */\nfunction sanitize(string, options) {\n if (typeof dompurify_1.default.sanitize !== 'function') {\n return string;\n }\n // Dompurify configuration\n const sanitizeOptions = {\n ADD_ATTR: ['ref', 'target'],\n USE_PROFILES: { html: true }\n };\n // Use profiles\n if (options.sanitizeConfig && options.sanitizeConfig.useProfiles) {\n Object.keys(options.sanitizeConfig.useProfiles).forEach(key => {\n sanitizeOptions.USE_PROFILES[key] = options.sanitizeConfig.useProfiles[key];\n });\n }\n // Add attrs\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addAttr) && options.sanitizeConfig.addAttr.length > 0) {\n options.sanitizeConfig.addAttr.forEach((attr) => {\n sanitizeOptions.ADD_ATTR.push(attr);\n });\n }\n // Add tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addTags) && options.sanitizeConfig.addTags.length > 0) {\n sanitizeOptions.ADD_TAGS = options.sanitizeConfig.addTags;\n }\n // Allow tags\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedTags) && options.sanitizeConfig.allowedTags.length > 0) {\n sanitizeOptions.ALLOWED_TAGS = options.sanitizeConfig.allowedTags;\n }\n // Allow attributes\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.allowedAttrs) && options.sanitizeConfig.allowedAttrs.length > 0) {\n sanitizeOptions.ALLOWED_ATTR = options.sanitizeConfig.allowedAttrs;\n }\n // Allowd URI Regex\n if (options.sanitizeConfig && options.sanitizeConfig.allowedUriRegex) {\n const allowedUriRegex = options.sanitizeConfig.allowedUriRegex;\n sanitizeOptions.ALLOWED_URI_REGEXP = lodash_1.default.isString(allowedUriRegex) ? new RegExp(allowedUriRegex) : allowedUriRegex;\n }\n // Allow to extend the existing array of elements that are safe for URI-like values\n if (options.sanitizeConfig && Array.isArray(options.sanitizeConfig.addUriSafeAttr) && options.sanitizeConfig.addUriSafeAttr.length > 0) {\n sanitizeOptions.ADD_URI_SAFE_ATTR = options.sanitizeConfig.addUriSafeAttr;\n }\n return dompurify_1.default.sanitize(string, sanitizeOptions);\n}\nexports.sanitize = sanitize;\n/**\n * Fast cloneDeep for JSON objects only.\n */\nfunction fastCloneDeep(obj) {\n return obj ? JSON.parse(JSON.stringify(obj)) : obj;\n}\nexports.fastCloneDeep = fastCloneDeep;\nfunction isInputComponent(componentJson) {\n if (componentJson.input === false || componentJson.input === true) {\n return componentJson.input;\n }\n switch (componentJson.type) {\n case 'htmlelement':\n case 'content':\n case 'columns':\n case 'fieldset':\n case 'panel':\n case 'table':\n case 'tabs':\n case 'well':\n case 'button':\n return false;\n default:\n return true;\n }\n}\nexports.isInputComponent = isInputComponent;\nfunction getArrayFromComponentPath(pathStr) {\n if (!pathStr || !lodash_1.default.isString(pathStr)) {\n if (!lodash_1.default.isArray(pathStr)) {\n return [pathStr];\n }\n return pathStr;\n }\n return pathStr.replace(/[[\\]]/g, '.')\n .replace(/\\.\\./g, '.')\n .replace(/(^\\.)|(\\.$)/g, '')\n .split('.')\n .map(part => lodash_1.default.defaultTo(lodash_1.default.toNumber(part), part));\n}\nexports.getArrayFromComponentPath = getArrayFromComponentPath;\nfunction isChildOf(child, parent) {\n while (child && child.parent) {\n if (child.parent === parent) {\n return true;\n }\n child = child.parent;\n }\n return false;\n}\nexports.isChildOf = isChildOf;\nfunction getStringFromComponentPath(path) {\n if (!lodash_1.default.isArray(path)) {\n return path;\n }\n let strPath = '';\n path.forEach((part, i) => {\n if (lodash_1.default.isNumber(part)) {\n strPath += `[${part}]`;\n }\n else {\n strPath += i === 0 ? part : `.${part}`;\n }\n });\n return strPath;\n}\nexports.getStringFromComponentPath = getStringFromComponentPath;\nfunction round(number, precision) {\n if (lodash_1.default.isNumber(number)) {\n return number.toFixed(precision);\n }\n return number;\n}\nexports.round = round;\n/**\n * Check for Internet Explorer browser version\n *\n * @return {(number|null)}\n */\nfunction getIEBrowserVersion() {\n const { ie, version } = getBrowserInfo();\n return ie ? version : null;\n}\nexports.getIEBrowserVersion = getIEBrowserVersion;\n/**\n * Get browser name and version (modified from 'jquery-browser-plugin')\n *\n * @return {Object} -- {{browser name, version, isWebkit?}}\n * Possible browser names: chrome, safari, ie, edge, opera, mozilla, yabrowser\n */\nfunction getBrowserInfo() {\n const browser = {};\n if (typeof window === 'undefined') {\n return browser;\n }\n const ua = window.navigator.userAgent.toLowerCase();\n const match = /(edge|edg)\\/([\\w.]+)/.exec(ua) ||\n /(opr)[/]([\\w.]+)/.exec(ua) ||\n /(yabrowser)[ /]([\\w.]+)/.exec(ua) ||\n /(chrome)[ /]([\\w.]+)/.exec(ua) ||\n /(iemobile)[/]([\\w.]+)/.exec(ua) ||\n /(version)(applewebkit)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+).*(version)[ /]([\\w.]+).*(safari)[ /]([\\w.]+)/.exec(ua) ||\n /(webkit)[ /]([\\w.]+)/.exec(ua) ||\n /(opera)(?:.*version|)[ /]([\\w.]+)/.exec(ua) ||\n /(msie) ([\\w.]+)/.exec(ua) ||\n ua.indexOf('trident') >= 0 && /(rv)(?::| )([\\w.]+)/.exec(ua) ||\n ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\\w.]+)|)/.exec(ua) ||\n [];\n const matched = {\n browser: match[5] || match[3] || match[1] || '',\n version: match[4] || match[2] || '0'\n };\n if (matched.browser) {\n browser[matched.browser] = true;\n browser.version = parseInt(matched.version, 10);\n }\n // Chrome, Opera 15+, Safari and Yandex.Browser are webkit based browsers\n if (browser.chrome || browser.opr || browser.safari || browser.edg || browser.yabrowser) {\n browser.isWebkit = true;\n }\n // IE11 has a new token so we will assign it ie to avoid breaking changes\n if (browser.rv || browser.iemobile) {\n browser.ie = true;\n }\n // Edge has a new token since it became webkit based\n if (browser.edg) {\n browser.edge = true;\n }\n // Opera 15+ are identified as opr\n if (browser.opr) {\n browser.opera = true;\n }\n return browser;\n}\nexports.getBrowserInfo = getBrowserInfo;\nfunction getComponentPathWithoutIndicies(path = '') {\n return path.replace(/\\[\\d+\\]/, '');\n}\nexports.getComponentPathWithoutIndicies = getComponentPathWithoutIndicies;\n/**\n * Returns a path to the component which based on its schema\n * @param {*} component is a component's schema containing link to its parent's schema in the 'parent' property\n */\nfunction getComponentPath(component, path = '') {\n var _a;\n if (!component || !component.key || ((_a = component === null || component === void 0 ? void 0 : component._form) === null || _a === void 0 ? void 0 : _a.display) === 'wizard') { // unlike the Webform, the Wizard has the key and it is a duplicate of the panel key\n return path;\n }\n path = component.isInputComponent || component.input === true ? `${component.key}${path ? '.' : ''}${path}` : path;\n return getComponentPath(component.parent, path);\n}\nexports.getComponentPath = getComponentPath;\n/**\n * Returns a parent component of the passed component instance skipping all the Layout components\n * @param {*} componentInstance\n * @return {(Component|undefined)}\n */\nfunction getDataParentComponent(componentInstance) {\n if (!componentInstance) {\n return;\n }\n const { parent } = componentInstance;\n if (parent && (parent.isInputComponent || parent.input)) {\n return parent;\n }\n else {\n return getDataParentComponent(parent);\n }\n}\nexports.getDataParentComponent = getDataParentComponent;\n/**\n * Returns whether the value is a promise\n * @param value\n * @return {boolean}\n */\nfunction isPromise(value) {\n return value\n && value.then\n && typeof value.then === 'function'\n && Object.prototype.toString.call(value) === '[object Promise]';\n}\nexports.isPromise = isPromise;\n/**\n * Determines if the component has a scoping parent in tree (a component which scopes its children and manages its\n * changes by itself, e.g. EditGrid)\n * @param componentInstance\n * @param firstPass\n * @returns {boolean|boolean|*}\n */\nfunction isInsideScopingComponent(componentInstance, firstPass = true) {\n if (!firstPass && (componentInstance === null || componentInstance === void 0 ? void 0 : componentInstance.hasScopedChildren)) {\n return true;\n }\n const dataParent = getDataParentComponent(componentInstance);\n if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.hasScopedChildren) {\n return true;\n }\n else if (dataParent === null || dataParent === void 0 ? void 0 : dataParent.parent) {\n return isInsideScopingComponent(dataParent.parent, false);\n }\n return false;\n}\nexports.isInsideScopingComponent = isInsideScopingComponent;\nfunction getFocusableElements(element) {\n const focusableSelector = `button:not([disabled]), input:not([disabled]), select:not([disabled]),\n textarea:not([disabled]), button:not([disabled]), [href]`;\n return element.querySelectorAll(focusableSelector);\n}\nexports.getFocusableElements = getFocusableElements;\nexports.componentValueTypes = {\n number: 'number',\n string: 'string',\n boolean: 'boolean',\n array: 'array',\n object: 'object',\n date: 'date',\n any: 'any',\n};\nfunction getComponentSavedTypes(fullSchema) {\n const schema = fullSchema || {};\n if (schema.persistent !== true) {\n return [];\n }\n if (schema.multiple) {\n return [exports.componentValueTypes.array];\n }\n return null;\n}\nexports.getComponentSavedTypes = getComponentSavedTypes;\n/**\n * Interpolates @formio/core errors so that they are compatible with the renderer\n * @param {FieldError[]} errors\n * @param firstPass\n * @returns {[]}\n */\nconst interpolateErrors = (component, errors, interpolateFn) => {\n return errors.map((error) => {\n error.component = component;\n const { errorKeyOrMessage, context } = error;\n const toInterpolate = component.errors && component.errors[errorKeyOrMessage] ? component.errors[errorKeyOrMessage] : errorKeyOrMessage;\n return Object.assign(Object.assign({}, error), { message: unescapeHTML(interpolateFn(toInterpolate, context)), context: Object.assign({}, context) });\n });\n};\nexports.interpolateErrors = interpolateErrors;\nfunction getItemTemplateKeys(template) {\n const templateKeys = [];\n if (!template) {\n return templateKeys;\n }\n const keys = template.match(/({{\\s*(.*?)\\s*}})/g);\n if (keys) {\n keys.forEach((key) => {\n const propKey = key.match(/{{\\s*item\\.(.*?)\\s*}}/);\n if (propKey && propKey.length > 1) {\n templateKeys.push(propKey[1]);\n }\n });\n }\n return templateKeys;\n}\nexports.getItemTemplateKeys = getItemTemplateKeys;\nfunction isSelectResourceWithObjectValue(comp = {}) {\n const { reference, dataSrc, valueProperty } = comp;\n return reference || (dataSrc === 'resource' && (!valueProperty || valueProperty === 'data'));\n}\nexports.isSelectResourceWithObjectValue = isSelectResourceWithObjectValue;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/utils/utils.js?");
8329
8339
 
8330
8340
  /***/ }),
8331
8341
 
@@ -8336,7 +8346,7 @@ eval("\n/* global jQuery */\nvar __createBinding = (this && this.__createBinding
8336
8346
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
8337
8347
 
8338
8348
  "use strict";
8339
- eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Formio_1 = __webpack_require__(/*! ../Formio */ \"./lib/cjs/Formio.js\");\nconst InputWidget_1 = __importDefault(__webpack_require__(/*! ./InputWidget */ \"./lib/cjs/widgets/InputWidget.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a';\nconst ISO_8601_FORMAT = 'yyyy-MM-ddTHH:mm:ssZ';\nconst isIEBrowser = (0, utils_1.getBrowserInfo)().ie;\nclass CalendarWidget extends InputWidget_1.default {\n /* eslint-disable camelcase */\n static get defaultSettings() {\n return {\n type: 'calendar',\n altInput: true,\n allowInput: true,\n clickOpens: true,\n enableDate: true,\n enableTime: true,\n mode: 'single',\n noCalendar: false,\n format: DEFAULT_FORMAT,\n dateFormat: ISO_8601_FORMAT,\n useLocaleSettings: false,\n language: 'us-en',\n hourIncrement: 1,\n minuteIncrement: 5,\n time_24hr: false,\n saveAs: 'date',\n displayInTimezone: '',\n timezone: '',\n disable: [],\n minDate: '',\n maxDate: ''\n };\n }\n /* eslint-enable camelcase */\n constructor(settings, component, instance, index) {\n super(settings, component, instance, index);\n // Change the format to map to the settings.\n if (this.settings.noCalendar) {\n this.settings.format = this.settings.format.replace(/yyyy-MM-dd /g, '');\n }\n if (!this.settings.enableTime) {\n this.settings.format = this.settings.format.replace(/ hh:mm a$/g, '');\n }\n else if (this.settings.time_24hr) {\n this.settings.format = this.settings.format.replace(/hh:mm a$/g, 'HH:mm');\n }\n this.zoneLoading = false;\n this.timezonesUrl = `${Formio_1.Formio.cdn['moment-timezone']}/data/packed/latest.json`;\n }\n /**\n * Load the timezones.\n *\n * @return {boolean} TRUE if the zones are loading, FALSE otherwise.\n */\n loadZones() {\n const timezone = this.timezone;\n if (this.zoneLoading) {\n return true;\n }\n if (!(0, utils_1.zonesLoaded)() && (0, utils_1.shouldLoadZones)(timezone)) {\n this.zoneLoading = true;\n (0, utils_1.loadZones)(this.timezonesUrl, timezone).then(() => {\n this.zoneLoading = false;\n this.emit('redraw');\n });\n // Return zones are loading.\n return true;\n }\n // Zones are already loaded.\n return false;\n }\n attach(input) {\n var _a;\n const superAttach = super.attach(input);\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.settings.language);\n this.defaultFormat = {\n date: dateFormatInfo.dayFirst ? 'd/m/Y ' : 'm/d/Y ',\n time: 'G:i K'\n };\n this.closedOn = 0;\n this.valueFormat = (this.settings.saveAs === 'date') ? ISO_8601_FORMAT : this.settings.dateFormat || ISO_8601_FORMAT;\n this.valueMomentFormat = (0, utils_1.convertFormatToMoment)(this.valueFormat);\n const isReadOnly = this.settings.readOnly;\n this.settings.minDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.minDate);\n this.settings.maxDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.maxDate);\n this.settings.disable = this.disabledDates;\n this.settings.disableWeekends ? this.settings.disable.push(this.disableWeekends) : '';\n this.settings.disableWeekdays ? this.settings.disable.push(this.disableWeekdays) : '';\n this.settings.disableFunction ? this.settings.disable.push(this.disableFunction) : '';\n this.settings.wasDefaultValueChanged = false;\n this.settings.defaultValue = '';\n this.settings.manualInputValue = '';\n this.settings.isManuallyOverriddenValue = false;\n this.settings.currentValue = '';\n this.settings.altFormat = (0, utils_1.convertFormatToFlatpickr)(this.settings.format);\n this.settings.dateFormat = (0, utils_1.convertFormatToFlatpickr)(this.settings.dateFormat);\n this.settings.position = 'auto center';\n this.settings.onChange = () => {\n if (this.settings.allowInput) {\n if (this.settings.isManuallyOverriddenValue && this.settings.enableTime) {\n this.calendar._input.value = this.settings.manualInputValue;\n }\n else {\n this.settings.manualInputValue = '';\n }\n this.settings.isManuallyOverriddenValue = false;\n }\n this.emit('update');\n };\n this.settings.onOpen = () => this.hook('onCalendarOpen');\n this.settings.onClose = () => {\n this.hook('onCalendarClose');\n this.closedOn = Date.now();\n if (this.settings.allowInput && this.settings.enableTime) {\n this.calendar._input.value = this.settings.manualInputValue || this.calendar._input.value;\n this.settings.isManuallyOverriddenValue = false;\n this.emit('update');\n }\n if (this.settings.wasDefaultValueChanged) {\n this.calendar._input.value = this.settings.defaultValue;\n this.settings.wasDefaultValueChanged = false;\n }\n if (this.calendar) {\n this.emit('blur');\n }\n };\n Formio_1.Formio.requireLibrary('flatpickr-css', 'flatpickr', [\n { type: 'styles', src: `${Formio_1.Formio.cdn['flatpickr-formio']}/flatpickr.min.css` }\n ], true);\n if (this.component.shortcutButtons) {\n this.component.shortcutButtons = this.component.shortcutButtons.filter((btn) => btn.label && btn.onClick);\n }\n if ((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) {\n Formio_1.Formio.requireLibrary('shortcut-buttons-flatpickr-css', 'ShortcutButtonsPlugin', [\n { type: 'styles', src: `${Formio_1.Formio.cdn['shortcut-buttons-flatpickr']}/themes/light.min.css` }\n ], true);\n }\n return superAttach\n .then(() => {\n var _a;\n if ((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) {\n return Formio_1.Formio.requireLibrary('shortcut-buttons-flatpickr', 'ShortcutButtonsPlugin', `${Formio_1.Formio.cdn['shortcut-buttons-flatpickr']}/shortcut-buttons-flatpickr.min.js`, true);\n }\n })\n .then((ShortcutButtonsPlugin) => {\n return Formio_1.Formio.requireLibrary('flatpickr', 'flatpickr', `${Formio_1.Formio.cdn['flatpickr-formio']}/flatpickr.min.js`, true)\n .then((Flatpickr) => {\n var _a;\n if (((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) && ShortcutButtonsPlugin) {\n this.initShortcutButtonsPlugin(ShortcutButtonsPlugin);\n }\n this.settings.formatDate = this.getFlatpickrFormatDate(Flatpickr);\n if (this._input) {\n const { locale } = this.settings;\n if (locale && locale.length >= 2 && locale !== 'en') {\n return Formio_1.Formio.requireLibrary(`flatpickr-${locale}`, `flatpickr-${locale}`, `${Formio_1.Formio.cdn['flatpickr-formio']}/l10n/flatpickr-${locale}.js`, true).then(() => this.initFlatpickr(Flatpickr));\n }\n else {\n this.initFlatpickr(Flatpickr);\n }\n }\n });\n })\n .catch((err) => {\n console.warn(err);\n });\n }\n get disableWeekends() {\n return function (date) {\n return (date.getDay() === 0 || date.getDay() === 6);\n };\n }\n get disableWeekdays() {\n return (date) => !this.disableWeekends(date);\n }\n get disableFunction() {\n return (date) => this.evaluate(`return ${this.settings.disableFunction}`, {\n date\n });\n }\n get timezone() {\n return this.componentInstance.getTimezone(this.settings);\n }\n get defaultSettings() {\n return CalendarWidget.defaultSettings;\n }\n addSuffix(suffix) {\n this.addEventListener(suffix, 'click', () => {\n setTimeout(() => {\n if (this.calendar) {\n if (!this.calendar.isOpen && ((Date.now() - this.closedOn) > 200)) {\n this.calendar.open();\n }\n else if (this.calendar.isOpen) {\n this.calendar.close();\n }\n }\n }, 0);\n });\n return suffix;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (this.calendar) {\n if (disabled) {\n this.calendar._input.setAttribute('disabled', 'disabled');\n }\n else {\n this.calendar._input.removeAttribute('disabled');\n }\n this.calendar.close();\n this.calendar.redraw();\n }\n }\n get input() {\n return this.calendar ? this.calendar.altInput : null;\n }\n get disabledDates() {\n if (this.settings.disabledDates) {\n const disabledDates = this.settings.disabledDates.split(',');\n return disabledDates.map((item) => {\n const dateMask = /\\d{4}-\\d{2}-\\d{2}/g;\n const dates = item.match(dateMask);\n if (dates && dates.length) {\n return dates.length === 1 ? item.match(dateMask)[0] : {\n from: item.match(dateMask)[0],\n to: item.match(dateMask)[1],\n };\n }\n });\n }\n return [];\n }\n get localeFormat() {\n let format = '';\n if (this.settings.enableDate) {\n format += this.defaultFormat.date;\n }\n if (this.settings.enableTime) {\n format += this.defaultFormat.time;\n }\n return format;\n }\n get dateTimeFormat() {\n return this.settings.useLocaleSettings ? this.localeFormat : (0, utils_1.convertFormatToFlatpickr)(this.dateFormat);\n }\n get dateFormat() {\n return lodash_1.default.get(this.settings, 'format', DEFAULT_FORMAT);\n }\n /**\n * Return the date value.\n *\n * @param date\n * @param format\n * @return {string}\n */\n getDateValue(date, format, useTimezone) {\n if (useTimezone) {\n return (0, utils_1.momentDate)(date, this.valueFormat, this.timezone).format((0, utils_1.convertFormatToMoment)(format));\n }\n return (0, moment_1.default)(date).format((0, utils_1.convertFormatToMoment)(format));\n }\n /**\n * Return the value of the selected date.\n *\n * @return {*}\n */\n getValue() {\n // Standard output format.\n if (!this.calendar) {\n return super.getValue();\n }\n // Get the selected dates from the calendar widget.\n const dates = this.calendar.selectedDates;\n if (!dates || !dates.length) {\n return super.getValue();\n }\n if (!(dates[0] instanceof Date)) {\n return 'Invalid Date';\n }\n return this.getDateValue(dates[0], this.valueFormat, (this.settings.saveAs === 'date'));\n }\n isValueISO8601(value) {\n return value && (typeof value === 'string') && value.match(/-[0-9]{2}T[0-9]{2}:/);\n }\n /**\n * Set the selected date value.\n *\n * @param value\n */\n setValue(value) {\n const saveAsText = (this.settings.saveAs === 'text');\n if (!this.calendar) {\n value = value ? (0, utils_1.formatDate)(this.timezonesUrl, value, (0, utils_1.convertFormatToMoment)(this.settings.format), this.timezone, (0, utils_1.convertFormatToMoment)(this.valueMomentFormat)) : value;\n return super.setValue(value);\n }\n const zonesLoading = this.loadZones();\n if (value) {\n if (!saveAsText && this.settings.readOnly && !zonesLoading) {\n this.calendar.setDate((0, utils_1.momentDate)(value, this.valueFormat, this.timezone).format(), false);\n }\n else if (this.isValueISO8601(value)) {\n this.calendar.setDate(value, false);\n }\n else {\n this.calendar.setDate((0, moment_1.default)(value, this.valueMomentFormat).toDate(), false);\n }\n }\n else {\n this.calendar.clear(false);\n }\n }\n getValueAsString(value, format) {\n const inputFormat = format || this.dateFormat;\n const valueFormat = this.calendar ? this.valueFormat : this.settings.dateFormat;\n if (this.settings.saveAs === 'text' && this.componentInstance.parent && !this.settings.readOnly) {\n return (0, moment_1.default)(value, (0, utils_1.convertFormatToMoment)(valueFormat)).format((0, utils_1.convertFormatToMoment)(valueFormat));\n }\n return (0, utils_1.formatDate)(this.timezonesUrl, value, inputFormat, this.timezone, (0, utils_1.convertFormatToMoment)(valueFormat));\n }\n setErrorClasses(hasErrors) {\n if (!this.input) {\n return;\n }\n if (hasErrors) {\n this.addClass(this.input, 'is-invalid');\n this.input.setAttribute('aria-invalid', 'true');\n }\n else {\n this.removeClass(this.input, 'is-invalid');\n this.input.setAttribute('aria-invalid', 'false');\n }\n }\n get validationValue() {\n const value = this.dataValue;\n if (typeof value === 'string') {\n return new Date(value);\n }\n return value.map(val => new Date(val));\n }\n isCalendarElement(element) {\n var _a, _b, _c, _d, _e;\n if (!element) {\n return true;\n }\n if ((_c = (_b = (_a = this.calendar) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.appendTo) === null || _c === void 0 ? void 0 : _c.contains(element)) {\n return true;\n }\n return (_e = (_d = this.calendar) === null || _d === void 0 ? void 0 : _d.calendarContainer) === null || _e === void 0 ? void 0 : _e.contains(element);\n }\n initFlatpickr(Flatpickr) {\n // Create a new flatpickr.\n this.calendar = new Flatpickr(this._input, Object.assign(Object.assign({}, this.settings), { disableMobile: true }));\n this.addEventListener(this.calendar.altInput, 'input', (event) => {\n if (this.settings.allowInput && this.settings.currentValue !== event.target.value) {\n this.settings.manualInputValue = event.target.value;\n this.settings.isManuallyOverriddenValue = true;\n this.settings.currentValue = event.target.value;\n }\n if (event.target.value === '' && this.calendar.selectedDates.length > 0) {\n this.settings.wasDefaultValueChanged = true;\n this.settings.defaultValue = event.target.value;\n this.calendar.clear();\n }\n else {\n this.settings.wasDefaultValueChanged = false;\n }\n });\n const excludedFromMaskFormats = ['MMMM'];\n if (!this.settings.readOnly && !lodash_1.default.some(excludedFromMaskFormats, format => lodash_1.default.includes(this.settings.format, format))) {\n // Enforce the input mask of the format.\n this.setInputMask(this.calendar._input, (0, utils_1.convertFormatToMask)(this.settings.format));\n }\n // Fixes an issue with IE11 where value is set only after the second click\n // TODO: Remove when the issue is solved in the flatpickr library\n if (isIEBrowser) {\n // Remove the original blur listener, because value will be set to empty since relatedTarget is null in IE11\n const originalBlurListener = this.calendar._handlers.find(({ event, element }) => event === 'blur' && element === this.calendar._input);\n this.calendar._input.removeEventListener('blur', originalBlurListener.handler);\n // Add the same event listener as in the original library, but with workaround for IE11 issue\n this.addEventListener(this.calendar._input, 'blur', (event) => {\n const activeElement = this.settings.shadowRoot ? this.settings.shadowRoot.activeElement : document.activeElement;\n const relatedTarget = event.relatedTarget ? event.relatedTarget : activeElement;\n const isInput = event.target === this.calendar._input;\n if (isInput && !this.isCalendarElement(relatedTarget)) {\n this.calendar.setDate(this.calendar._input.value, true, event.target === this.calendar.altInput\n ? this.calendar.config.altFormat\n : this.calendar.config.dateFormat);\n }\n });\n }\n // Make sure we commit the value after a blur event occurs.\n this.addEventListener(this.calendar._input, 'blur', (event) => {\n var _a, _b, _c, _d;\n const activeElement = this.settings.shadowRoot ? this.settings.shadowRoot.activeElement : document.activeElement;\n const relatedTarget = event.relatedTarget ? event.relatedTarget : activeElement;\n if (!(isIEBrowser && !relatedTarget) && !this.isCalendarElement(relatedTarget)) {\n const inputValue = this.calendar.input.value;\n const dateValue = inputValue ? (0, moment_1.default)(this.calendar.input.value, (0, utils_1.convertFormatToMoment)(this.valueFormat)).toDate() : inputValue;\n this.calendar.setDate(dateValue, true, this.settings.altFormat);\n }\n else if (!this.calendar.input.value && this.calendar.config.noCalendar) {\n const value = (0, moment_1.default)({ hour: (_b = (_a = this.calendar) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.defaultHour, minute: (_d = (_c = this.calendar) === null || _c === void 0 ? void 0 : _c.config) === null || _d === void 0 ? void 0 : _d.defaultMinute }).toDate();\n this.calendar.setDate(value, true, this.settings.format);\n }\n });\n // FJS-1103: When hit the enter button, the field not saving the year correctly\n this.addEventListener(this.calendar.altInput, 'keydown', (event) => {\n if (event.keyCode === 13) {\n if (this.calendar.isOpen) {\n this.calendar.close();\n event.stopPropagation();\n }\n }\n });\n // If other fields are used to calculate disabled dates, we need to redraw calendar to refresh disabled dates\n if (this.settings.disableFunction && this.componentInstance && this.componentInstance.root) {\n this.componentInstance.root.on('change', (e) => {\n if (e.changed && this.calendar) {\n this.calendar.redraw();\n }\n });\n }\n // Restore the calendar value from the component value.\n this.setValue(this.componentValue);\n }\n initShortcutButtonsPlugin(ShortcutButtonsPlugin) {\n this.settings.plugins = [\n // eslint-disable-next-line new-cap\n ShortcutButtonsPlugin({\n button: this.component.shortcutButtons.map((btn) => ({ label: btn.label, attributes: btn.attribute })),\n onClick: (index) => {\n const getValue = this.component.shortcutButtons[index].onClick;\n const date = this.evaluate(getValue, { date: new Date() }, 'date');\n this.calendar.setDate(date, true);\n }\n })\n ];\n }\n get componentValue() {\n let compValue = this.componentInstance.dataValue;\n if (Array.isArray(compValue)) {\n compValue = compValue[this.valueIndex];\n }\n return compValue;\n }\n getFlatpickrFormatDate(Flatpickr) {\n return (date, format) => {\n // Only format this if this is the altFormat and the form is readOnly.\n if (this.settings.readOnly && (format === this.settings.altFormat)) {\n if (!this.settings.enableTime || this.loadZones()) {\n return Flatpickr.formatDate(date, format);\n }\n const currentValue = new Date(this.getValue());\n if (currentValue.toString() === date.toString()) {\n return (0, utils_1.formatOffset)(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), new Date(this.componentValue), format, this.timezone);\n }\n return (0, utils_1.formatOffset)(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), date, format, this.timezone);\n }\n return Flatpickr.formatDate(date, format);\n };\n }\n destroy() {\n super.destroy();\n if (this.calendar) {\n this.calendar.destroy();\n }\n }\n}\nexports[\"default\"] = CalendarWidget;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/widgets/CalendarWidget.js?");
8349
+ eval("\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nconst Formio_1 = __webpack_require__(/*! ../Formio */ \"./lib/cjs/Formio.js\");\nconst InputWidget_1 = __importDefault(__webpack_require__(/*! ./InputWidget */ \"./lib/cjs/widgets/InputWidget.js\"));\nconst utils_1 = __webpack_require__(/*! ../utils/utils */ \"./lib/cjs/utils/utils.js\");\nconst moment_1 = __importDefault(__webpack_require__(/*! moment */ \"./node_modules/moment/moment.js\"));\nconst lodash_1 = __importDefault(__webpack_require__(/*! lodash */ \"./node_modules/lodash/lodash.js\"));\nconst DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a';\nconst ISO_8601_FORMAT = 'yyyy-MM-ddTHH:mm:ssZ';\nconst isIEBrowser = (0, utils_1.getBrowserInfo)().ie;\nclass CalendarWidget extends InputWidget_1.default {\n /* eslint-disable camelcase */\n static get defaultSettings() {\n return {\n type: 'calendar',\n altInput: true,\n allowInput: true,\n clickOpens: true,\n enableDate: true,\n enableTime: true,\n mode: 'single',\n noCalendar: false,\n format: DEFAULT_FORMAT,\n dateFormat: ISO_8601_FORMAT,\n useLocaleSettings: false,\n language: 'us-en',\n hourIncrement: 1,\n minuteIncrement: 5,\n time_24hr: false,\n saveAs: 'date',\n displayInTimezone: '',\n timezone: '',\n disable: [],\n minDate: '',\n maxDate: ''\n };\n }\n /* eslint-enable camelcase */\n constructor(settings, component, instance, index) {\n super(settings, component, instance, index);\n // Change the format to map to the settings.\n if (this.settings.noCalendar) {\n this.settings.format = this.settings.format.replace(/yyyy-MM-dd /g, '');\n }\n if (!this.settings.enableTime) {\n this.settings.format = this.settings.format.replace(/ hh:mm a$/g, '');\n }\n else if (this.settings.time_24hr) {\n this.settings.format = this.settings.format.replace(/hh:mm a$/g, 'HH:mm');\n }\n this.zoneLoading = false;\n this.timezonesUrl = `${Formio_1.Formio.cdn['moment-timezone']}/data/packed/latest.json`;\n }\n /**\n * Load the timezones.\n *\n * @return {boolean} TRUE if the zones are loading, FALSE otherwise.\n */\n loadZones() {\n const timezone = this.timezone;\n if (this.zoneLoading) {\n return true;\n }\n if (!(0, utils_1.zonesLoaded)() && (0, utils_1.shouldLoadZones)(timezone)) {\n this.zoneLoading = true;\n (0, utils_1.loadZones)(this.timezonesUrl, timezone).then(() => {\n this.zoneLoading = false;\n this.emit('redraw');\n });\n // Return zones are loading.\n return true;\n }\n // Zones are already loaded.\n return false;\n }\n attach(input) {\n var _a;\n const superAttach = super.attach(input);\n const dateFormatInfo = (0, utils_1.getLocaleDateFormatInfo)(this.settings.language);\n this.defaultFormat = {\n date: dateFormatInfo.dayFirst ? 'd/m/Y ' : 'm/d/Y ',\n time: 'G:i K'\n };\n this.closedOn = 0;\n this.valueFormat = (this.settings.saveAs === 'date') ? ISO_8601_FORMAT : this.settings.dateFormat || ISO_8601_FORMAT;\n this.valueMomentFormat = (0, utils_1.convertFormatToMoment)(this.valueFormat);\n const isReadOnly = this.settings.readOnly;\n this.settings.minDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.minDate);\n this.settings.maxDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.maxDate);\n this.settings.disable = this.disabledDates;\n this.settings.disableWeekends ? this.settings.disable.push(this.disableWeekends) : '';\n this.settings.disableWeekdays ? this.settings.disable.push(this.disableWeekdays) : '';\n this.settings.disableFunction ? this.settings.disable.push(this.disableFunction) : '';\n this.settings.wasDefaultValueChanged = false;\n this.settings.defaultValue = '';\n this.settings.manualInputValue = '';\n this.settings.isManuallyOverriddenValue = false;\n this.settings.currentValue = '';\n this.settings.altFormat = (0, utils_1.convertFormatToFlatpickr)(this.settings.format);\n this.settings.dateFormat = (0, utils_1.convertFormatToFlatpickr)(this.settings.dateFormat);\n this.settings.position = 'auto center';\n this.settings.onChange = () => {\n if (this.settings.allowInput) {\n if (this.settings.isManuallyOverriddenValue && this.settings.enableTime) {\n this.calendar._input.value = this.settings.manualInputValue;\n }\n else {\n this.settings.manualInputValue = '';\n }\n this.settings.isManuallyOverriddenValue = false;\n }\n this.emit('update');\n };\n this.settings.onOpen = () => this.hook('onCalendarOpen');\n this.settings.onClose = () => {\n this.hook('onCalendarClose');\n this.closedOn = Date.now();\n if (this.settings.allowInput && this.settings.enableTime) {\n this.calendar._input.value = this.settings.manualInputValue || this.calendar._input.value;\n this.settings.isManuallyOverriddenValue = false;\n this.emit('update');\n }\n if (this.settings.wasDefaultValueChanged) {\n this.calendar._input.value = this.settings.defaultValue;\n this.settings.wasDefaultValueChanged = false;\n }\n if (this.calendar) {\n this.emit('blur');\n }\n };\n Formio_1.Formio.requireLibrary('flatpickr-css', 'flatpickr', [\n { type: 'styles', src: `${Formio_1.Formio.cdn['flatpickr-formio']}/flatpickr.min.css` }\n ], true);\n if (this.component.shortcutButtons) {\n this.component.shortcutButtons = this.component.shortcutButtons.filter((btn) => btn.label && btn.onClick);\n }\n if ((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) {\n Formio_1.Formio.requireLibrary('shortcut-buttons-flatpickr-css', 'ShortcutButtonsPlugin', [\n { type: 'styles', src: `${Formio_1.Formio.cdn['shortcut-buttons-flatpickr']}/themes/light.min.css` }\n ], true);\n }\n return superAttach\n .then(() => {\n var _a;\n if ((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) {\n return Formio_1.Formio.requireLibrary('shortcut-buttons-flatpickr', 'ShortcutButtonsPlugin', `${Formio_1.Formio.cdn['shortcut-buttons-flatpickr']}/shortcut-buttons-flatpickr.min.js`, true);\n }\n })\n .then((ShortcutButtonsPlugin) => {\n return Formio_1.Formio.requireLibrary('flatpickr', 'flatpickr', `${Formio_1.Formio.cdn['flatpickr-formio']}/flatpickr.min.js`, true)\n .then((Flatpickr) => {\n var _a;\n if (((_a = this.component.shortcutButtons) === null || _a === void 0 ? void 0 : _a.length) && ShortcutButtonsPlugin) {\n this.initShortcutButtonsPlugin(ShortcutButtonsPlugin);\n }\n this.settings.formatDate = this.getFlatpickrFormatDate(Flatpickr);\n if (this._input) {\n const { locale } = this.settings;\n if (locale && locale.length >= 2 && locale !== 'en') {\n return Formio_1.Formio.requireLibrary(`flatpickr-${locale}`, `flatpickr-${locale}`, `${Formio_1.Formio.cdn['flatpickr-formio']}/l10n/flatpickr-${locale}.js`, true).then(() => this.initFlatpickr(Flatpickr));\n }\n else {\n this.initFlatpickr(Flatpickr);\n }\n }\n });\n })\n .catch((err) => {\n console.warn(err);\n });\n }\n get disableWeekends() {\n return function (date) {\n return (date.getDay() === 0 || date.getDay() === 6);\n };\n }\n get disableWeekdays() {\n return (date) => !this.disableWeekends(date);\n }\n get disableFunction() {\n return (date) => this.evaluate(`return ${this.settings.disableFunction}`, {\n date\n });\n }\n get timezone() {\n return this.componentInstance.getTimezone(this.settings);\n }\n get defaultSettings() {\n return CalendarWidget.defaultSettings;\n }\n addSuffix(suffix) {\n this.addEventListener(suffix, 'click', () => {\n setTimeout(() => {\n if (this.calendar) {\n if (!this.calendar.isOpen && ((Date.now() - this.closedOn) > 200)) {\n this.calendar.open();\n }\n else if (this.calendar.isOpen) {\n this.calendar.close();\n }\n }\n }, 0);\n });\n return suffix;\n }\n set disabled(disabled) {\n super.disabled = disabled;\n if (this.calendar) {\n if (disabled) {\n this.calendar._input.setAttribute('disabled', 'disabled');\n }\n else {\n this.calendar._input.removeAttribute('disabled');\n }\n this.calendar.close();\n this.calendar.redraw();\n }\n }\n get input() {\n return this.calendar ? this.calendar.altInput : null;\n }\n get disabledDates() {\n if (this.settings.disabledDates) {\n const disabledDates = this.settings.disabledDates.split(',');\n return disabledDates.map((item) => {\n const dateMask = /\\d{4}-\\d{2}-\\d{2}/g;\n const dates = item.match(dateMask);\n if (dates && dates.length) {\n return dates.length === 1 ? item.match(dateMask)[0] : {\n from: item.match(dateMask)[0],\n to: item.match(dateMask)[1],\n };\n }\n });\n }\n return [];\n }\n get localeFormat() {\n let format = '';\n if (this.settings.enableDate) {\n format += this.defaultFormat.date;\n }\n if (this.settings.enableTime) {\n format += this.defaultFormat.time;\n }\n return format;\n }\n get dateTimeFormat() {\n return this.settings.useLocaleSettings ? this.localeFormat : (0, utils_1.convertFormatToFlatpickr)(this.dateFormat);\n }\n get dateFormat() {\n return lodash_1.default.get(this.settings, 'format', DEFAULT_FORMAT);\n }\n /**\n * Return the date value.\n *\n * @param date\n * @param format\n * @return {string}\n */\n getDateValue(date, format, useTimezone) {\n if (useTimezone) {\n return (0, utils_1.momentDate)(date, this.valueFormat, this.timezone).format((0, utils_1.convertFormatToMoment)(format));\n }\n return (0, moment_1.default)(date).format((0, utils_1.convertFormatToMoment)(format));\n }\n /**\n * Return the value of the selected date.\n *\n * @return {*}\n */\n getValue() {\n // Standard output format.\n if (!this.calendar) {\n return super.getValue();\n }\n // Get the selected dates from the calendar widget.\n const dates = this.calendar.selectedDates;\n if (!dates || !dates.length) {\n return super.getValue();\n }\n if (!(dates[0] instanceof Date)) {\n return 'Invalid Date';\n }\n return this.getDateValue(dates[0], this.valueFormat, (this.settings.saveAs === 'date'));\n }\n isValueISO8601(value) {\n return value && (typeof value === 'string') && value.match(/-[0-9]{2}T[0-9]{2}:/);\n }\n /**\n * Set the selected date value.\n *\n * @param value\n */\n setValue(value) {\n const saveAsText = (this.settings.saveAs === 'text');\n if (!this.calendar) {\n value = value ? (0, utils_1.formatDate)(this.timezonesUrl, value, (0, utils_1.convertFormatToMoment)(this.settings.format), this.timezone, (0, utils_1.convertFormatToMoment)(this.valueMomentFormat)) : value;\n return super.setValue(value);\n }\n const zonesLoading = this.loadZones();\n if (value) {\n if (!saveAsText && this.settings.readOnly && !zonesLoading) {\n this.calendar.setDate((0, utils_1.momentDate)(value, this.valueFormat, this.timezone).format(), false);\n }\n else if (this.isValueISO8601(value)) {\n this.calendar.setDate(value, false);\n }\n else {\n this.calendar.setDate((0, moment_1.default)(value, this.valueMomentFormat).toDate(), false);\n }\n }\n else {\n this.calendar.clear(false);\n }\n }\n getValueAsString(value, format) {\n const inputFormat = format || this.dateFormat;\n const valueFormat = this.calendar ? this.valueFormat : this.settings.dateFormat;\n if (this.settings.saveAs === 'text' && this.componentInstance.parent && !this.settings.readOnly) {\n return (0, moment_1.default)(value, (0, utils_1.convertFormatToMoment)(valueFormat)).format((0, utils_1.convertFormatToMoment)(valueFormat));\n }\n return (0, utils_1.formatDate)(this.timezonesUrl, value, inputFormat, this.timezone, (0, utils_1.convertFormatToMoment)(valueFormat));\n }\n setErrorClasses(hasErrors) {\n if (!this.input) {\n return;\n }\n if (hasErrors) {\n this.addClass(this.input, 'is-invalid');\n this.input.setAttribute('aria-invalid', 'true');\n }\n else {\n this.removeClass(this.input, 'is-invalid');\n this.input.setAttribute('aria-invalid', 'false');\n }\n }\n get validationValue() {\n const value = this.dataValue;\n if (typeof value === 'string') {\n return new Date(value);\n }\n return value.map(val => new Date(val));\n }\n isCalendarElement(element) {\n var _a, _b, _c, _d, _e;\n if (!element) {\n return true;\n }\n if ((_c = (_b = (_a = this.calendar) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.appendTo) === null || _c === void 0 ? void 0 : _c.contains(element)) {\n return true;\n }\n return (_e = (_d = this.calendar) === null || _d === void 0 ? void 0 : _d.calendarContainer) === null || _e === void 0 ? void 0 : _e.contains(element);\n }\n initFlatpickr(Flatpickr) {\n // Create a new flatpickr.\n this.calendar = new Flatpickr(this._input, Object.assign(Object.assign({}, this.settings), { disableMobile: true }));\n this.addEventListener(this.calendar.altInput, 'input', (event) => {\n if (this.settings.allowInput && this.settings.currentValue !== event.target.value) {\n this.settings.manualInputValue = event.target.value;\n this.settings.isManuallyOverriddenValue = true;\n this.settings.currentValue = event.target.value;\n }\n if (event.target.value === '' && this.calendar.selectedDates.length > 0) {\n this.settings.wasDefaultValueChanged = true;\n this.settings.defaultValue = event.target.value;\n this.calendar.clear();\n }\n else {\n this.settings.wasDefaultValueChanged = false;\n }\n });\n const excludedFromMaskFormats = ['MMMM'];\n if (!this.settings.readOnly && !lodash_1.default.some(excludedFromMaskFormats, format => lodash_1.default.includes(this.settings.format, format))) {\n // Enforce the input mask of the format.\n this.setInputMask(this.calendar._input, (0, utils_1.convertFormatToMask)(this.settings.format));\n }\n // Fixes an issue with IE11 where value is set only after the second click\n // TODO: Remove when the issue is solved in the flatpickr library\n if (isIEBrowser) {\n // Remove the original blur listener, because value will be set to empty since relatedTarget is null in IE11\n const originalBlurListener = this.calendar._handlers.find(({ event, element }) => event === 'blur' && element === this.calendar._input);\n this.calendar._input.removeEventListener('blur', originalBlurListener.handler);\n // Add the same event listener as in the original library, but with workaround for IE11 issue\n this.addEventListener(this.calendar._input, 'blur', (event) => {\n const activeElement = this.settings.shadowRoot ? this.settings.shadowRoot.activeElement : document.activeElement;\n const relatedTarget = event.relatedTarget ? event.relatedTarget : activeElement;\n const isInput = event.target === this.calendar._input;\n if (isInput && !this.isCalendarElement(relatedTarget)) {\n this.calendar.setDate(this.calendar._input.value, true, event.target === this.calendar.altInput\n ? this.calendar.config.altFormat\n : this.calendar.config.dateFormat);\n }\n });\n }\n // Make sure we commit the value after a blur event occurs.\n this.addEventListener(this.calendar._input, 'blur', (event) => {\n var _a, _b, _c, _d;\n const activeElement = this.settings.shadowRoot ? this.settings.shadowRoot.activeElement : document.activeElement;\n const relatedTarget = event.relatedTarget ? event.relatedTarget : activeElement;\n if (!(isIEBrowser && !relatedTarget) && !this.isCalendarElement(relatedTarget)) {\n const inputValue = this.calendar.input.value;\n const dateValue = inputValue ? (0, moment_1.default)(this.calendar.input.value, (0, utils_1.convertFormatToMoment)(this.valueFormat)).toDate() : inputValue;\n this.calendar.setDate(dateValue, true, this.settings.altFormat);\n }\n else if (!this.calendar.input.value && this.calendar.config.noCalendar) {\n const value = (0, moment_1.default)({ hour: (_b = (_a = this.calendar) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.defaultHour, minute: (_d = (_c = this.calendar) === null || _c === void 0 ? void 0 : _c.config) === null || _d === void 0 ? void 0 : _d.defaultMinute }).toDate();\n this.calendar.setDate(value, true, this.settings.format);\n }\n });\n // FJS-1103: When hit the enter button, the field not saving the year correctly\n this.addEventListener(this.calendar.altInput, 'keydown', (event) => {\n if (event.keyCode === 13) {\n if (this.calendar.isOpen) {\n this.calendar.close();\n event.stopPropagation();\n }\n }\n });\n // If other fields are used to calculate disabled dates, we need to redraw calendar to refresh disabled dates\n if (this.settings.disableFunction && this.componentInstance && this.componentInstance.root) {\n this.componentInstance.root.on('change', (e) => {\n if (e.changed && this.calendar) {\n this.calendar.redraw();\n }\n });\n }\n // Restore the calendar value from the component value.\n this.setValue(this.componentValue);\n }\n initShortcutButtonsPlugin(ShortcutButtonsPlugin) {\n this.settings.plugins = [\n // eslint-disable-next-line new-cap\n ShortcutButtonsPlugin({\n button: this.component.shortcutButtons.map((btn) => ({ label: btn.label, attributes: btn.attribute })),\n onClick: (index) => {\n const getValue = this.component.shortcutButtons[index].onClick;\n const date = this.evaluate(getValue, { date: new Date() }, 'date');\n this.calendar.setDate(date, true);\n }\n })\n ];\n }\n get componentValue() {\n let compValue = this.componentInstance.dataValue;\n if (Array.isArray(compValue)) {\n compValue = compValue[this.valueIndex];\n }\n return compValue;\n }\n getFlatpickrFormatDate(Flatpickr) {\n return (date, format) => {\n // Only format this if this is the altFormat and the form is readOnly.\n if (this.settings.readOnly && (format === this.settings.altFormat)) {\n if (!this.settings.enableTime || this.loadZones()) {\n return Flatpickr.formatDate(date, format);\n }\n const currentValue = new Date(this.getValue());\n if (currentValue.toString() === date.toString()) {\n return (0, utils_1.formatOffset)(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), new Date(this.componentValue), format, this.timezone);\n }\n return (0, utils_1.formatOffset)(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), date, format, this.timezone);\n }\n return Flatpickr.formatDate(date, format);\n };\n }\n destroy(all = false) {\n if (this.calendar) {\n this.calendar.destroy();\n }\n super.destroy(all);\n }\n}\nexports[\"default\"] = CalendarWidget;\n\n\n//# sourceURL=webpack://Formio/./lib/cjs/widgets/CalendarWidget.js?");
8340
8350
 
8341
8351
  /***/ }),
8342
8352