/*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./WOP/design/index.scss":
/*!*******************************!*\
  !*** ./WOP/design/index.scss ***!
  \*******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./WOP/design/index.scss?");

/***/ }),

/***/ "./node_modules/dompurify/dist/purify.es.mjs":
/*!***************************************************!*\
  !*** ./node_modules/dompurify/dist/purify.es.mjs ***!
  \***************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (/* binding */ purify)\n/* harmony export */ });\n/*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */\n\nconst {\n  entries,\n  setPrototypeOf,\n  isFrozen,\n  getPrototypeOf,\n  getOwnPropertyDescriptor\n} = Object;\nlet {\n  freeze,\n  seal,\n  create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n  apply,\n  construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n  freeze = function freeze(x) {\n    return x;\n  };\n}\nif (!seal) {\n  seal = function seal(x) {\n    return x;\n  };\n}\nif (!apply) {\n  apply = function apply(fun, thisValue, args) {\n    return fun.apply(thisValue, args);\n  };\n}\nif (!construct) {\n  construct = function construct(Func, args) {\n    return new Func(...args);\n  };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n  return function (thisArg) {\n    if (thisArg instanceof RegExp) {\n      thisArg.lastIndex = 0;\n    }\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 * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction 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 * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction 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 * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction 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 * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction 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 * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction 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\nconst 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']);\nconst 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']);\nconst 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// 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.\nconst 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']);\nconst 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// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst 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']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', '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', 'exponent', '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', 'intercept', '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', 'slope', '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', 'tablevalues', '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']);\nconst 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']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*/gm); // eslint-disable-line unicorn/better-regex\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n  __proto__: null,\n  ARIA_ATTR: ARIA_ATTR,\n  ATTR_WHITESPACE: ATTR_WHITESPACE,\n  CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n  DATA_ATTR: DATA_ATTR,\n  DOCTYPE_NAME: DOCTYPE_NAME,\n  ERB_EXPR: ERB_EXPR,\n  IS_ALLOWED_URI: IS_ALLOWED_URI,\n  IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n  MUSTACHE_EXPR: MUSTACHE_EXPR,\n  TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst 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};\nconst getGlobal = function getGlobal() {\n  return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n  if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n    return null;\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};\nconst _createHooksMap = function _createHooksMap() {\n  return {\n    afterSanitizeAttributes: [],\n    afterSanitizeElements: [],\n    afterSanitizeShadowDOM: [],\n    beforeSanitizeAttributes: [],\n    beforeSanitizeElements: [],\n    beforeSanitizeShadowDOM: [],\n    uponSanitizeAttribute: [],\n    uponSanitizeElement: [],\n    uponSanitizeShadowNode: []\n  };\n};\nfunction createDOMPurify() {\n  let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n  const DOMPurify = root => createDOMPurify(root);\n  DOMPurify.version = '3.2.6';\n  DOMPurify.removed = [];\n  if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\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 remove = lookupGetter(ElementPrototype, 'remove');\n  const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n  const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n  const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\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 = _createHooksMap();\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   * 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  /* allowed element names */\n  let ALLOWED_TAGS = null;\n  const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n  /* Allowed attribute names */\n  let ALLOWED_ATTR = null;\n  const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\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  /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n  let FORBID_TAGS = null;\n  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n  let FORBID_ATTR = null;\n  /* Decide if ARIA attributes are okay */\n  let ALLOW_ARIA_ATTR = true;\n  /* Decide if custom data attributes are okay */\n  let ALLOW_DATA_ATTR = true;\n  /* Decide if unknown protocols are okay */\n  let ALLOW_UNKNOWN_PROTOCOLS = false;\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  /* 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  /* 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  /* Decide if document with <html>... should be returned */\n  let WHOLE_DOCUMENT = false;\n  /* Track whether config is already set on this instance of DOMPurify. */\n  let SET_CONFIG = false;\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  /* 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  /* 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  /* 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  /* 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  /* 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  /* Keep element content when removing element? */\n  let KEEP_CONTENT = true;\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  /* Allow usage of profiles like html, svg and mathMl */\n  let USE_PROFILES = {};\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  /* 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  /* 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  /* Allowed XHTML+XML namespaces */\n  let ALLOWED_NAMESPACES = null;\n  const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n  let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n  let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\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  /* 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  /* Keep a reference to config to pass to hooks */\n  let CONFIG = null;\n  /* Ideally, do not touch anything below this line */\n  /* ______________________________________________ */\n  const formElement = document.createElement('form');\n  const isRegexOrFunction = function isRegexOrFunction(testValue) {\n    return testValue instanceof RegExp || testValue instanceof Function;\n  };\n  /**\n   * _parseConfig\n   *\n   * @param 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    /* Shield configuration object from tampering */\n    if (!cfg || typeof cfg !== 'object') {\n      cfg = {};\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    // 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    /* 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), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n    DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : 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) : clone({});\n    FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});\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    MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n    HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\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    /* 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    /* 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    /* Add #text in case KEEP_CONTENT is set to true */\n    if (KEEP_CONTENT) {\n      ALLOWED_TAGS['#text'] = true;\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    /* 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      // Overwrite existing TrustedTypes policy.\n      trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\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      // If creating the internal policy succeeded sign internal variables.\n      if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n        emptyHTML = trustedTypesPolicy.createHTML('');\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  /* 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   * @param element a DOM element whose namespace is being checked\n   * @returns 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    // 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      // 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      // 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      // 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      // 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      // 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    // 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    // 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   * _forceRemove\n   *\n   * @param 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      getParentNode(node).removeChild(node);\n    } catch (_) {\n      remove(node);\n    }\n  };\n  /**\n   * _removeAttribute\n   *\n   * @param name an Attribute name\n   * @param element a DOM node\n   */\n  const _removeAttribute = function _removeAttribute(name, element) {\n    try {\n      arrayPush(DOMPurify.removed, {\n        attribute: element.getAttributeNode(name),\n        from: element\n      });\n    } catch (_) {\n      arrayPush(DOMPurify.removed, {\n        attribute: null,\n        from: element\n      });\n    }\n    element.removeAttribute(name);\n    // We void attribute values for unremovable \"is\" attributes\n    if (name === 'is') {\n      if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n        try {\n          _forceRemove(element);\n        } catch (_) {}\n      } else {\n        try {\n          element.setAttribute(name, '');\n        } catch (_) {}\n      }\n    }\n  };\n  /**\n   * _initDocument\n   *\n   * @param dirty - a string of dirty markup\n   * @return 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    /* 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    /* 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   * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n   *\n   * @param root The root element or node to start traversing on.\n   * @return 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   * _isClobbered\n   *\n   * @param element element to check for clobbering attacks\n   * @return true if clobbered, false if safe\n   */\n  const _isClobbered = function _isClobbered(element) {\n    return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n  };\n  /**\n   * Checks whether the given object is a DOM node.\n   *\n   * @param value object to check whether it's a DOM node\n   * @return true is object is a DOM node\n   */\n  const _isNode = function _isNode(value) {\n    return typeof Node === 'function' && value instanceof Node;\n  };\n  function _executeHooks(hooks, currentNode, data) {\n    arrayForEach(hooks, hook => {\n      hook.call(DOMPurify, currentNode, data, CONFIG);\n    });\n  }\n  /**\n   * _sanitizeElements\n   *\n   * @protect nodeName\n   * @protect textContent\n   * @protect removeChild\n   * @param currentNode to check for permission to exist\n   * @return true if node was killed, false if left alive\n   */\n  const _sanitizeElements = function _sanitizeElements(currentNode) {\n    let content = null;\n    /* Execute a hook if present */\n    _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n    /* Check if element is clobbered or can clobber */\n    if (_isClobbered(currentNode)) {\n      _forceRemove(currentNode);\n      return true;\n    }\n    /* Now let's check the element's type and name */\n    const tagName = transformCaseFunc(currentNode.nodeName);\n    /* Execute a hook if present */\n    _executeHooks(hooks.uponSanitizeElement, currentNode, {\n      tagName,\n      allowedTags: ALLOWED_TAGS\n    });\n    /* Detect mXSS attempts abusing namespace confusion */\n    if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\\w!]/g, currentNode.textContent)) {\n      _forceRemove(currentNode);\n      return true;\n    }\n    /* Remove any occurrence of processing instructions */\n    if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n      _forceRemove(currentNode);\n      return true;\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    /* 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      /* 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    /* Check whether element has a valid namespace */\n    if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n      _forceRemove(currentNode);\n      return true;\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    /* 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    /* Execute a hook if present */\n    _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n    return false;\n  };\n  /**\n   * _isValidAttribute\n   *\n   * @param lcTag Lowercase tag name of containing element.\n   * @param lcName Lowercase attribute name.\n   * @param value Attribute value.\n   * @return 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    /* 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   * _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 tagName name of the tag of the node to sanitize\n   * @returns 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   * _sanitizeAttributes\n   *\n   * @protect attributes\n   * @protect nodeName\n   * @protect removeAttribute\n   * @protect setAttribute\n   *\n   * @param currentNode to sanitize\n   */\n  const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n    /* Execute a hook if present */\n    _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n    const {\n      attributes\n    } = currentNode;\n    /* Check if we have attributes; if not we might have a text node */\n    if (!attributes || _isClobbered(currentNode)) {\n      return;\n    }\n    const hookEvent = {\n      attrName: '',\n      attrValue: '',\n      keepAttr: true,\n      allowedAttributes: ALLOWED_ATTR,\n      forceKeepAttr: undefined\n    };\n    let l = attributes.length;\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      const initValue = attrValue;\n      let value = name === 'value' ? initValue : stringTrim(initValue);\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      _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n      value = hookEvent.attrValue;\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        // Prefix the value and later re-create the attribute with the sanitized value\n        value = SANITIZE_NAMED_PROPS_PREFIX + value;\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      /* Did the hooks approve of the attribute? */\n      if (hookEvent.forceKeepAttr) {\n        continue;\n      }\n      /* Did the hooks approve of the attribute? */\n      if (!hookEvent.keepAttr) {\n        _removeAttribute(name, currentNode);\n        continue;\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      /* 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      /* Is `value` valid for this attribute? */\n      const lcTag = transformCaseFunc(currentNode.nodeName);\n      if (!_isValidAttribute(lcTag, lcName, value)) {\n        _removeAttribute(name, currentNode);\n        continue;\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      /* Handle invalid data-* attribute set by try-catching it */\n      if (value !== initValue) {\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          _removeAttribute(name, currentNode);\n        }\n      }\n    }\n    /* Execute a hook if present */\n    _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n  };\n  /**\n   * _sanitizeShadowDOM\n   *\n   * @param fragment to iterate over recursively\n   */\n  const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n    let shadowNode = null;\n    const shadowIterator = _createNodeIterator(fragment);\n    /* Execute a hook if present */\n    _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n    while (shadowNode = shadowIterator.nextNode()) {\n      /* Execute a hook if present */\n      _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n      /* Sanitize tags and elements */\n      _sanitizeElements(shadowNode);\n      /* Check attributes next */\n      _sanitizeAttributes(shadowNode);\n      /* Deep shadow DOM detected */\n      if (shadowNode.content instanceof DocumentFragment) {\n        _sanitizeShadowDOM(shadowNode.content);\n      }\n    }\n    /* Execute a hook if present */\n    _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\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    /* 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    /* Return dirty HTML if DOMPurify cannot run */\n    if (!DOMPurify.isSupported) {\n      return dirty;\n    }\n    /* Assign config vars */\n    if (!SET_CONFIG) {\n      _parseConfig(cfg);\n    }\n    /* Clean up removed elements */\n    DOMPurify.removed = [];\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      /* Initialize the document to work on */\n      body = _initDocument(dirty);\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    /* Remove first element node (ours) if FORCE_BODY is set */\n    if (body && FORCE_BODY) {\n      _forceRemove(body.firstChild);\n    }\n    /* Get node iterator */\n    const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n    /* Now start iterating over the created document */\n    while (currentNode = nodeIterator.nextNode()) {\n      /* Sanitize tags and elements */\n      _sanitizeElements(currentNode);\n      /* Check attributes next */\n      _sanitizeAttributes(currentNode);\n      /* Shadow DOM detected, sanitize it */\n      if (currentNode.content instanceof DocumentFragment) {\n        _sanitizeShadowDOM(currentNode.content);\n      }\n    }\n    /* If we sanitized `dirty` in-place, return it. */\n    if (IN_PLACE) {\n      return dirty;\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    /* 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    /* 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  DOMPurify.setConfig = function () {\n    let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n    _parseConfig(cfg);\n    SET_CONFIG = true;\n  };\n  DOMPurify.clearConfig = function () {\n    CONFIG = null;\n    SET_CONFIG = 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  DOMPurify.addHook = function (entryPoint, hookFunction) {\n    if (typeof hookFunction !== 'function') {\n      return;\n    }\n    arrayPush(hooks[entryPoint], hookFunction);\n  };\n  DOMPurify.removeHook = function (entryPoint, hookFunction) {\n    if (hookFunction !== undefined) {\n      const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n      return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n    }\n    return arrayPop(hooks[entryPoint]);\n  };\n  DOMPurify.removeHooks = function (entryPoint) {\n    hooks[entryPoint] = [];\n  };\n  DOMPurify.removeAllHooks = function () {\n    hooks = _createHooksMap();\n  };\n  return DOMPurify;\n}\nvar purify = createDOMPurify();\n\n\n//# sourceMappingURL=purify.es.mjs.map\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./node_modules/dompurify/dist/purify.es.mjs?");

/***/ }),

/***/ "./src/components/data-table/DataTableComponent.js":
/*!*********************************************************!*\
  !*** ./src/components/data-table/DataTableComponent.js ***!
  \*********************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const { elementGenerator: generator, translationService } = WOP;\n    /**\n     * @typedef TableCell\n     * @property {string?} label\n     * @property {string?} className\n     * @property {(cell: HTMLTableCellElement) => void?} renderer\n     */\n\n    /**\n     * Renders table cell.\n     *\n     * @param {'td' | 'th'} type\n     * @param {TableCell} cellData\n     * @param {boolean} header\n     * @returns {HTMLElement}\n     */\n    const renderCell = (type, cellData, header= false) => {\n        let cell = generator.createElement(type, cellData.className, cellData.label, null, null, true);\n\n        if (header) {\n            cell = generator.createElement(type);\n            const content = generator.createElement('span', cellData.className, cellData.label);\n            cell.appendChild(content);\n        }\n\n        cellData.renderer && cellData.renderer(cell);\n\n        return cell;\n    };\n\n    const getTableElement = () => {\n        return generator.createElementFromHTML(\n            '<div class=\"op-table-wrapper\"><table><thead><tr></tr></thead><tbody></tbody></table></div>'\n        );\n    };\n\n    /**\n     * Data table component.\n     *\n     * @param {TableCell[]} headers\n     * @param {TableCell[][]} items\n     * @param {string?} className\n     */\n    const createDataTable = (headers, items, className) => {\n        const tableWrapper = getTableElement();\n\n        headers.forEach((header) => {\n            header.label = translationService.translate(header.label);\n        });\n\n        const heading = tableWrapper.querySelector('thead tr');\n        heading.append(...headers.map((cellData) => renderCell('th', cellData, true)));\n\n        createTableRows(tableWrapper, items);\n\n        return generator.createElement('div', className, '', null, [tableWrapper]);\n    };\n\n    /**\n     * Creates a data table.\n     *\n     * @param {TableCell[]} header\n     * @param {TableCell[][]} items\n     * @return {HTMLElement}\n     */\n    const createPaymentsDataTable = (header, items) => {\n        /**\n         * Renders item card data.\n         *\n         * @param {TableCell} cellHeader\n         * @param {TableCell} cellData\n         * @param {string} className\n         * @returns {HTMLElement}\n         */\n        const createCardItemElements = (cellHeader, cellData, className) => {\n            const header = generator.createElement('span', 'opp-info-label', cellHeader.label);\n            cellHeader.renderer && cellHeader.renderer(header);\n            const cell = generator.createElement('span', 'opp-info-data', cellData.label);\n            cellData.renderer && cellData.renderer(cell);\n\n            return generator.createElement('li', `opp-payment-info-item ${className}`, '', null, [header, cell]);\n        };\n\n        const tableWrapper = getTableElement();\n        const mobileWrapper = generator.createElement('div', 'op-data-table-wrapper');\n        mobileWrapper.append(\n            ...items.map((item) => {\n                const paymentName = generator.createElement('div', 'opp-payment-method-name', item[0].label);\n                const infoList = generator.createElement('ul', 'opp-payment-info-list', '', null, [\n                    createCardItemElements(header[4], item[4], 'opp-info-status'),\n                    createCardItemElements(header[1], item[1], 'opp-info-currencies'),\n                    createCardItemElements(header[2], item[2], 'opp-info-countries'),\n                    createCardItemElements(header[3], item[3], 'opp-info-type')\n                ]);\n\n                const paymentActions = generator.createElement('div', 'opp-payment-actions');\n\n                item[0].renderer(paymentName);\n                item[5].renderer(paymentActions);\n\n                return generator.createElement('div', 'opp-data-card', '', null, [\n                    paymentName,\n                    infoList,\n                    paymentActions\n                ]);\n            })\n        );\n\n        const heading = tableWrapper.querySelector('thead tr');\n        heading.append(...header.map((cellData) => renderCell('th', cellData, true)));\n\n        createTableRows(tableWrapper, items);\n\n        return generator.createElement('div', '', '', null, [tableWrapper, mobileWrapper]);\n    };\n\n    /**\n     * Renders table rows.\n     *\n     * @param tableWrapper\n     * @param {TableCell[][]} items\n     */\n    const createTableRows = (tableWrapper, items) => {\n        items.length &&\n        tableWrapper.querySelector('tbody').append(\n            ...items.map((item) => {\n                const row = generator.createElement('tr');\n                row.append(...item.map((cellData) => renderCell('td', cellData)));\n\n                return row;\n            })\n        );\n    };\n\n    /**\n     * Renders the empty list message with the image.\n     *\n     * @param {string} label\n     * @returns {HTMLElement}\n     */\n    const createNoItemsMessage = (label) => {\n        return generator.createElement('div', 'opp-no-items-wrapper', '', null, [\n            generator.createElement('p', '', label)\n        ]);\n    };\n\n    WOP.components.DataTable = {\n        createDataTable,\n        createPaymentsDataTable,\n        createTableRows,\n        createNoItemsMessage\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/data-table/DataTableComponent.js?");

/***/ }),

/***/ "./src/components/dropdown/DropdownComponent.js":
/*!******************************************************!*\
  !*** ./src/components/dropdown/DropdownComponent.js ***!
  \******************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    /**\n     * @typedef DropdownComponentModel\n     *\n     * @property {Option[]} options\n     * @property {string?} name\n     * @property {string?} value\n     * @property {string?} placeholder\n     * @property {(value: string) => void?} onChange\n     * @property {boolean?} updateTextOnChange\n     * @property {boolean?} searchable\n     */\n\n    /**\n     * Single-select dropdown component.\n     *\n     * @param {DropdownComponentModel} props\n     *\n     * @constructor\n     */\n    const DropdownComponent = ({\n        options,\n        name,\n        value = '',\n        placeholder,\n        onChange,\n        updateTextOnChange = true,\n        searchable = false\n    }) => {\n        const { elementGenerator: generator, translationService } = WOP;\n        const filterItems = (text) => {\n            const filteredItems = text\n                ? options.filter((option) => option.label.toLowerCase().includes(text.toLowerCase()))\n                : options;\n\n            if (filteredItems.length === 0) {\n                selectButton.classList.add('ops--no-results');\n            } else {\n                selectButton.classList.remove('ops--no-results');\n            }\n\n            renderOptions(filteredItems);\n        };\n\n        const renderOptions = (options) => {\n            list.innerHTML = '';\n            options.forEach((option) => {\n                const listItem = generator.createElement(\n                    'li',\n                    'opp-dropdown-list-item' + (option === selectedItem ? ' ops--selected' : ''),\n                    option.label\n                );\n                list.append(listItem);\n\n                listItem.addEventListener('click', () => {\n                    hiddenInput.value = WOP.sanitize(option.value);\n                    updateTextOnChange && (buttonSpan.innerHTML = WOP.sanitize(translationService.translate(option.label)));\n                    list.classList.remove('ops--show');\n                    list.childNodes.forEach((node) => node.classList.remove('ops--selected'));\n                    listItem.classList.add('ops--selected');\n                    wrapper.classList.remove('ops--active');\n                    buttonSpan.classList.add('ops--selected');\n                    selectButton.classList.remove('ops--search-active');\n                    onChange && onChange(WOP.sanitize(option.value));\n                });\n            });\n        };\n\n        const hiddenInput = generator.createElement('input', 'opp-hidden-input', '', { type: 'hidden', name, value });\n        const wrapper = generator.createElement('div', 'op-single-select-dropdown');\n\n        const selectButton = generator.createElement('button', 'opp-dropdown-button opp-field-component', '', {\n            type: 'button'\n        });\n        const selectedItem = options.find((option) => option.value === value);\n        const buttonSpan = generator.createElement(\n            'span',\n            selectedItem ? 'ops--selected' : '',\n            selectedItem ? selectedItem.label : placeholder\n        );\n        selectButton.append(buttonSpan);\n\n        const searchInput = generator.createElement('input', 'op-text-input', '', {\n            type: 'text',\n            placeholder: translationService.translate('general.search')\n        });\n        searchInput.addEventListener('input', (event) => filterItems(event.currentTarget?.value || ''));\n        if (searchable) {\n            selectButton.append(searchInput);\n        }\n\n        const list = generator.createElement('ul', 'opp-dropdown-list');\n        renderOptions(options);\n\n        selectButton.addEventListener('click', () => {\n            list.classList.toggle('ops--show');\n            wrapper.classList.toggle('ops--active');\n            if (searchable) {\n                selectButton.classList.toggle('ops--search-active');\n                if (selectButton.classList.contains('ops--search-active')) {\n                    searchInput.focus();\n                    searchInput.value = '';\n                    filterItems('');\n                }\n            }\n        });\n\n        document.documentElement.addEventListener('click', (event) => {\n            if (!wrapper.contains(event.target) && event.target !== wrapper) {\n                list.classList.remove('ops--show');\n                wrapper.classList.remove('ops--active');\n                selectButton.classList.remove('ops--search-active');\n            }\n        });\n\n        wrapper.append(hiddenInput, selectButton, list);\n\n        return wrapper;\n    };\n\n    WOP.components.Dropdown = {\n        /**\n         * @param {DropdownComponentModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => DropdownComponent(config)\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/dropdown/DropdownComponent.js?");

/***/ }),

/***/ "./src/components/footer/Footer.js":
/*!*****************************************!*\
  !*** ./src/components/footer/Footer.js ***!
  \*****************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef FooterModel\n     *\n     * @property {string} newVersion\n     * @property {string} installedVersion\n     * */\n\n    /**\n     * Footer component.\n     *\n     * @param {FooterModel} params\n     * @returns {HTMLElement}\n     * @constructor\n     */\n    const Footer = ({\n                        newVersion,\n                        installedVersion\n                    }) => {\n        const { elementGenerator: generator, translationService } = WOP;\n        const footer = generator.createElement('div', 'op-footer');\n\n        if (newVersion !== installedVersion && newVersion !== '') {\n            const update = generator.createElement('div', 'op-update', translationService.translate('general.version.update', ['v' + newVersion]));\n            footer.appendChild(update);\n        }\n\n        const version = generator.createElement('p', 'op-version', 'v' + installedVersion);\n        footer.appendChild(version);\n\n        return footer;\n    };\n\n    WOP.components.Footer = {\n        /**\n         * @param {FooterModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => Footer(config)\n    };\n})();\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/footer/Footer.js?");

/***/ }),

/***/ "./src/components/header-menu/HeaderMenu.js":
/*!**************************************************!*\
  !*** ./src/components/header-menu/HeaderMenu.js ***!
  \**************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    /**\n     * @param {LinkDropDownComponentModel} linkDropDown\n     * @param {string} page\n     *\n     * @returns {*|HTMLElement}\n     * @constructor\n     */\n    const HeaderMenu = (linkDropDown, page) => {\n        const {\n            elementGenerator: generator,\n            translationService\n        } = WOP;\n\n        document.getElementsByTagName('body')[0].style.overflow = 'hidden';\n\n        let content = generator.createElement('div', 'op-header-menu-content');\n        const paymentsTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-payment',\n            translationService.translate('general.payments')\n        );\n        paymentsTab.href = '#payments';\n        paymentsTab.addEventListener('click', function () {\n            let menu = document.querySelector('.op-header-menu');\n            let menuItem = document.querySelector('.op-clicked');\n\n            if (menu) {\n                menu.remove();\n                document.getElementsByTagName('body')[0].style.overflow = 'scroll';\n            }\n\n            menuItem.classList.toggle('op-clicked');\n        });\n\n        const monitoringTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-monitoring',\n            translationService.translate('general.monitoring')\n        );\n        monitoringTab.href = '#monitoring';\n        monitoringTab.addEventListener('click', function () {\n            let menu = document.querySelector('.op-header-menu');\n            let menuItem = document.querySelector('.op-clicked');\n\n            if (menu) {\n                menu.remove();\n                document.getElementsByTagName('body')[0].style.overflow = 'scroll';\n            }\n\n            menuItem.classList.toggle('op-clicked');\n        })\n        const settingsTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-settings',\n            translationService.translate('general.settings')\n        );\n        settingsTab.href = '#settings';\n        settingsTab.addEventListener('click', function () {\n            let menu = document.querySelector('.op-header-menu');\n            let menuItem = document.querySelector('.op-clicked');\n\n            if (menu) {\n                menu.remove();\n                document.getElementsByTagName('body')[0].style.overflow = 'scroll';\n            }\n\n            menuItem.classList.toggle('op-clicked');\n        });\n\n        if (page === 'connection') {\n            paymentsTab.classList.add('ops--disabled');\n            monitoringTab.classList.add('ops--disabled');\n            settingsTab.classList.add('ops--disabled');\n        }\n\n        const helpTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-help',\n            translationService.translate('general.needHelp')\n        );\n        helpTab.href = translationService.translate('general.helpLink');\n        helpTab.target = '_blank';\n        helpTab.rel = 'noopener noreferrer';\n        const documentation = generator.createElement(\n            'div',\n            'op-header-tab op-documentation-wrapper'\n        );\n        const documentationTitle = generator.createElement(\n            'span',\n            'op-header-documentation',\n            translationService.translate('general.documentation')\n        );\n\n        documentation.appendChild(documentationTitle);\n        const docsLinks = generator.createElement('ul', 'op-documents-list');\n\n        linkDropDown.options.forEach((option) => {\n            const listItem = generator.createElement(\n                'li',\n                'op-documents-link-wrapper'\n            );\n            const listTitle = generator.createElement(\n                'span',\n                'op-documents-link',\n                translationService.translate(option.label)\n            );\n\n            listTitle.addEventListener('click', () => {\n                window.open(option.link, '_blank');\n            });\n            listItem.appendChild(listTitle);\n\n            docsLinks.appendChild(listItem);\n        });\n        documentation.appendChild(docsLinks);\n\n        content.appendChild(paymentsTab);\n        content.appendChild(monitoringTab);\n        content.appendChild(settingsTab);\n        content.appendChild(helpTab);\n        content.appendChild(documentation);\n\n        const modal = generator.createElement('div', 'op-header-menu');\n\n        modal.appendChild(content);\n\n        return modal;\n    };\n\n    WOP.components.HeaderMenu = {\n        /**\n         * @param {LinkDropDownComponentModel} linkDropDown\n         * @param {string} page\n         * @returns {HTMLElement}\n         */\n        create: (linkDropDown, page) => HeaderMenu(linkDropDown, page)\n    };\n})();\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/header-menu/HeaderMenu.js?");

/***/ }),

/***/ "./src/components/header/Header.js":
/*!*****************************************!*\
  !*** ./src/components/header/Header.js ***!
  \*****************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef HeaderModel\n     *\n     * @property {string?} brand\n     * @property {LinkDropDownComponentModel?} linkDropDown\n     * @property {string} page\n     * @property {string} mode\n     * */\n\n    /**\n     * Header component.\n     *\n     * @param {HeaderModel} params\n     * @returns {HTMLElement}\n     * @constructor\n     */\n    const Header = ({\n        brand,\n        linkDropDown,\n        page,\n        mode\n    }) => {\n        const { elementGenerator: generator, translationService } = WOP;\n        const header = generator.createElement('div');\n        const navigation = generator.createElement('div', 'op-main-header-navigation');\n        const leftPart = generator.createElement('div', 'op-main-header-left');\n        const logoWrapper = generator.createElement('div', 'op-main-logo');\n        logoWrapper.appendChild(generator.createElement(\n            'img', 'op-small-logo', '',\n            { 'alt': 'logo', 'src': WOP.baseImgUrl + '/' + brand + '-small.svg' }\n        ));\n        logoWrapper.appendChild(generator.createElement(\n            'img', 'op-big-logo',\n            '', { 'alt': 'logo', 'src': WOP.baseImgUrl + '/' + brand + '.svg' }\n        ));\n\n        const badge = generator.createElement(\n            'span',\n            'op-header-badge',\n            translationService.translate('general.direct').toUpperCase()\n        );\n        const documentationWrapper = generator.createElement('div', 'op-link-dropdown');\n        const documentation = generator.createLinkDropdownField(linkDropDown);\n        documentationWrapper.appendChild(documentation);\n        const rightPart = generator.createElement('div', 'op-main-header-right');\n        const menuItem = generator.createElement('button', 'op-header-menu-item');\n        menuItem.addEventListener('click', function () {\n            if (menuItem.classList.contains('op-clicked')) {\n                let menu = document.querySelector('.op-header-menu');\n\n                if (menu) {\n                    menu.remove();\n                    document.getElementsByTagName('body')[0].style.overflow = 'scroll';\n                }\n            } else {\n                let mainPage = WOP.templateService.getMainPage();\n                let menuBox = WOP.components.HeaderMenu.create(linkDropDown, page);\n                menuBox.classList.add('op-open');\n\n                mainPage.firstChild.appendChild(menuBox);\n            }\n\n            menuItem.classList.toggle('op-clicked');\n        })\n        const baseUrl = window.location.href.split('#')[0];\n        const paymentsTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-payment',\n            translationService.translate('general.payments')\n        );\n        paymentsTab.href = baseUrl + '#payments';\n        const monitoringTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-monitoring',\n            translationService.translate('general.monitoring')\n        );\n        monitoringTab.href = baseUrl + '#monitoring';\n        const settingsTab = generator.createElement(\n            'a',\n            'op-header-tab op-header-settings',\n            translationService.translate('general.settings')\n        );\n        settingsTab.href = baseUrl + '#settings';\n\n        rightPart.appendChild(menuItem);\n        rightPart.appendChild(paymentsTab);\n        rightPart.appendChild(monitoringTab);\n        rightPart.appendChild(settingsTab);\n\n        leftPart.appendChild(logoWrapper);\n        leftPart.appendChild(badge);\n        leftPart.appendChild(documentationWrapper);\n\n        navigation.appendChild(leftPart);\n        navigation.appendChild(rightPart);\n\n        const titleHeader = generator.createElement('div', 'op-main-title-header');\n        const title = generator.createElement('div', 'op-main-title', '');\n        const state = generator.createElement('div', 'op-status');\n        state.id = 'op-status';\n\n        if (mode !== undefined) {\n            const modeDiv = generator.createElement('div', 'op-mode');\n            const indicator = generator.createElement('span', 'op-icon');\n\n            if (mode === 'test') {\n                indicator.classList.add('op-sandbox');\n            } else {\n                indicator.classList.add('op-live');\n            }\n\n            const modeText = generator.createElement('p', 'op-mode-text', 'general.mode.' + mode);\n            modeDiv.appendChild(indicator);\n            modeDiv.appendChild(modeText);\n            state.appendChild(modeDiv);\n        }\n\n        titleHeader.appendChild(title);\n        titleHeader.appendChild(state);\n\n        const responsiveHeader = generator.createElement('div', 'op-main-responsive-header');\n        responsiveHeader.appendChild(state.cloneNode(true));\n\n        header.appendChild(navigation);\n        header.appendChild(titleHeader);\n        header.appendChild(responsiveHeader);\n\n        return header;\n    };\n\n    WOP.components.Header = {\n        /**\n         * @param {HeaderModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => Header(config)\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/header/Header.js?");

/***/ }),

/***/ "./src/components/link-dropdown/LinkDropDownComponent.js":
/*!***************************************************************!*\
  !*** ./src/components/link-dropdown/LinkDropDownComponent.js ***!
  \***************************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef Option\n     *\n     * @property {string} label\n     * @property {string} link\n     */\n\n    /**\n     * @typedef LinkDropDownComponentModel\n     *\n     * @property {Option[]} options\n     * @property {string?} name\n     * @property {string?} className\n     * */\n\n    /**\n     * Link dropdown component.\n     *\n     * @param {LinkDropDownComponentModel} params\n     * @returns {HTMLElement}\n     * @constructor\n     */\n    const LinkDropDownComponent = ({\n        options,\n        name = '',\n        className = ''\n    }) => {\n        const { elementGenerator: generator, translationService } = WOP;\n\n        options.forEach((option) => {\n            option.label = translationService.translate(option.label);\n        });\n\n        const createListItem = (additionalClass, label, htmlKey) => {\n            const item = generator.createElement('li', `opp-dropdown-list-item ${additionalClass}`, label, htmlKey, []);\n            list.append(item);\n            return item;\n        };\n\n        const renderOption = (option) => {\n            const listItem = createListItem('', option.label, null);\n\n            listItem.addEventListener('click', () => {\n                window.open(option.link, '_blank');\n            });\n        };\n        const label = translationService.translate(name);\n        const wrapper = generator.createElement('div', 'op-list-dropdown' + (className ? ' ' + className : ''));\n        const selectButton = generator.createElement(\n            'button',\n            'opp-dropdown-button opt--ghost',\n            label,\n            {\n                type: 'button'\n            },\n            []\n        );\n\n        const list = generator.createElement('ul', 'opp-dropdown-list');\n        options.forEach(renderOption);\n\n        selectButton.addEventListener('click', (event) => {\n            preventDefaults(event);\n            list.classList.toggle('ops--show');\n            wrapper.classList.toggle('ops--active');\n        });\n\n        window.addEventListener('click', (event) => {\n            if (!list.contains(event.target) && event.target !== list) {\n                list.classList.remove('ops--show');\n                wrapper.classList.remove('ops--active');\n            }\n        });\n\n        wrapper.append(selectButton, list);\n\n        return wrapper;\n    };\n\n    WOP.components.LinkDropDownComponent = {\n        /**\n         * @param {LinkDropDownComponentModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => LinkDropDownComponent(config)\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/link-dropdown/LinkDropDownComponent.js?");

/***/ }),

/***/ "./src/components/modal/ModalComponent.js":
/*!************************************************!*\
  !*** ./src/components/modal/ModalComponent.js ***!
  \************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    /**\n     * @typedef ButtonConfig\n     * @property {string} label\n     * @property {string?} className\n     * @property {'primary' | 'secondary'} type\n     * @property {() => void} onClick\n     */\n\n    /**\n     * @typedef ModalConfiguration\n     * @property {string?} title\n     * @property {string?} className\n     * @property {HTMLElement} content The content of the body.\n     * @property {ButtonConfig[]} buttons Footer buttons.\n     * @property {(modal: HTMLDivElement) => void?} onOpen Will fire after the modal is opened.\n     * @property {() => boolean?} onClose Will fire before the modal is closed.\n     *      If the return value is false, the modal will not be closed.\n     * @property {boolean} [footer=false] Indicates whether to use footer. Defaults to false.\n     * @property {boolean} [canClose=true] Indicates whether to use an (X) button or click outside the modal\n     * to close it. Defaults to true.\n     * @property {boolean} [fullWidthBody=false] Indicates whether to make body full width\n     */\n\n    /**\n     * @param {ModalConfiguration} configuration\n     * @constructor\n     */\n    function ModalComponent(configuration) {\n        const { templateService, translationService, utilities, elementGenerator } = WOP,\n            config = configuration;\n\n        /**\n         * @type {HTMLDivElement}\n         */\n        let modal;\n\n        /**\n         * Closes the modal on Esc key.\n         *\n         * @param {KeyboardEvent} event\n         */\n        const closeOnEsc = (event) => {\n            if (event.key === 'Escape') {\n                this.close();\n            }\n        };\n\n        /**\n         * Closes the modal.\n         */\n        this.close = () => {\n            if (!config.onClose || config.onClose()) {\n                window.removeEventListener('keyup', closeOnEsc);\n                modal?.remove();\n            }\n        };\n\n        /**\n         * Opens the modal.\n         */\n        this.open = () => {\n            const modalTemplate =\n                '<div id=\"op-modal\" class=\"op-modal ops--hidden\">\\n' +\n                '    <div class=\"opp-modal-content\">' +\n                '        <button class=\"op-button opt--ghost opm--icon-only opp-close-button\"><span></span></button>' +\n                '        <div class=\"opp-title\"></div>' +\n                '        <div class=\"opp-body\"></div>' +\n                '        <div class=\"opp-footer\"></div>' +\n                '    </div>' +\n                '</div>';\n\n            modal = WOP.elementGenerator.createElementFromHTML(modalTemplate);\n            const closeBtn = modal.querySelector('.opp-close-button'),\n                closeBtnSpan = modal.querySelector('.opp-close-button span'),\n                title = modal.querySelector('.opp-title'),\n                body = modal.querySelector('.opp-body'),\n                footer = modal.querySelector('.opp-footer');\n\n            utilities.showElement(modal);\n            if (config.canClose === false) {\n                utilities.hideElement(closeBtn);\n            } else {\n                window.addEventListener('keyup', closeOnEsc);\n                closeBtn.addEventListener('click', this.close);\n                closeBtnSpan.style.display = 'flex';\n                modal.addEventListener('click', (event) => {\n                    if (event.target.id === 'op-modal') {\n                        event.preventDefault();\n                        this.close();\n\n                        return false;\n                    }\n                });\n            }\n\n            if (config.title) {\n                title.innerHTML = WOP.sanitize(translationService.translate(config.title));\n            } else {\n                utilities.hideElement(title);\n            }\n\n            if (config.className) {\n                modal.classList.add(config.className);\n            }\n\n            body.append(...(Array.isArray(config.content) ? config.content : [config.content]));\n            if (configuration.fullWidthBody) {\n                body.classList.add('opm--full-width');\n            }\n\n            if (config.footer === false || !config.buttons) {\n                utilities.hideElement(footer);\n            } else {\n                config.buttons.forEach((button) => {\n                    footer.appendChild(elementGenerator.createButton(button));\n                });\n            }\n\n            templateService.getMainPage().parentNode.appendChild(modal);\n            if (config.onOpen) {\n                config.onOpen(modal);\n            }\n        };\n    }\n\n    WOP.components.Modal = {\n        /** @param {ModalConfiguration} config */\n        create: (config) => new ModalComponent(config)\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/modal/ModalComponent.js?");

/***/ }),

/***/ "./src/components/multiselect-dropdown/MultiselectDropdownComponent.js":
/*!*****************************************************************************!*\
  !*** ./src/components/multiselect-dropdown/MultiselectDropdownComponent.js ***!
  \*****************************************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef MultiselectDropdownComponentModel\n     *\n     * @property {Option[]} options\n     * @property {string?} name\n     * @property {string[]?} values\n     * @property {string[]?} lockedValues - Values that are checked by default and cannot be unchecked\n     * @property {string?} placeholder\n     * @property {string?} selectedText\n     * @property {(values: string[]) => void} onChange\n     * @property {boolean?} updateTextOnChange\n     * @property {boolean?} useAny\n     * @property {string?} className\n     * */\n\n    /**\n     * Multiselect dropdown component.\n     *\n     * @param {MultiselectDropdownComponentModel} params\n     * @returns {HTMLElement}\n     * @constructor\n     */\n    const MultiselectDropdownComponent = ({\n        options,\n        name = '',\n        values = [],\n        lockedValues = [],\n        placeholder,\n        selectedText,\n        onChange,\n        updateTextOnChange = true,\n        useAny = true,\n        className = ''\n    }) => {\n        const { elementGenerator: generator, translationService } = WOP;\n\n        options.forEach((option) => {\n            option.label = translationService.translate(option.label);\n        });\n\n        const createChip = (item) => {\n            const isLocked = lockedValues.includes(item.value);\n            const chip = generator.createElement('span', 'opp-chip' + (isLocked ? ' opp-chip--locked' : ''));\n            const chipLabel = generator.createElement('span', 'opp-chip-label', WOP.sanitize(item.label));\n\n            if (isLocked) {\n                chip.append(chipLabel);\n            } else {\n                const chipClose = generator.createElement('span', 'opp-chip-close', '×');\n\n                chipClose.addEventListener('click', (event) => {\n                    preventDefaults(event);\n                    const index = selectedItems.indexOf(item);\n                    if (index > -1) {\n                        selectedItems.splice(index, 1);\n                    }\n\n                    const listItem = list.querySelector(`[data-value=\"${item.value}\"]`);\n                    if (listItem) {\n                        listItem.classList.remove('ops--selected');\n                        listItem.childNodes[0].checked = false;\n                    }\n\n                    handleDisplayedItems();\n                });\n\n                chip.append(chipLabel, chipClose);\n            }\n            return chip;\n        };\n\n        const handleDisplayedItems = (fireChange = true) => {\n            hiddenInput.value = WOP.sanitize(selectedItems.map((item) => WOP.sanitize(item.value)).join(','));\n            if (useAny) {\n                const anyItem = list.querySelector('.opt--any');\n                if (selectedItems.length > 0) {\n                    anyItem?.classList.remove('ops--selected');\n                } else {\n                    anyItem.classList.toggle('ops--selected');\n\n                    list.querySelectorAll(':not(.opt--any)').forEach((listItem) => {\n                        listItem.classList.remove('ops--selected');\n                        if (anyItem.classList.contains('ops--selected')) {\n                            listItem.classList.add('ops--disabled');\n                        } else {\n                            listItem.classList.remove('ops--disabled');\n                        }\n                    });\n                }\n            }\n\n            if (updateTextOnChange) {\n                const buttonContent = selectButton.firstElementChild;\n                buttonContent.innerHTML = '';\n\n                if (selectedItems.length > 0) {\n                    selectedItems.forEach((item) => {\n                        buttonContent.append(createChip(item));\n                    });\n                } else {\n                    buttonContent.innerHTML = WOP.sanitize(translationService.translate(placeholder));\n                }\n            }\n\n            fireChange && onChange?.(selectedItems.map((item) => WOP.sanitize(item.value)));\n        };\n\n        const createListItem = (additionalClass, label, htmlKey) => {\n            const item = generator.createElement('li', `opp-dropdown-list-item ${additionalClass}`, label, htmlKey, [\n                generator.createElement('input', 'opp-checkbox', '', { type: 'checkbox' })\n            ]);\n            list.append(item);\n            return item;\n        };\n\n        const renderOption = (option) => {\n            const isLocked = lockedValues.includes(option.value);\n            const isSelected = values?.includes(option.value) || isLocked;\n            const listItem = createListItem(\n                (isSelected ? 'ops--selected' : '') + (isLocked ? ' ops--locked' : ''),\n                option.label,\n                null\n            );\n            listItem.setAttribute('data-value', option.value);\n\n            if (isLocked) {\n                listItem.childNodes[0].checked = true;\n            }\n\n            selectedItems.forEach((item) => {\n                if (option.value === item.value) {\n                    listItem.classList.add('ops--selected');\n                }\n            });\n\n            listItem.addEventListener('click', () => {\n                if (isLocked) {\n                    return;\n                }\n                listItem.classList.toggle('ops--selected');\n                listItem.childNodes[0].checked = listItem.classList.contains('ops--selected');\n                if (!selectedItems.includes(option)) {\n                    selectedItems.push(option);\n                } else {\n                    const index = selectedItems.indexOf(option);\n                    selectedItems.splice(index, 1);\n                }\n\n                handleDisplayedItems();\n            });\n        };\n\n        let selectedItems = options.filter((option) => values?.includes(option.value) || lockedValues.includes(option.value));\n\n        const hiddenInput = generator.createElement('input', 'opp-hidden-input', '', {\n            type: 'hidden',\n            name,\n            value: values?.join(',') || ''\n        });\n        const wrapper = generator.createElement('div', 'op-multiselect-dropdown' + (className ? ' ' + className : ''));\n        const selectButton = generator.createElement(\n            'button',\n            'opp-dropdown-button opp-field-component',\n            '',\n            {\n                type: 'button'\n            },\n            [generator.createElement('span', selectedItems ? 'ops--selected' : '', placeholder)]\n        );\n\n        const list = generator.createElement('ul', 'opp-dropdown-list');\n        if (useAny) {\n            const anyItem = createListItem('opt--any' + (!values?.length ? ' ops--selected' : ''), 'general.any', null);\n\n            anyItem.addEventListener('click', () => {\n                selectedItems = options.filter((option) => lockedValues.includes(option.value));\n                anyItem.childNodes[0].checked = anyItem.classList.contains('ops--selected');\n\n                handleDisplayedItems();\n            });\n        }\n\n        options.forEach(renderOption);\n\n        selectButton.addEventListener('click', (event) => {\n            preventDefaults(event);\n            list.classList.toggle('ops--show');\n            wrapper.classList.toggle('ops--active');\n        });\n\n        window.addEventListener('click', (event) => {\n            if (!list.contains(event.target) && event.target !== list) {\n                list.classList.remove('ops--show');\n                wrapper.classList.remove('ops--active');\n            }\n        });\n\n        wrapper.append(hiddenInput, selectButton, list);\n\n        values?.length && handleDisplayedItems(false);\n\n        return wrapper;\n    };\n\n    WOP.components.MultiselectDropdown = {\n        /**\n         * @param {MultiselectDropdownComponentModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => MultiselectDropdownComponent(config)\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/multiselect-dropdown/MultiselectDropdownComponent.js?");

/***/ }),

/***/ "./src/components/sliding-modal/SlidingModal.js":
/*!******************************************************!*\
  !*** ./src/components/sliding-modal/SlidingModal.js ***!
  \******************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef VaultTitle\n     *\n     * @property {string} language\n     * @property {string} translation\n     */\n\n    /**\n     * @typedef AdditionalData\n     *\n     * @property {VaultTitle[]?} vaultTitleCollection\n     * @property {boolean?} instantPayment\n     * @property {string?} recurrenceType\n     * @property {string?} signatureType\n     * @property {int?} sessionTimeout\n     * @property {string?} paymentProductId\n     * @property {string?} paymentOption\n     * @property {string?} logo\n     * @property {boolean?} enableGroupCards\n     * @property {boolean?} enable3ds\n     * @property {boolean?} enforceStrongAuthentication\n     * @property {boolean?} enable3dsExemption\n     * @property {'low-value' | 'transaction-risk-analysis' | null} exemptionType\n     * @property {float?} exemptionLimit\n     * @property {string?} flowType\n     */\n\n    /**\n     * @typedef SlidingModalModel\n     *\n     * @property {string} paymentProductId\n     * @property {string} name\n     * @property {boolean} enabled\n     * @property {string} translations\n     * @property {string[]} integrationTypes\n     * @property {string} paymentGroup\n     * @property {string} template\n     * @property {string} logo\n     * @property {string} paymentAction\n     * @property {AdditionalData} additionalData\n     */\n\n    /**\n     * @typedef Language\n     *\n     * @property {string} code\n     * @property {string} logo\n     */\n\n    /**\n     * @param {SlidingModalModel} configuration\n     * @param {string} saveMethodConfigurationUrl\n     * @param {Language[]} languages\n     *\n     * @returns {*|HTMLElement}\n     * @constructor\n     */\n    const SlidingModal = (configuration, saveMethodConfigurationUrl, languages) => {\n        const {\n            elementGenerator: generator,\n            translationService,\n            utilities,\n            templateService,\n            validationService: validator\n        } = WOP;\n        const api = WOP.ajaxService;\n        /** @type {SlidingModalModel|null} */\n        let activeMethod = null;\n        /** @type {SlidingModalModel|null} */\n        let changedMethod = null;\n        /** @type {number} */\n        let numberOfChanges = 0;\n        let name = null;\n        let vaultTitle = null;\n        const separateCapture = [\n            'hosted_checkout', '302', '5001', '5133', '5129', '5100', 'cards', '320', '3301', '5908',\n            '5127', '840', '3203', '5131', '5407', '5404'\n        ];\n\n        /**\n         * Handles form input field change.\n         *\n         * @param {string} prop\n         * @param {any} value\n         * @param {boolean?} additional\n         */\n        const handleConfigMethodChange = (prop, value, additional) => {\n            if (prop !== 'logo') {\n                value = WOP.sanitize(value);\n            }\n\n            const areDifferent = (source, target) => {\n                if (Array.isArray(source) && Array.isArray(target)) {\n                    return !WOP.utilities.compareArrays(source, target);\n                }\n\n                return source !== target;\n            };\n\n            const areArraysEqual = (prop, additional) => {\n                let changed = additional ? changedMethod.additionalData[prop] : changedMethod[prop];\n                let active = additional ? activeMethod.additionalData[prop] : activeMethod[prop];\n\n                if (changed.length !== active.length) {\n                    numberOfChanges++;\n                    return;\n                }\n\n                const sorted1 = [...changed].sort((a, b) => a.locale.localeCompare(b.locale));\n                const sorted2 = [...active].sort((a, b) => a.locale.localeCompare(b.locale));\n\n                let result = sorted1.every((item, index) => {\n                    return item.locale === sorted2[index].locale && item.value === sorted2[index].value;\n                });\n\n                if (!result) {\n                    numberOfChanges++;\n                }\n            }\n\n            numberOfChanges = 0;\n            if (additional) {\n                if (!changedMethod.additionalData) {\n                    changedMethod.additionalData = {};\n                }\n\n                changedMethod.additionalData[prop] = value;\n            } else if (prop === 'logo') {\n                changedMethod.logoFile = value;\n                numberOfChanges = 1;\n            } else {\n                changedMethod[prop] = value;\n            }\n\n            Object.entries(changedMethod).forEach(([prop, value]) => {\n                if (prop === 'additionalData') {\n                    Object.entries(changedMethod.additionalData).forEach(([prop, value]) => {\n                        if (prop === 'vaultTitleCollection') {\n                            areArraysEqual(prop, true);\n                        } else if (prop !== 'logo') {\n                            areDifferent(activeMethod.additionalData[prop], value) && numberOfChanges++;\n                        }\n                    });\n                } else {\n                    if (prop === 'name') {\n                        areArraysEqual(prop, false);\n                    } else {\n                        areDifferent(activeMethod[prop], value) && numberOfChanges++;\n                    }\n                }\n            });\n\n            const btn = document.querySelector('.op-save-btn');\n            const hasValidationErrors = form.querySelector('.ops--error') !== null;\n\n            if (numberOfChanges > 0 && !hasValidationErrors) {\n                btn.classList.remove('ops--disabled');\n            } else {\n                btn.classList.add('ops--disabled');\n            }\n        };\n\n        /**\n         * The card authorization mode (final vs pre-authorization) only applies when the payment\n         * action is \"Authorize\" (authorize-only); for \"Authorize and capture\" it is never sent, so\n         * the field is hidden. 'FINAL_AUTHORIZATION' is the authorize-only payment action value.\n         *\n         * @param {string} paymentActionValue\n         */\n        const handleAuthorizationModeVisibility = (paymentActionValue) => {\n            const field = form.querySelector('[name=\"authorizationMode\"]');\n            if (!field) {\n                return;\n            }\n\n            const wrapper = utilities.getAncestor(field, 'op-field-wrapper');\n            if (paymentActionValue === 'FINAL_AUTHORIZATION') {\n                utilities.showElement(wrapper);\n            } else {\n                utilities.hideElement(wrapper);\n            }\n        };\n\n        const isValid = () => {\n            let result = [validateRequiredField(['enabled', 'name'])];\n\n            return !result.includes(false);\n        };\n\n        /**\n         * Validates the additional form fields.\n         *\n         * @param {(keyof AdditionalDataConfig | 'name' | 'enabled' | 'paymentAction')[]} fieldNames\n         * @returns {boolean[]}\n         */\n        const validateRequiredField = (fieldNames) => {\n            return fieldNames.map((fieldName) =>\n                validator.validateRequiredField(form.querySelector(`[name=${fieldName}]`))\n            );\n        };\n\n        const createHeader = () => {\n            const modalHeader = generator.createElement('div', 'op-header-name');\n            const logo = generator.createElement('img', 'op-payment-logo');\n            logo.src = configuration.logo;\n            const nameWrapper = generator.createElement('div', 'op-name-wrapper');\n            const name = generator.createElement('p', 'op-payment-method-name', configuration.name[0].value);\n            nameWrapper.appendChild(name);\n            configuration.integrationTypes.forEach((type) => {\n                const typeElement = generator.createElement(\n                    'span',\n                    'op-integration-type ' + 'op-' + type,\n                    'payments.integrationType.' + type\n                );\n                nameWrapper.appendChild(typeElement);\n            });\n            const closeButton = generator.createElement('div', 'op-close-button');\n            closeButton.addEventListener('click', () => {\n                let modal = document.querySelector('.op-sliding-modal');\n                let mask = document.querySelector('.op-dark-mask');\n\n                templateService.getMainPage().querySelector('.op-payments-page').classList.remove('op-settings-modal-opened');\n                mask.remove();\n                modal.remove();\n            });\n\n            modalHeader.appendChild(logo);\n            modalHeader.appendChild(nameWrapper);\n            modalHeader.appendChild(closeButton);\n\n            return modalHeader;\n        };\n\n        function getCardsFields() {\n            vaultTitle = WOP.components.TranslatableLabel.create({\n                onChange: () => {\n                    handleConfigMethodChange('vaultTitleCollection', vaultTitle.getValues(), true);\n                },\n                name: 'name',\n                languages: languages,\n                translations: activeMethod.additionalData.vaultTitleCollection\n            });\n\n            let vaultTitleWrapper = generator.createFieldWrapper(\n                vaultTitle.element,\n                translationService.translate('payments.configure.fields.vaultTitle.label')\n            );\n\n            let flowType = generator.createDropdownField({\n                name: 'flowType',\n                value: activeMethod.additionalData.flowType || 'iframe',\n                label: 'payments.configure.fields.flowType.label',\n                description: WOP.brand.code + '.payments.flowType.description',\n                options: [\n                    {\n                        label: 'payments.configure.fields.flowType.iframe',\n                        value: 'iframe'\n                    },\n                    {\n                        label: 'payments.configure.fields.flowType.redirect',\n                        value: 'redirect'\n                    }\n                ],\n                onChange: (value) => handleCardsSettingsChange('flowType', value)\n            });\n\n            return [\n                ...get3dsSettings(),\n                vaultTitleWrapper,\n                flowType,\n                ...generator.createFormFields([\n                    {\n                        name: 'enableGroupCards',\n                        value: configuration.additionalData.enableGroupCards,\n                        type: 'checkbox',\n                        className: '',\n                        label: `payments.configure.fields.enableGroupCards.label`,\n                        description: `payments.configure.fields.enableGroupCards.description`,\n                        onChange: (value) => handleConfigMethodChange('enableGroupCards', value === true, true)\n                    }\n                ])\n            ];\n        }\n\n        function get3dsSettings() {\n            return [\n                ...generator.createFormFields([\n                    {\n                        name: 'enable3ds',\n                        value: configuration.additionalData.enable3ds,\n                        type: 'checkbox',\n                        className: '',\n                        label: `generalSettings.cardsSettings.enable3ds.title`,\n                        description: `generalSettings.cardsSettings.enable3ds.description`,\n                        onChange: (value) => handleCardsSettingsChange('enable3ds', value)\n                    },\n                    {\n                        name: 'enforceStrongAuthentication',\n                        value: configuration.additionalData.enforceStrongAuthentication,\n                        type: 'checkbox',\n                        className: '',\n                        label: `generalSettings.cardsSettings.enforceStrongAuthentication.title`,\n                        onChange: (value) => handleCardsSettingsChange('enforceStrongAuthentication', value)\n                    },\n                    {\n                        name: 'enable3dsExemption',\n                        value: configuration.additionalData.enable3dsExemption,\n                        type: 'checkbox',\n                        className: '',\n                        label: `generalSettings.cardsSettings.3dsExemption.title`,\n                        description: `generalSettings.cardsSettings.3dsExemption.description`,\n                        onChange: (value) => handleCardsSettingsChange('enable3dsExemption', value)\n                    }\n                ]),\n                generator.createDropdownField({\n                    name: 'exemptionType',\n                    value: configuration.additionalData.exemptionType,\n                    label: 'generalSettings.cardsSettings.exemptionType.title',\n                    description: 'generalSettings.cardsSettings.exemptionType.description',\n                    options: [\n                        {\n                            label: 'generalSettings.cardsSettings.exemptionType.values.lowValue',\n                            value: 'low-value'\n                        },\n                        {\n                            label: 'generalSettings.cardsSettings.exemptionType.values.transactionRisk',\n                            value: 'transaction-risk-analysis'\n                        }\n                    ],\n                    onChange: (value) => handleCardsSettingsChange('exemptionType', value)\n                }),\n                generator.createNumberField({\n                    name: 'exemptionLimit',\n                    value: configuration.additionalData.exemptionLimit,\n                    label: 'generalSettings.cardsSettings.exemptionLimit.title',\n                    description: 'generalSettings.cardsSettings.exemptionLimit.description',\n                    onChange: (value) => handleCardsSettingsChange('exemptionLimit', value)\n                }),\n            ];\n        }\n\n        function handle3dsSpecificChanges(prop, value) {\n            if (prop === 'enable3ds') {\n                let enforceStrongAuthentication = utilities.getAncestor(form.querySelector(\n                        '[name=\"enforceStrongAuthentication\"]'), 'op-field-wrapper'),\n                    enableExemption = utilities.getAncestor(\n                        form.querySelector('[name=\"enable3dsExemption\"]'),\n                        'op-field-wrapper'\n                    ),\n                    exemptionType = utilities.getAncestor(\n                        form.querySelector('[name=\"exemptionType\"]'),\n                        'op-field-wrapper'\n                    ),\n                    exemptionLimit = utilities.getAncestor(\n                        form.querySelector('[name=\"exemptionLimit\"]'),\n                        'op-field-wrapper'\n                    );\n                if (value === true) {\n                    utilities.showElement(enforceStrongAuthentication);\n\n                    if (!changedMethod.additionalData.enforceStrongAuthentication) {\n                        utilities.showElement(enableExemption);\n\n                        if (changedMethod.additionalData.enable3dsExemption === true) {\n                            utilities.showElement(exemptionType);\n                            utilities.showElement(exemptionLimit);\n                        }\n                    }\n                } else {\n                    utilities.hideElement(enforceStrongAuthentication);\n                    utilities.hideElement(enableExemption);\n                    utilities.hideElement(exemptionType);\n                    utilities.hideElement(exemptionLimit);\n                }\n            }\n\n            if (prop === 'enforceStrongAuthentication') {\n                let enableExemption = utilities.getAncestor(\n                    form.querySelector('[name=\"enable3dsExemption\"]'),\n                    'op-field-wrapper'\n                );\n                let exemptionType = utilities.getAncestor(\n                    form.querySelector('[name=\"exemptionType\"]'),\n                    'op-field-wrapper'\n                );\n                let exemptionLimit = utilities.getAncestor(\n                    form.querySelector('[name=\"exemptionLimit\"]'),\n                    'op-field-wrapper'\n                );\n                if (value === true) {\n                    utilities.hideElement(enableExemption);\n                    utilities.hideElement(exemptionType);\n                    utilities.hideElement(exemptionLimit);\n                } else {\n                    if (changedMethod.additionalData.enable3ds === true) {\n                        utilities.showElement(enableExemption);\n                    }\n\n                    if (changedMethod.additionalData.enable3dsExemption === true) {\n                        utilities.showElement(exemptionType);\n                        utilities.showElement(exemptionLimit);\n                    }\n                }\n            }\n\n            if (prop === 'enable3dsExemption') {\n                let exemptionType = utilities.getAncestor(\n                        form.querySelector('[name=\"exemptionType\"]'),\n                        'op-field-wrapper'\n                    ),\n                    exemptionLimit = utilities.getAncestor(\n                        form.querySelector('[name=\"exemptionLimit\"]'),\n                        'op-field-wrapper'\n                    ),\n                    enableExemption = utilities.getAncestor(\n                        form.querySelector('[name=\"enable3dsExemption\"]'),\n                        'op-field-wrapper'\n                    );\n                if (value === true && changedMethod.additionalData.enforceStrongAuthentication === false\n                    && changedMethod.additionalData.enable3ds === true) {\n                    let warning = generator.createElement(\n                        'div',\n                        'ops-warning',\n                        '',\n                        null,\n                        [\n                            generator.createElement(\n                                'span',\n                                'ops-warning-message',\n                                translationService.translate('generalSettings.cardsSettings.3dsExemption.warning')\n                            )\n                        ]\n                    );\n                    enableExemption.append(warning);\n\n                    utilities.showElement(exemptionType);\n                    utilities.showElement(exemptionLimit);\n                } else {\n                    let warning = enableExemption.querySelector('.ops-warning');\n\n                    if (warning) {\n                        warning.remove();\n                    }\n\n                    utilities.hideElement(exemptionType);\n                    utilities.hideElement(exemptionLimit);\n                }\n            }\n\n            if (prop === 'exemptionType') {\n                let exemptionLimit = form.querySelector('[name=\"exemptionLimit\"]');\n                validator.removeError(exemptionLimit);\n\n                if (value === 'low-value') {\n                    if (exemptionLimit.value > 30) {\n                        exemptionLimit.value = activeMethod.additionalData.exemptionType === 'low-value' ?\n                            activeMethod.additionalData.exemptionLimit : 30;\n                        changedMethod.additionalData.exemptionLimit = activeMethod.additionalData.exemptionType === 'low-value' ?\n                            activeMethod.additionalData.exemptionLimit : 30;\n                    }\n                } else {\n                    exemptionLimit.value = activeMethod.additionalData.exemptionType === 'transaction-risk-analysis' ?\n                        activeMethod.additionalData.exemptionLimit : 100;\n                    changedMethod.additionalData.exemptionLimit = activeMethod.additionalData.exemptionType === 'transaction-risk-analysis' ?\n                        activeMethod.additionalData.exemptionLimit : 100;\n                }\n            }\n\n            if (prop === 'exemptionLimit') {\n                let exemptionLimit = form.querySelector('[name=\"exemptionLimit\"]');\n\n                if (changedMethod.additionalData.exemptionType === 'low-value') {\n                    if (value < 0 || value > 30) {\n                        validator.setError(exemptionLimit, 'generalSettings.cardsSettings.exemptionLimit.errorLowValue');\n                    } else {\n                        validator.removeError(exemptionLimit);\n                    }\n                }\n\n                if (changedMethod.additionalData.exemptionType === 'transaction-risk-analysis') {\n                    if (value < 0 || value > 100) {\n                        validator.setError(exemptionLimit, 'generalSettings.cardsSettings.exemptionLimit.errorTransactionRisk');\n                    } else {\n                        validator.removeError(exemptionLimit);\n                    }\n                }\n            }\n        }\n\n        function handleCardsSettingsChange(prop, value) {\n            handle3dsSpecificChanges(prop, value);\n\n            handleConfigMethodChange(prop, value, true);\n        }\n\n        function getInstantPaymentField() {\n            return generator.createFormFields([\n                {\n                    name: 'instantPayment',\n                    value: configuration.additionalData.instantPayment,\n                    type: 'checkbox',\n                    className: '',\n                    label: `payments.configure.fields.instantPayment.label`,\n                    description: `payments.configure.fields.instantPayment.description`,\n                    onChange: (value) => handleConfigMethodChange('instantPayment', value, true)\n                }\n            ]);\n        }\n\n        function getSepaFields() {\n            // Recurrence type is hardcoded to UNIQUE (one-off payments only), so it is not exposed\n            // as a merchant-configurable field - only the signature type is configurable.\n            return generator.createFormFields(\n                [\n                    {\n                        name: 'signatureType',\n                        value: configuration.additionalData.signatureType,\n                        type: 'dropdown',\n                        label: 'payments.configure.fields.directDebitSignature.label',\n                        options: [\n                            {label: 'payments.configure.fields.directDebitSignature.SMS', value: 'SMS'},\n                            {label: 'payments.configure.fields.directDebitSignature.UNSIGNED', value: 'UNSIGNED'}\n                        ],\n                        onChange: (value) => handleConfigMethodChange('signatureType', value, true)\n                    }\n                ]\n            );\n        }\n\n        function getIntersolveFields() {\n            return generator.createFormFields(\n                [\n                    {\n                        name: 'sessionTimeout',\n                        value: configuration.additionalData.sessionTimeout,\n                        type: 'number',\n                        label: 'payments.configure.fields.sessionTimeout.label',\n                        description: 'payments.configure.fields.sessionTimeout.description',\n                        onChange: (value) => handleConfigMethodChange('sessionTimeout', value, true)\n                    },\n                    {\n                        name: 'paymentProductId',\n                        value: configuration.additionalData.paymentProductId,\n                        type: 'number',\n                        label: 'payments.configure.fields.productId.label',\n                        description: 'payments.configure.fields.productId.description',\n                        onChange: (value) => handleConfigMethodChange('paymentProductId', value, true)\n                    }\n                ]\n            );\n        }\n\n        function getOneyFields() {\n            return generator.createFormFields(\n                [\n                    {\n                        name: 'paymentOption',\n                        value: configuration.additionalData.paymentOption,\n                        type: 'text',\n                        label: 'payments.configure.fields.paymentOption.label',\n                        onChange: (value) => handleConfigMethodChange('paymentOption', value, true)\n                    }\n                ]\n            );\n        }\n\n        function getDescriptorFields() {\n            return generator.createFormFields(\n                [\n                    {\n                        name: 'descriptor',\n                        value: configuration.additionalData.descriptor,\n                        type: 'text',\n                        maxLength: 15,\n                        label: 'payments.configure.fields.descriptor.label',\n                        description: 'payments.configure.fields.descriptor.description',\n                        onChange: (value) => handleConfigMethodChange('descriptor', value, true)\n                    }\n                ]\n            );\n        }\n\n        function getHostedCheckoutFields() {\n            return [\n                ...generator.createFormFields(\n                    [\n                        {\n                            name: 'logo',\n                            value: configuration.additionalData.logo,\n                            type: 'file',\n                            supportedMimeTypes: ['image/jpeg', 'image/jpg', 'image/png'],\n                            label: 'payments.configure.fields.logo.label',\n                            description: WOP.brand.code + '.payments.hostedCheckout.logo.description',\n                            onChange: (value) => handleConfigMethodChange('logo', value, false)\n                        },\n                        {\n                            name: 'enableGroupCards',\n                            value: configuration.additionalData.enableGroupCards,\n                            type: 'checkbox',\n                            className: '',\n                            label: `payments.configure.fields.enableGroupCards.label`,\n                            description: `payments.configure.fields.enableGroupCards.description`,\n                            onChange: (value) => handleConfigMethodChange('enableGroupCards', value === true, true)\n                        }\n                    ]\n                ),\n                ...get3dsSettings()\n            ];\n        }\n\n        function getGooglePayFields() {\n            return get3dsSettings();\n        }\n\n        function handleSave(event) {\n            preventDefaults(event);\n            utilities.showLoader();\n\n            const data = {\n                ...changedMethod,\n                additionalData: utilities.cloneObject(changedMethod.additionalData)\n            };\n\n            if (!isValid()) {\n                utilities.hideLoader();\n                return;\n            }\n\n            const postData = new FormData();\n            Object.entries(data).forEach(([key, value]) => {\n                if (key !== 'logoFile' && key !== 'additionalData' && key !== 'name') {\n                    postData.append(key, value);\n                }\n            });\n\n            postData.append('name', JSON.stringify(data.name));\n            postData.append('additionalData', JSON.stringify(data.additionalData || null));\n\n            if (data.logoFile) {\n                postData.set('logo', data.logoFile, data.logoFile.name);\n            }\n\n            const url = saveMethodConfigurationUrl.replace('{methodId}', activeMethod.paymentProductId);\n            api.post(url, postData, {\n                'Content-Type': 'multipart/form-data'\n            }).then(() => {\n                utilities.createToasterMessage('payments.configure.methodSaved');\n                utilities.hideLoader();\n                WOP.state.display();\n            }).catch((error) => {\n                utilities.createToasterMessage(error, 'error');\n                utilities.hideLoader();\n            });\n        }\n\n        const createDefaultForm = () => {\n            const form = generator.createElement('form', 'op-form');\n\n            const enabled = generator.createFormFields([\n                {\n                    name: 'enabled',\n                    value: configuration.enabled,\n                    type: 'checkbox',\n                    className: '',\n                    label: `payments.configure.fields.enableOnCheckout.label`,\n                    description: `payments.configure.fields.enableOnCheckout.description`,\n                    onChange: (value) => handleConfigMethodChange('enabled', value, false)\n                }\n            ]);\n            form.appendChild(enabled[0]);\n\n            name = WOP.components.TranslatableLabel.create({\n                onChange: () => {\n                    handleConfigMethodChange('name', name.getValues(), false);\n                },\n                name: 'name',\n                languages: languages,\n                translations: activeMethod.name\n            });\n            let nameWrapper = generator.createFieldWrapper(\n                name.element,\n                translationService.translate('payments.configure.fields.name.label'),\n                translationService.translate('payments.configure.fields.name.description')\n            );\n            form.appendChild(nameWrapper);\n\n            const template = generator.createFormFields(\n                [\n                    {\n                        name: 'template',\n                        value: configuration.template,\n                        type: 'text',\n                        label: 'payments.configure.fields.templateName.label',\n                        description: 'payments.configure.fields.templateName.description',\n                        onChange: (value) => handleConfigMethodChange('template', value, false)\n                    }\n                ]\n            );\n\n            form.appendChild(template[0]);\n\n            // Per-method checkout button title: changes the pay-button label when this method is selected.\n            const buttonTitle = generator.createFormFields([\n                {\n                    name: 'buttonTitle',\n                    value: configuration.additionalData.buttonTitle,\n                    type: 'text',\n                    label: 'payments.configure.fields.buttonTitle.label',\n                    description: 'payments.configure.fields.buttonTitle.description',\n                    onChange: (value) => handleConfigMethodChange('buttonTitle', value, true)\n                }\n            ]);\n            form.append(...buttonTitle);\n\n            if (separateCapture.includes(activeMethod.paymentProductId)) {\n                let paymentAction = generator.createDropdownField({\n                    name: 'paymentAction',\n                    value: activeMethod.paymentAction || 'authorize-capture',\n                    label: 'generalSettings.paymentSettings.paymentAction.title',\n                    description: 'generalSettings.paymentSettings.paymentAction.description',\n                    options: [\n                        {\n                            label: 'generalSettings.paymentSettings.paymentAction.values.authorize',\n                            value: 'FINAL_AUTHORIZATION'\n                        },\n                        {\n                            label: 'generalSettings.paymentSettings.paymentAction.values.authorizeCapture',\n                            value: 'SALE'\n                        }\n                    ],\n                    onChange: (value) => {\n                        handleConfigMethodChange('paymentAction', value);\n                        handleAuthorizationModeVisibility(value);\n                    }\n                });\n\n                form.appendChild(paymentAction);\n\n                if (configuration.paymentProductId === 'cards') {\n                    let authorizationMode = generator.createDropdownField({\n                        name: 'authorizationMode',\n                        value: activeMethod.additionalData.authorizationMode || 'FINAL_AUTHORIZATION',\n                        label: 'payments.configure.fields.authorizationMode.label',\n                        description: 'payments.configure.fields.authorizationMode.description',\n                        options: [\n                            {\n                                label: 'payments.configure.fields.authorizationMode.final',\n                                value: 'FINAL_AUTHORIZATION'\n                            },\n                            {\n                                label: 'payments.configure.fields.authorizationMode.preAuthorization',\n                                value: 'PRE_AUTHORIZATION'\n                            }\n                        ],\n                        onChange: (value) => handleConfigMethodChange('authorizationMode', value, true)\n                    });\n\n                    form.appendChild(authorizationMode);\n                }\n            }\n\n            if (configuration.paymentProductId === 'cards') {\n                let cardFields = getCardsFields();\n                form.append(...cardFields);\n            }\n\n            if (configuration.paymentProductId === '5408') {\n                let instantPayment = getInstantPaymentField();\n                form.appendChild(instantPayment[0]);\n            }\n\n            if (configuration.paymentProductId === '771') {\n                let sepaFields = getSepaFields();\n                form.append(...sepaFields);\n            }\n\n            if (configuration.paymentProductId === '5700') {\n                let intersolveFields = getIntersolveFields();\n                form.append(...intersolveFields);\n            }\n\n            if (['5111', '5112', '5127', '5125'].includes(configuration.paymentProductId)) {\n                let oneyFields = getOneyFields();\n                form.append(...oneyFields);\n            }\n\n            // Sofinco / Linxo: optional soft descriptor sent on the payment (order.references.descriptor).\n            if (['5131', '5003'].includes(configuration.paymentProductId)) {\n                let descriptorFields = getDescriptorFields();\n                form.append(...descriptorFields);\n            }\n\n            if (configuration.paymentProductId === 'hosted_checkout') {\n                let hostedCheckoutFields = getHostedCheckoutFields();\n                form.append(...hostedCheckoutFields);\n            }\n\n            if (configuration.paymentProductId === '320') {\n                let googlePay = getGooglePayFields();\n                form.append(...googlePay);\n            }\n\n            const buttons = generator.createElement('div', 'op-button-bar');\n            const saveButton = generator.createElement(\n                'button',\n                'op-save-btn op-button opt--primary ops--disabled',\n                translationService.translate('general.saveChanges')\n            );\n            const cancelButton = generator.createElement(\n                'button',\n                'op-button opt--secondary',\n                translationService.translate('general.cancel')\n            );\n            cancelButton.addEventListener('click', function (event) {\n                preventDefaults(event);\n                let mask = document.querySelector('.op-dark-mask');\n                templateService.getMainPage().querySelector('.op-payments-page').classList.remove('op-settings-modal-opened');\n                mask.remove();\n                document.querySelector('.op-sliding-modal').remove();\n            });\n\n            saveButton.addEventListener('click', function (event) {\n                handleSave(event);\n            });\n\n            buttons.appendChild(saveButton);\n            buttons.appendChild(cancelButton);\n            form.appendChild(buttons);\n\n            return form;\n        };\n\n        activeMethod = utilities.cloneObject(configuration);\n        changedMethod = utilities.cloneObject(configuration);\n        const modal = generator.createElement('div', 'op-sliding-modal');\n\n        const paymentGroup = generator.createElement('div', 'op-payment-group',\n            'payments.paymentGroups.' + configuration.paymentGroup);\n        const form = createDefaultForm();\n\n        if (activeMethod.paymentProductId === 'cards' || activeMethod.paymentProductId === 'hosted_checkout'\n            || activeMethod.paymentProductId === '320') {\n            handle3dsSpecificChanges('enable3ds', activeMethod.additionalData.enable3ds);\n            handle3dsSpecificChanges('enforceStrongAuthentication', activeMethod.additionalData.enforceStrongAuthentication);\n            handle3dsSpecificChanges('enable3dsExemption', activeMethod.additionalData.enable3dsExemption);\n\n            const paymentActionField = form.querySelector('[name=\"paymentAction\"]');\n            if (paymentActionField) {\n                handleAuthorizationModeVisibility(paymentActionField.value);\n            }\n        }\n\n        modal.appendChild(createHeader());\n        modal.appendChild(paymentGroup);\n        modal.appendChild(form);\n\n        return modal;\n    };\n\n    WOP.components.SlidingModal = {\n        /**\n         * @param {SlidingModalModel} config\n         * @param {string} saveMethodConfigurationUrl\n         * @param {Language[]} languages\n         * @returns {HTMLElement}\n         */\n        create: (config, saveMethodConfigurationUrl, languages) => SlidingModal(config, saveMethodConfigurationUrl, languages)\n    };\n})();\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/sliding-modal/SlidingModal.js?");

/***/ }),

/***/ "./src/components/table-filter/TableFilterComponent.js":
/*!*************************************************************!*\
  !*** ./src/components/table-filter/TableFilterComponent.js ***!
  \*************************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    /**\n     * @typedef TableFilterParams\n     *\n     * @property {Option[]} options\n     * @property {string?} name\n     * @property {string[]?} values\n     * @property {(values: string[]) => void} onChange\n     * @property {string?} label\n     * @property {string?} selectPlaceholder\n     * @property {boolean?} isMultiselect\n     */\n    const { elementGenerator: generator, components } = WOP;\n\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * Compares contents of two arrays.\n     *\n     * @param {string[]} a1\n     * @param {string[]} a2\n     * @return {boolean}\n     */\n    const arraysHaveSameContent = (a1, a2) => {\n        if (a1.length !== a2.length) {\n            return false;\n        }\n\n        for (let i = 0; i < a1.length; i++) {\n            if (!a2.includes(a1[i])) {\n                return false;\n            }\n        }\n\n        for (let i = 0; i < a2.length; i++) {\n            if (!a1.includes(a2[i])) {\n                return false;\n            }\n        }\n\n        return true;\n    };\n\n    /**\n     * Gets the label to be displayed in the main button.\n     *\n     * @param {string} label The default label when nothing is selected.\n     * @param {string} labelPlural Label when more than two options are selected.\n     * @param {Option[]} options Possible options.\n     * @param {string[]} values Selected values.\n     * @return {string}\n     */\n    const getButtonLabel = (label, labelPlural, options, values) => {\n        if (values.length === 0) {\n            return label;\n        }\n\n        if (values.length < 2) {\n            return values.map((value) => options.find((o) => o.value === value).label).join(', ');\n        }\n\n        return `${values.length} ${labelPlural.toLowerCase()}`;\n    };\n\n    /**\n     * Gets the label to be displayed in the main button.\n     *\n     * @param {string} label The default label when nothing is selected.\n     * @param {Option[]} options Possible options.\n     * @param {string[]} values Selected values.\n     * @return {string}\n     */\n    const getButtonTooltip = (label, options, values) => {\n        if (values.length === 0) {\n            return '';\n        }\n\n        if (values.length < 2) {\n            return label;\n        }\n\n        return values.map((value) => options.find((o) => o.value === value).label).join(', ');\n    };\n\n    /**\n     * Renders the main button.\n     *\n     * @param {string} label\n     * @param {string} labelPlural\n     * @param {Option[]} options\n     * @param {string[]} values\n     * @param {() => void} onClick\n     * @param {() => void} onClear\n     * @return {HTMLButtonElement}\n     */\n    const renderButton = (label, labelPlural, options, values, onClick, onClear) => {\n        const button = generator.createButton({\n            type: 'secondary',\n            className: 'opp-filter-button' + (values.length > 0 ? ' ops--selected' : ''),\n            label: getButtonLabel(label, labelPlural, options, values),\n            onClick: onClick\n        });\n\n        const deleteButton = generator.createElement('button', 'opp-delete-text-button');\n        deleteButton.addEventListener('click', (e) => {\n            preventDefaults(e);\n            onClear();\n        });\n\n        button.append(\n            deleteButton,\n            generator.createElement('span', 'opp-tooltip', getButtonTooltip(label, options, values))\n        );\n\n        return button;\n    };\n\n    /**\n     * Renders selected options.\n     *\n     * @param {Option[]} options\n     * @param {string[]} selectedValues\n     * @param {(value: string) =>, void} onRemove\n     * @return {HTMLElement[]}\n     */\n    const getOptionsList = (options, selectedValues, onRemove) => {\n        return selectedValues.map((value) => {\n            const deleteButton = generator.createElementFromHTML('<button class=\"opt--remove-item\"></button>');\n            deleteButton.addEventListener('click', (e) => {\n                preventDefaults(e);\n                onRemove(value);\n            });\n\n            const element = generator.createElement(\n                'li',\n                'opp-selected-data-item',\n                options.find((o) => o.value === value).label,\n                null\n            );\n\n            element.prepend(deleteButton);\n\n            return element;\n        });\n    };\n\n    /**\n     * Creates a table filter element.\n     *\n     * @param {TableFilterParams} args\n     * @return {HTMLElement}\n     */\n    const create = ({\n        options,\n        name = '',\n        values = [],\n        onChange,\n        label = '',\n        labelPlural = '',\n        selectPlaceholder = '',\n        isMultiselect = true\n    }) => {\n        let selectedValues = [...values];\n\n        const createDropdown = () =>\n            components.Dropdown.create({\n                options,\n                name,\n                placeholder: selectPlaceholder,\n                onChange: handleSelectChange,\n                value: isMultiselect ? undefined : selectedValues[0],\n                updateTextOnChange: !isMultiselect,\n                searchable: true\n            });\n\n        const createFilterContainerContent = () => {\n            dataContainer.append(\n                ...[\n                    generator.createElement('span', 'opp-data-label', label),\n                    createDropdown(),\n                    generator.createElement(\n                        'ul',\n                        'opp-selected-data',\n                        '',\n                        null,\n                        isMultiselect\n                            ? getOptionsList(options, selectedValues, (value) => handleSelectChange(value, false))\n                            : []\n                    )\n                ]\n            );\n\n            clearButton.disabled = selectedValues.length === 0;\n            applyButton.disabled = arraysHaveSameContent(selectedValues, values);\n        };\n\n        const fireOnChange = (values) => {\n            selectedValues = values;\n            handleSelectedValuesChange();\n            filterContainer.classList.remove('ops--open');\n            values.length ? button.classList.add('ops--selected') : button.classList.remove('ops--selected');\n            button.firstElementChild.innerHTML = WOP.sanitize(getButtonLabel(label, labelPlural, options, selectedValues));\n            button.lastElementChild.innerHTML = WOP.sanitize(getButtonTooltip(label, options, selectedValues));\n            dataContainer.innerHTML = '';\n            onChange?.(selectedValues);\n        };\n\n        const handleSelectedValuesChange = () => {\n            const list = filterContainer.querySelector('.opp-selected-data');\n            if (list && isMultiselect) {\n                list.innerHTML = '';\n                list.append(...getOptionsList(options, selectedValues, (value) => handleSelectChange(value, false)));\n            } else if (!isMultiselect && selectedValues.length === 0) {\n                // reset value for the dropdown\n                const previousDD = filterContainer.querySelector('.op-single-select-dropdown');\n                dataContainer.insertBefore(createDropdown(), previousDD);\n\n                previousDD?.remove();\n            }\n\n            clearButton.disabled = selectedValues.length === 0;\n            applyButton.disabled = arraysHaveSameContent(selectedValues, values);\n        };\n\n        const handleSelectChange = (value, add = true) => {\n            if (add) {\n                isMultiselect && !selectedValues.includes(value) && selectedValues.push(value);\n                !isMultiselect && (selectedValues = [value]);\n            } else if (isMultiselect) {\n                selectedValues = selectedValues.filter((v) => v !== value);\n            } else {\n                selectedValues = [];\n            }\n\n            handleSelectedValuesChange();\n        };\n\n        const closeFilter = () => {\n            selectedValues = [...values];\n            filterContainer.classList.remove('ops--open');\n            dataContainer.innerHTML = '';\n        };\n\n        const button = renderButton(\n            label,\n            labelPlural,\n            options,\n            values,\n            () => {\n                if (filterContainer.classList.contains('ops--open')) {\n                    dataContainer.innerHTML = '';\n                } else {\n                    let openedFilters = document.querySelectorAll('.opp-dropdown-container.ops--open');\n\n                    openedFilters.forEach((filter) => {\n                        filter.classList.remove('ops--open');\n                        filter.querySelector('.opp-dropdown-data').innerHTML = '';\n                    });\n\n                    createFilterContainerContent();\n                }\n\n                filterContainer.classList.toggle('ops--open');\n            },\n            () => {\n                fireOnChange([]);\n            }\n        );\n\n        const clearButton = generator.createButton({\n            type: 'secondary',\n            size: 'small',\n            label: 'general.clear',\n            className: 'opm--blue',\n            disabled: values.length === 0,\n            onClick: () => {\n                selectedValues = [];\n                handleSelectedValuesChange();\n            }\n        });\n        const applyButton = generator.createButton({\n            type: 'primary',\n            size: 'small',\n            label: 'general.apply',\n            className: 'opm--blue',\n            disabled: true,\n            onClick: () => fireOnChange(selectedValues)\n        });\n\n        const dataContainer = generator.createElement('div', 'opp-dropdown-data');\n        const filterContainer = generator.createElement('div', 'opp-dropdown-container', '', null, [\n            generator.createElement('div', 'opp-content', '', null, [\n                generator.createElement('div', 'opp-filter-header', '', null, [\n                    generator.createElement('span', '', 'payments.filter.filter'),\n                    generator.createElement('button', 'opp-close-button', '', { onClick: closeFilter })\n                ]),\n                dataContainer,\n                generator.createElement('span', 'opp-buttons', '', null, [clearButton, applyButton])\n            ])\n        ]);\n\n        const element = generator.createElement('div', 'op-multiselect-filter', '', null, [button, filterContainer]);\n\n        window.addEventListener('click', (event) => {\n            if (!element.contains(event.target) && event.target !== element) {\n                closeFilter();\n            }\n        });\n\n        return element;\n    };\n\n    WOP.components.TableFilter = {\n        create\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/table-filter/TableFilterComponent.js?");

/***/ }),

/***/ "./src/components/translatable-label/TranslatableLabel.js":
/*!****************************************************************!*\
  !*** ./src/components/translatable-label/TranslatableLabel.js ***!
  \****************************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\nif (!window.WOP.components) {\n    window.WOP.components = {};\n}\n\n(function () {\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * @typedef Translation\n     *\n     * @property {string} language\n     * @property {string} translation\n     */\n\n    /**\n     * @typedef Language\n     *\n     * @property {string} code\n     * @property {string} logo\n     */\n\n    /**\n     * @typedef TranslatableLabelModel\n     *\n     * @property {Language[]} languages\n     * @property {Translation[]} translations\n     * @property {string} name\n     * @property onChange\n     */\n\n    const TranslatableLabel = (configuration) => {\n        const { elementGenerator: generator } = WOP;\n        let values = [];\n\n        /**\n         * @param {string} lang\n         */\n        const findIndex = (lang) => {\n            return values.findIndex(value => value.locale === lang);\n        }\n\n        values = WOP.utilities.cloneObject(configuration.translations);\n        let currentLang = configuration.translations[0] !== undefined ?\n            configuration.translations[0].locale : 'en';\n\n        if (configuration.languages[currentLang] === undefined) {\n            currentLang = Object.values(configuration.languages)[0].code;\n        }\n\n        const wrapper = generator.createElement('div', 'op-translatable-label');\n        const input = generator.createElement('input', 'op-lang-label-input');\n        input.type = 'text';\n        input.name = configuration.name;\n        const currentIndex = findIndex(currentLang);\n        input.value = currentIndex !== -1 ? values[currentIndex].value :\n            (values[0] !== undefined ? values[0].value : '');\n        input.addEventListener('change', (e) => {\n            e.preventDefault();\n            let index = findIndex(currentLang);\n            if (values[index] === undefined) {\n                values.push({'locale': currentLang, 'value': input.value});\n            } else {\n                values[index]['value'] = input.value;\n            }\n\n            configuration.onChange();\n        });\n\n        const dropdown = generator.createElement('div', 'op-lang-dropdown');\n        const flagImg = generator.createElement('img');\n        const language = generator.createElement('span', 'op-lang-code', configuration.languages[currentLang].code);\n        const languageBtn = generator.createElement('div', 'op-lang-btn')\n        flagImg.src =  configuration.languages[currentLang].logo;\n        flagImg.title = configuration.languages[currentLang].code;\n        languageBtn.appendChild(flagImg);\n        languageBtn.appendChild(language);\n\n        dropdown.appendChild(languageBtn);\n\n        const options = generator.createElement('div', 'op-lang-options');\n\n        for (const key in configuration.languages) {\n            const opt = generator.createElement('div', 'op-lang-btn');\n            const flag = generator.createElement('img');\n            const flagLanguage = generator.createElement('span', 'op-lang-code', configuration.languages[key].code);\n            flag.title = configuration.languages[key].code;\n            flag.src = configuration.languages[key].logo;\n            flag.style.marginRight = '6px';\n            opt.appendChild(flag);\n            opt.appendChild(flagLanguage);\n            opt.onclick = (e) => {\n                preventDefaults(e);\n                let index = findIndex(currentLang);\n\n                if (values[index] === undefined) {\n                    values.push({'locale': currentLang, 'value': input.value});\n                } else {\n                    values[index]['value'] = input.value;\n                }\n\n                currentLang = configuration.languages[key].code;\n                index = findIndex(currentLang);\n                input.value = values[index] !== undefined ? values[index].value :\n                    (values[0] !== undefined ? values[0].value : '');\n                flagImg.src = configuration.languages[key].logo;\n                flagImg.title = configuration.languages[key].code;\n                language.innerHTML = configuration.languages[key].code;\n                options.style.display = 'none';\n            }\n            options.appendChild(opt);\n        }\n\n        dropdown.appendChild(options);\n        dropdown.onclick = (e) => {\n            preventDefaults(e);\n            options.style.display = options.style.display === 'block' ? 'none' : 'block';\n        }\n\n        wrapper.appendChild(input);\n        wrapper.appendChild(dropdown);\n\n        return {\n            element: wrapper,\n            getValues: () => values\n        };\n    }\n\n    WOP.components.TranslatableLabel = {\n        /**\n         * @param {TranslatableLabelModel} config\n         * @returns {HTMLElement}\n         */\n        create: (config) => TranslatableLabel(config),\n        getConfiguredValues: () => {\n            return values;\n        }\n    };\n})();\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/components/translatable-label/TranslatableLabel.js?");

/***/ }),

/***/ "./src/controllers/ConnectionController.js":
/*!*************************************************!*\
  !*** ./src/controllers/ConnectionController.js ***!
  \*************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * Webhook delivery modes reported by the core. See the settings controller for the full description.\n     */\n    const WEBHOOK_MODE_MANUAL = 'manual';\n    const WEBHOOK_MODE_AUTOMATIC = 'automatic';\n\n    /**\n     * @typedef ConnectionInfo\n     * @property {string} pspid\n     * @property {string} apiKey\n     * @property {string} apiSecret\n     * @property {string} webhooksKey\n     * @property {string} webhooksSecret\n     */\n\n    /**\n     * @typedef Connection\n     * @property {'test' | 'live'} mode\n     * @property {ConnectionInfo?} sandboxData\n     * @property {ConnectionInfo?} liveData\n     * @property {('manual' | 'automatic')?} webhookMode\n     */\n\n    /**\n     * @typedef ConnectionSettings\n     * @property {'test' | 'live'} mode\n     * @property {string} pspid\n     * @property {string} apiKey\n     * @property {string} apiSecret\n     * @property {string} webhooksKey\n     * @property {string} webhooksSecret\n     */\n    /**\n     * Handles connection page logic.\n     *\n     * @param {{getSettingsUrl: string, submitUrl: string, webhooksUrl: string}} configuration\n     * @constructor\n     */\n    function ConnectionController(configuration) {\n        /** @type AjaxServiceType */\n        const api = WOP.ajaxService;\n\n        const {\n            templateService,\n            elementGenerator: generator,\n            validationService: validator,\n            translationService: translationService,\n            components,\n            state,\n            utilities\n        } = WOP;\n        /** @type {HTMLElement} */\n        let form;\n        let currentStoreId;\n        /** @type {ConnectionSettings} */\n        let activeSettings;\n        /** @type {ConnectionSettings} */\n        let changedSettings;\n\n        /**\n         * Webhook delivery mode of the integration, as reported by the core. Defaults to manual, which is\n         * also how a core that does not report the mode behaves.\n         *\n         * @type {string}\n         */\n        let webhookMode = WEBHOOK_MODE_MANUAL;\n\n        /**\n         * @return {boolean}\n         */\n        const isAutomaticWebhooks = () => webhookMode === WEBHOOK_MODE_AUTOMATIC;\n\n        /**\n         * Builds the read-only webhook URL field with a copy button, for registering the URL in the\n         * Worldline back office.\n         *\n         * @return {HTMLElement}\n         */\n        const createWebhooksUrlField = () => {\n            const webhookUrlDiv = generator.createElement(\n                'div',\n                'op-webhooks-url-wrapper'\n            );\n            const webhooksUrl = generator.createElement(\n                'span',\n                'op-webhooks-url',\n                state.formatUrl(configuration.webhooksUrl)\n            );\n            const webhookCopy = generator.createElement(\n                'span',\n                'op-webhooks-url-copy'\n            );\n            webhookCopy.addEventListener('click', function () {\n                navigator.clipboard.writeText(state.formatUrl(configuration.webhooksUrl));\n                utilities.createToasterMessage('general.copied');\n            });\n            webhookUrlDiv.appendChild(webhooksUrl);\n            webhookUrlDiv.appendChild(webhookCopy);\n\n            return generator.createFieldWrapper(\n                webhookUrlDiv,\n                'connection.webhooksUrl.title',\n                'connection.webhooksUrl.description'\n            );\n        };\n\n        /**\n         * Displays page content.\n         *\n         * @param {{ state?: string, storeId: string }} config\n         */\n        this.display = ({ storeId }) => {\n            utilities.showLoader();\n            currentStoreId = storeId;\n            templateService.clearMainPage();\n\n            configuration.getSettingsUrl = configuration.getSettingsUrl.replace('{storeId}', storeId);\n            configuration.submitUrl = configuration.submitUrl.replace('{storeId}', storeId);\n\n            state\n                .getCurrentMerchantState()\n                .then((state) => {\n                    return api.get(configuration.getSettingsUrl, () => null).then(createForm);\n                })\n                .finally(() => {\n                    let header = templateService.getHeaderSection();\n                    let title = header.querySelector('.op-main-title');\n                    title.innerText = WOP.sanitize(translationService.translate(WOP.brand.code + '.connection'));\n                    utilities.hideLoader();\n                    WOP.state.initializeFooter();\n                });\n        };\n\n        /**\n         * Sets the unsaved changes.\n         *\n         * @return {boolean}\n         */\n        this.hasUnsavedChanges = () => false;\n\n        /**\n         * Renders the form.\n         *\n         * @param {ConnectionSettings} data\n         */\n        const renderForm = (data) => {\n            const content = generator.createElement('div', 'op-connection-page');\n            form = generator.createElement('form');\n            const title = generator.createElement('p', 'op-connection-title', WOP.brand.code + '.connectionTitle', null, null, true);\n            title.querySelector('a').target = '_blank';\n\n            const headerSection = generator.createElement('div', 'op-header-section', '', { id: 'op-header-section' });\n\n            const components = [\n                title,\n                generator.createDropdownField({\n                    name: 'mode',\n                    value: data.mode || 'test',\n                    label: 'connection.mode.title',\n                    description: 'connection.mode.description',\n                    options: [\n                        { label: 'connection.mode.options.sandbox', value: 'test' },\n                        { label: 'connection.mode.options.live', value: 'live' }\n                    ],\n                    onChange: (value) => handleChange('mode', value)\n                }),\n                generator.createTextField({\n                    name: 'pspid',\n                    value: data.pspid,\n                    label: 'connection.pspid.title',\n                    description: 'connection.pspid.description',\n                    error: 'connection.pspid.error',\n                    onChange: (value) => handleChange('pspid', value)\n                }),\n                generator.createTextField({\n                    name: 'apiKey',\n                    value: data.apiKey,\n                    label: 'connection.apiKey.title',\n                    description: 'connection.apiKey.description',\n                    error: 'connection.apiKey.error',\n                    onChange: (value) => handleChange('apiKey', value)\n                }),\n                generator.createPasswordField({\n                    name: 'apiSecret',\n                    value: data.apiSecret,\n                    label: 'connection.apiSecret.title',\n                    placeholder: translationService.translate(\n                        'connection.apiSecret.placeholder',\n                        [data.mode || 'sandbox']\n                    ),\n                    description: 'connection.apiSecret.description',\n                    error: 'connection.apiSecret.error',\n                    onChange: (value) => handleChange('apiSecret', value)\n                }),\n                generator.createTextField({\n                    name: 'webhooksKey',\n                    value: data.webhooksKey,\n                    label: 'connection.webhooksKey.title',\n                    placeholder: translationService.translate('connection.webhooksKey.placeholder'),\n                    description: 'connection.webhooksKey.description',\n                    error: 'connection.webhooksKey.error',\n                    onChange: (value) => handleChange('webhooksKey', value)\n                }),\n                generator.createPasswordField({\n                    name: 'webhooksSecret',\n                    value: data.webhooksSecret,\n                    label: 'connection.webhooksSecret.title',\n                    placeholder: translationService.translate('connection.webhooksSecret.placeholder'),\n                    description: 'connection.webhooksSecret.description',\n                    error: 'connection.webhooksSecret.error',\n                    onChange: (value) => handleChange('webhooksSecret', value)\n                })\n            ];\n\n            // With manual webhooks the merchant has to register this URL in the Worldline back office,\n            // so it is shown together with a copy button. With automatic webhooks the core sends the URL\n            // with every payment request and the merchant never needs to see it.\n            if (!isAutomaticWebhooks()) {\n                components.push(createWebhooksUrlField());\n            }\n\n            form.append(...components);\n\n            const connectButton = generator.createButton({\n                type: 'primary',\n                name: 'saveButton',\n                disabled: !data.apiKey,\n                label: 'connection.connect',\n                onClick: handleFormSubmit\n            })\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n\n            buttonWrapper.append(connectButton);\n            form.append(buttonWrapper);\n\n            content.append(headerSection);\n            content.append(form);\n            templateService.clearMainPage();\n            templateService.getMainPage().append(content);\n        };\n\n        /**\n         * Creates the form.\n         *\n         * @param {Connection?} settings\n         */\n        const createForm = (settings) => {\n            webhookMode = settings?.webhookMode || WEBHOOK_MODE_MANUAL;\n\n            const mode = settings?.mode || 'test';\n            /** @type ConnectionSettings */\n            const data = { mode: mode, pspid: '', apiKey: '', apiSecret: '', webhooksKey: '', webhooksSecret: '' };\n            if (settings?.[`${mode}Data`]) {\n                data.pspid = settings[`${mode}Data`].pspid;\n                data.apiKey = settings[`${mode}Data`].apiKey;\n                data.apiSecret = settings[`${mode}Data`].apiSecret;\n                data.webhooksKey = settings[`${mode}Data`].webhooksKey;\n                data.webhooksSecret = settings[`${mode}Data`].webhooksSecret;\n            }\n\n            changedSettings = utilities.cloneObject(data);\n            activeSettings = utilities.cloneObject(data);\n\n            renderForm(data);\n\n            return Promise.resolve();\n        };\n\n        /**\n         *\n         * @param {keyof ConnectionSettings} prop\n         * @param {any} value\n         */\n        const handleChange = (prop, value) => {\n            changedSettings[prop] = value;\n            if (prop === 'mode') {\n                changedSettings.apiKey = '';\n                changedSettings.apiSecret = '';\n                changedSettings.pspid = '';\n                changedSettings.webhooksKey = '';\n                changedSettings.webhooksSecret = '';\n                form['apiKey'].value = '';\n                form['pspid'].value = '';\n                form['apiSecret'].value = '';\n                form['webhooksKey'].value = '';\n                form['webhooksSecret'].value = '';\n            } else {\n                validator.validateRequiredField(form[prop], 'connection.' + prop + '.error');\n            }\n\n            form['saveButton'].disabled = !form['pspid'].value || !form['apiKey'].value\n                || !form['apiSecret'].value || !form['webhooksKey'].value || !form['webhooksSecret'].value;\n        };\n\n        /**\n         * Converts form data to the settings object.\n         *\n         * @return {Connection}\n         */\n        const getFormData = () => ({\n            mode: changedSettings.mode,\n            [changedSettings.mode + 'Data']: {\n                pspid: changedSettings.pspid,\n                apiKey: changedSettings.apiKey,\n                apiSecret: changedSettings.apiSecret,\n                webhooksKey: changedSettings.webhooksKey,\n                webhooksSecret: changedSettings.webhooksSecret\n            }\n        });\n\n        /**\n         * Saves the connection configuration.\n         *\n         * @returns {boolean}\n         */\n        const handleFormSubmit = () => {\n            const isValid =\n                validator.validateRequiredField(form['mode']) &&\n                validator.validateRequiredField(form['pspid'], 'connection.pspid.error') &&\n                validator.validateRequiredField(form['apiKey'], 'connection.apiKey.error') &&\n                validator.validateRequiredField(form['apiSecret'], 'connection.apiSecret.error') &&\n                validator.validateRequiredField(form['webhooksKey'], 'connection.webhooksKey.error') &&\n                validator.validateRequiredField(form['webhooksSecret'], 'connection.webhooksSecret.error');\n\n            if (isValid) {\n                utilities.showLoader();\n                api.post(configuration.submitUrl, getFormData())\n                    .then((response) => {\n                        handleSaveSuccess(response);\n                    })\n                    .finally(() => {\n                        utilities.hideLoader();\n                    });\n            }\n\n            return false;\n        };\n\n        const handleSaveSuccess = (response) => {\n            const finishSave = () => {\n                activeSettings = { ...changedSettings };\n                showFlashMessage('connection.messages.connectionUpdated', 'success');\n            };\n\n            if (response.errorMessage === undefined) {\n                utilities.remove401Message();\n                state.enableHeaderTabs();\n                state.display();\n                state.setHeader();\n                finishSave();\n\n                return;\n            }\n\n            showFlashMessage('connection.messages.connectionFailed', 'error');\n        };\n\n        /**\n         * Shows the disconnect confirmation modal.\n         */\n        const showDisconnectModal = () => {\n            showConfirmModal('disconnect').then((confirmed) => confirmed && handleDisconnect());\n        };\n\n        /**\n         * Shows the confirmation modal dialog.\n         *\n         * @param {string} type\n         * @returns {Promise}\n         */\n        const showConfirmModal = (type) => {\n            return new Promise((resolve) => {\n                const modal = components.Modal.create({\n                    title: `connection.${type}Modal.title`,\n                    className: `op-confirm-modal`,\n                    content: [generator.createElement('p', '', `connection.${type}Modal.message`)],\n                    footer: true,\n                    buttons: [\n                        {\n                            type: 'secondary',\n                            label: 'general.cancel',\n                            onClick: () => {\n                                modal.close();\n                                resolve(false);\n                            }\n                        },\n                        {\n                            type: 'primary',\n                            className: 'opm--destructive',\n                            label: 'general.confirm',\n                            onClick: () => {\n                                modal.close();\n                                resolve(true);\n                            }\n                        }\n                    ]\n                });\n\n                modal.open();\n            });\n        };\n\n        const handleDisconnect = () => {\n            utilities.showLoader();\n            api.delete(configuration.disconnectUrl)\n                .then(() => {\n                    window.location.reload();\n                })\n                .finally(() => {\n                    utilities.hideLoader();\n                });\n        };\n\n        /**\n         * Displays the flash message.\n         *\n         * @param {string} message Translation key or message\n         * @param {'success' | 'error'} status\n         */\n        const showFlashMessage = (message, status = 'success') => {\n            utilities.createToasterMessage(message, status);\n        };\n    }\n\n    WOP.ConnectionController = ConnectionController;\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/controllers/ConnectionController.js?");

/***/ }),

/***/ "./src/controllers/MonitoringController.js":
/*!*************************************************!*\
  !*** ./src/controllers/MonitoringController.js ***!
  \*************************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef MonitoringLogsData\n     * @property {boolean} nextPageAvailable\n     * @property {MonitoringLog[]} monitoringLogs\n     * @property {int} beginning\n     * @property {int} end\n     * @property {int} numberOfItems\n     */\n\n    /**\n     * @typedef MonitoringLog\n     * @property {string} orderId\n     * @property {string} paymentNumber\n     * @property {string} logLevel\n     * @property {string} message\n     * @property {string} createdAt\n     * @property {string} requestMethod\n     * @property {string} requestEndpoint\n     * @property {string} requestBody\n     * @property {string} statusCode\n     * @property {string} responseBody\n     * @property {string} transactionLink\n     * @property {string} orderLink\n     */\n\n    /**\n     * @typedef WebhookLogsData\n     * @property {boolean} nextPageAvailable\n     * @property {WebhookLog[]} webhookLogs\n     * @property {int} beginning\n     * @property {int} end\n     * @property {int} numberOfItems\n     */\n\n    /**\n     * @typedef WebhookLog\n     * @property {string} orderId\n     * @property {string} paymentNumber\n     * @property {string} paymentMethod\n     * @property {string} status\n     * @property {string} type\n     * @property {string} createdAt\n     * @property {string} statusCode\n     * @property {string} webhookBody\n     * @property {string} transactionLink\n     * @property {string} orderLink\n     */\n\n    /**\n     * Handles monitoring page logic.\n     *\n     * @param {{getMonitoringLogsUrl: string, getWebhookLogsUrl: string,\n     * downloadMonitoringLogsUrl: string, downloadWebhookLogsUrl: string, page: string}} configuration\n     * @constructor\n     */\n    function MonitoringController(configuration) {\n        /** @type AjaxServiceType */\n        const api = WOP.ajaxService;\n        const {\n            templateService,\n            elementGenerator: generator,\n            utilities,\n            components,\n            translationService\n        } = WOP;\n        const dataTableComponent = components.DataTable;\n        /** @type string */\n        let currentStoreId = '';\n        let activeType = 'webhooks';\n        let nextPageAvailable = true;\n        let currentlyLoading = false;\n        let currentSearchTerm = '';\n        let page = 1;\n        let limit = 10;\n        let shouldRenderHeader = false;\n\n        /**\n         * Displays page content.\n         *\n         * @param {{state?: string, storeId: string}} config\n         */\n        this.display = ({ storeId }) => {\n            currentStoreId = storeId;\n            templateService.clearMainPage();\n\n            configuration.getMonitoringLogsUrl = configuration.getMonitoringLogsUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.downloadMonitoringLogsUrl = configuration.downloadMonitoringLogsUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.getWebhookLogsUrl = configuration.getWebhookLogsUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.downloadWebhookLogsUrl = configuration.downloadWebhookLogsUrl.replace(\n                '{storeId}',\n                storeId\n            );\n\n            return renderPage();\n        };\n\n        const renderPage = () => {\n            utilities.showLoader();\n            let url;\n            let renderer;\n\n            templateService.clearMainPage();\n\n            renderTabs();\n\n            switch (configuration.page) {\n                case 'webhooks':\n                    url = `${configuration.getWebhookLogsUrl}&pageNumber=${page}&pageSize=${limit}`;\n                    renderer = renderWebhookLogsTable;\n                    break;\n                case 'logs':\n                    url = `${configuration.getMonitoringLogsUrl}&pageNumber=${page}&pageSize=${limit}`;\n                    renderer = renderMonitoringLogsTable;\n                    break;\n            }\n\n            return api\n                .get(url, () => {\n                })\n                .then(renderer)\n                .finally(() => {\n                    let header = templateService.getHeaderSection();\n                    let title = header.querySelector('.op-main-title');\n                    title.innerText = WOP.sanitize(translationService.translate('monitoring.title'));\n                    utilities.hideLoader();\n                    WOP.state.setHeader();\n                    WOP.state.initializeFooter();\n                });\n        };\n\n        const renderTabs = () => {\n            let tabs = generator.createElement('div', 'op-tab');\n            let webhookClasses = 'op-tab-item' + (configuration.page === 'webhooks' ? ' op-active' : '');\n            let monitoringClasses = 'op-tab-item' + (configuration.page === 'logs' ? ' op-active' : '');\n            let webhooksTab = generator.createElement(\n                'div',\n                webhookClasses,\n                translationService.translate('monitoring.webhooks.title')\n            );\n            let monitoringTab = generator.createElement(\n                'div',\n                monitoringClasses,\n                translationService.translate('monitoring.logs.title')\n            );\n\n            webhooksTab.addEventListener('click', () => {\n                utilities.showLoader();\n                shouldRenderHeader = false;\n                currentSearchTerm = '';\n                page = 1;\n                monitoringTab.classList.remove('op-active');\n                webhooksTab.classList.add('op-active');\n                activeType = 'webhooks';\n                api.get(`${configuration.getWebhookLogsUrl}&pageNumber=${page}&pageSize=${limit}`, () => {\n                })\n                    .then(renderWebhookLogsTable)\n                    .finally(() => {\n                        utilities.hideLoader();\n                    })\n            });\n\n            monitoringTab.addEventListener('click', () => {\n                utilities.showLoader();\n                shouldRenderHeader = false;\n                page = 1;\n                currentSearchTerm = '';\n                webhooksTab.classList.remove('op-active');\n                monitoringTab.classList.add('op-active');\n                activeType = 'logs';\n                api.get(`${configuration.getMonitoringLogsUrl}&pageNumber=${page}&pageSize=${limit}`, () => {\n                })\n                    .then(renderMonitoringLogsTable)\n                    .finally(() => {\n                        utilities.hideLoader();\n                    })\n            });\n\n            tabs.appendChild(webhooksTab);\n            tabs.appendChild(monitoringTab);\n            templateService.getMainPage().appendChild(tabs);\n        };\n\n        /**\n         * Renders the webhook logs table.\n         *\n         * @param {WebhookLogsData} webhookLogsPage\n         */\n        const renderWebhookLogsTable = (webhookLogsPage) => {\n            const headers = [\n                'monitoring.webhooks.webhookEventsLogs.orderId',\n                'monitoring.webhooks.webhookEventsLogs.paymentNumber',\n                'monitoring.webhooks.webhookEventsLogs.paymentMethod',\n                'monitoring.webhooks.webhookEventsLogs.status',\n                'monitoring.webhooks.webhookEventsLogs.type',\n                'monitoring.webhooks.webhookEventsLogs.createdAt',\n                'monitoring.webhooks.webhookEventsLogs.statusCode',\n                ''\n            ];\n\n            createNotifications(headers, getRowsConfig, 'Webhooks', webhookLogsPage);\n        };\n\n        /**\n         * Renders the monitoring logs table.\n         *\n         * @param {MonitoringLogsData} monitoringLogsPage\n         */\n        const renderMonitoringLogsTable = (monitoringLogsPage) => {\n            const headers = [\n                'monitoring.logs.monitoringLogs.orderId',\n                'monitoring.logs.monitoringLogs.paymentNumber',\n                'monitoring.logs.monitoringLogs.logLevel',\n                'monitoring.logs.monitoringLogs.logMessage',\n                'monitoring.logs.monitoringLogs.createdAt',\n                ''\n            ];\n            createNotifications(headers, getMonitoringLogsRowsConfig, 'Logs', monitoringLogsPage);\n        };\n\n        /**\n         * @param {WebhookLog} log Log.\n         */\n        const renderWebhookDetailsModal = (log) => {\n            const modal = components.Modal.create({\n                title: `monitoring.webhooks.modal.title`,\n                className: 'op-webhook-notifications-modal',\n                content: [\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.orderId'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.orderId)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.paymentNumber'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.paymentNumber)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.paymentMethod'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.paymentMethod)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.status'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.status)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.type'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.type)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.createdAt'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.createdAt)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.statusCode'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.statusCode)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.webhooks.modal.webhookBody'\n                        ),\n                        generator.createElement('span', 'op-webhook-details', log.webhookBody)\n                    ]),\n                ],\n                footer: true,\n                canClose: true,\n                buttons: [\n                    {\n                        type: 'primary',\n                        label: 'general.ok',\n                        onClick: () => modal.close()\n                    }\n                ]\n            });\n\n            modal.open();\n        };\n\n        /**\n         * @param {MonitoringLog} log\n         */\n        const renderLogDetailsModal = (log) => {\n            const modal = components.Modal.create({\n                title: `monitoring.logs.modal.title`,\n                className: 'op-webhook-notifications-modal',\n                content: [\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.orderId'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.orderId)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.paymentNumber'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.paymentNumber)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.logLevel'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.logLevel)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.logMessage'\n                        ),\n                        generator.createElement('span', 'op-webhook-details', log.message)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.createdAt'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.createdAt)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.requestMethod'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.requestMethod)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.requestEndpoint'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.requestEndpoint)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.requestBody'\n                        ),\n                        generator.createElement('span', 'op-webhook-details', log.requestBody, null, null, false, false)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.responseStatusCode'\n                        ),\n                        generator.createElement('span', 'opp-reason-text', log.statusCode)\n                    ]),\n                    generator.createElement('p', 'opp-reason', '', null, [\n                        generator.createElement(\n                            'span',\n                            'opp-reason-title',\n                            'monitoring.logs.modal.responseBody'\n                        ),\n                        generator.createElement('span', 'op-webhook-details', log.responseBody, null, null, false, false)\n                    ]),\n                ],\n                footer: true,\n                canClose: true,\n                buttons: [\n                    {\n                        type: 'primary',\n                        label: 'general.ok',\n                        onClick: () => modal.close()\n                    }\n                ]\n            });\n\n            modal.open();\n        }\n\n        /**\n         * Renders webhooks table rows.\n         *\n         * @param {WebhookLog[]} webhookLogs\n         * @returns {TableCell[][]}\n         */\n        const getRowsConfig = (webhookLogs) => {\n            return webhookLogs?.map((webhookLog) => {\n                return [\n                    {\n                        renderer: (cell) => {\n                            if (webhookLog.orderLink) {\n                                let link = generator.createElement(\n                                    'a',\n                                    'opm--left-aligned opm--green-text opm--link',\n                                    '',\n                                    { href: webhookLog.orderLink, target: '_blank' },\n                                    [\n                                        generator.createElement(\n                                            'span',\n                                            '',\n                                            webhookLog.orderId\n                                        )\n                                    ]\n                                );\n\n                                cell.append(link);\n                            } else {\n                                cell.append(\n                                    generator.createElement(\n                                        'span',\n                                        '',\n                                        webhookLog.orderId\n                                    )\n                                );\n                            }\n                        },\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) => {\n                            if (webhookLog.transactionLink) {\n                                let link = generator.createElement(\n                                    'a',\n                                    'opm--left-aligned opm--green-text opm--link',\n                                    '',\n                                    { href: webhookLog.transactionLink, target: '_blank' },\n                                    [\n                                        generator.createElement(\n                                            'span',\n                                            '',\n                                            webhookLog.paymentNumber\n                                        )\n                                    ]\n                                );\n\n                                cell.append(link);\n                            } else {\n                                cell.append(\n                                    generator.createElement(\n                                        'span',\n                                        '',\n                                        webhookLog.paymentNumber\n                                    )\n                                );\n                            }\n                        },\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: webhookLog.paymentMethod,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) =>\n                            cell.append(\n                                generator.createElement(\n                                    'span',\n                                    `opp-status opt--${webhookLog.status.toLowerCase()}`,\n                                    translationService.translate(`monitoring.webhooks.status.${webhookLog.status}`)\n                                )\n                            ),\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: webhookLog.type,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: webhookLog.createdAt,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: webhookLog.statusCode,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) => {\n                            const moreActionsWrapper = generator.createElement('div', 'op-link-dropdown');\n                            const moreActions = generator.createElement('div', 'op-list-dropdown');\n                            const moreActionsList = generator.createElement('ul', 'opp-dropdown-list');\n                            const moreActionsButton = generator.createElement(\n                                'button',\n                                'op-more-actions-button opt--ghost',\n                                '\\u00B7\\u00B7\\u00B7'\n                            );\n                            moreActionsButton.addEventListener('click', (event) => {\n                                event.preventDefault();\n                                event.stopPropagation();\n                                moreActionsList.classList.toggle('ops--show');\n                                cell.classList.toggle('ops--active');\n                            });\n                            document.addEventListener('mouseup', function (e) {\n                                if (moreActionsButton !== e.target) {\n                                    cell.classList.remove('ops--active');\n                                    moreActionsList.classList.remove('ops--show');\n                                }\n                            });\n\n                            const viewDetails = generator.createElement(\n                                'li',\n                                'opp-dropdown-list-item-icon-before op-learn-more',\n                                translationService.translate('monitoring.webhooks.webhookEventsLogs.viewDetails')\n                            );\n                            moreActionsList.appendChild(viewDetails);\n                            viewDetails.addEventListener('click', (event) => {\n                                moreActionsList.classList.toggle('ops--show');\n                                cell.classList.toggle('ops--active');\n                                renderWebhookDetailsModal(webhookLog);\n                            });\n                            moreActions.appendChild(moreActionsButton)\n                            moreActions.appendChild(moreActionsList);\n                            moreActionsWrapper.appendChild(moreActions);\n                            cell.append(moreActionsWrapper);\n                        }\n                    }\n                ];\n            });\n        };\n\n        /**\n         * Renders monitoring logs table rows.\n         *\n         * @param {MonitoringLog[]} monitoringLogs\n         * @returns {TableCell[][]}\n         */\n        const getMonitoringLogsRowsConfig = (monitoringLogs) => {\n            return monitoringLogs?.map((monitoringLog) => {\n                const options = {\n                    day: 'numeric',\n                    month: 'numeric',\n                    year: 'numeric',\n                    hour: 'numeric',\n                    minute: 'numeric',\n                    hour12: false\n                };\n\n                const formattedDateTime = new Date(monitoringLog.createdAt)\n                    .toLocaleString('en-US', options)\n                    .replace(/, /g, ' ')\n                    .replace(/\\//g, '-');\n\n                return [\n                    {\n                        renderer: (cell) => {\n                            if (monitoringLog.orderLink) {\n                                let link = generator.createElement(\n                                    'a',\n                                    'opm--left-aligned opm--green-text opm--link',\n                                    '',\n                                    { href: monitoringLog.orderLink, target: '_blank' },\n                                    [\n                                        generator.createElement(\n                                            'span',\n                                            '',\n                                            monitoringLog.orderId\n                                        )\n                                    ]\n                                );\n\n                                cell.append(link);\n                            } else {\n                                cell.append(\n                                    generator.createElement(\n                                        'span',\n                                        '',\n                                        monitoringLog.orderId\n                                    )\n                                )\n                            }\n                        },\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) => {\n                            if (monitoringLog.transactionLink) {\n                                let link = generator.createElement(\n                                    'a',\n                                    'opm--left-aligned opm--green-text opm--link',\n                                    '',\n                                    { href: monitoringLog.transactionLink, target: '_blank' },\n                                    [\n                                        generator.createElement(\n                                            'span',\n                                            '',\n                                            monitoringLog.paymentNumber\n                                        )\n                                    ]\n                                );\n\n                                cell.append(link);\n                            } else {\n                                cell.append(\n                                    generator.createElement(\n                                        'span',\n                                        '',\n                                        monitoringLog.paymentNumber\n                                    )\n                                )\n                            }\n                        },\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) =>\n                            cell.append(\n                                generator.createElement(\n                                    'span',\n                                    `opp-status opt--${monitoringLog.logLevel.toLowerCase()}`,\n                                    translationService.translate(`monitoring.logs.severity.${monitoringLog.logLevel}`)\n                                )\n                            ),\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: monitoringLog.message,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        label: formattedDateTime,\n                        className: 'opm--left-aligned'\n                    },\n                    {\n                        renderer: (cell) => {\n                            const moreActionsWrapper = generator.createElement('div', 'op-link-dropdown');\n                            const moreActions = generator.createElement('div', 'op-list-dropdown');\n                            const moreActionsList = generator.createElement('ul', 'opp-dropdown-list');\n                            const moreActionsButton = generator.createElement(\n                                'button',\n                                'op-more-actions-button opt--ghost',\n                                '\\u00B7\\u00B7\\u00B7'\n                            );\n                            moreActionsButton.addEventListener('click', (event) => {\n                                event.preventDefault();\n                                event.stopPropagation();\n                                moreActionsList.classList.toggle('ops--show');\n                                cell.classList.toggle('ops--active');\n                            });\n                            document.addEventListener('mouseup', function (e) {\n                                if (moreActionsButton !== e.target) {\n                                    cell.classList.remove('ops--active');\n                                    moreActionsList.classList.remove('ops--show');\n                                }\n                            });\n\n                            const viewDetails = generator.createElement(\n                                'li',\n                                'opp-dropdown-list-item-icon-before op-learn-more',\n                                translationService.translate('monitoring.webhooks.webhookEventsLogs.viewDetails')\n                            );\n                            moreActionsList.appendChild(viewDetails);\n                            viewDetails.addEventListener('click', (event) => {\n                                moreActionsList.classList.toggle('ops--show');\n                                cell.classList.toggle('ops--active');\n                                renderLogDetailsModal(monitoringLog);\n                            });\n                            moreActions.appendChild(moreActionsButton)\n                            moreActions.appendChild(moreActionsList);\n                            moreActionsWrapper.appendChild(moreActions);\n                            cell.append(moreActionsWrapper);\n                        }\n                    }\n                ];\n            });\n        };\n\n        /**\n         * Returns a function that renders a notifications table and handles pagination.\n         *\n         * @param {string[]} headers The table headers.\n         * @param {(notifications: any[]) => TableCell[][]} getRowsConfig A function that maps logs to table rows.\n         * @param {string} type The type of logs.\n         * @param {WebhookLogsData | MonitoringLogsData} logsPage Webhook logs page.\n         */\n        const createNotifications = (headers, getRowsConfig, type, logsPage) => {\n            const typeLc = type.toLowerCase();\n            nextPageAvailable = logsPage.nextPageAvailable;\n\n            if (activeType !== typeLc) {\n                page = 1;\n            }\n            currentlyLoading = false;\n\n            let component = templateService.getMainPage().querySelector('.op-notifications-page');\n\n            if (component) {\n                component.parentNode.removeChild(component);\n            }\n\n            const headerCells = headers.map((headerLabel) => ({\n                label: headerLabel,\n                className: 'opm--center-aligned'\n            }));\n\n            const rows = getRowsConfig(typeLc === 'webhooks' ? logsPage.webhookLogs : logsPage.monitoringLogs);\n            const downloadBtn = generator.createElement('a', 'op-button opt--ghost ops--icon', 'monitoring.download');\n\n            if (rows.length === 0) {\n                downloadBtn.classList.add('ops--disabled');\n            }\n\n            downloadBtn.href = typeLc === 'webhooks' ? configuration.downloadWebhookLogsUrl : configuration.downloadMonitoringLogsUrl;\n\n            templateService\n                .getMainPage()\n                .append(\n                    generator.createElement('div', `op-notifications-page`, '', null, [\n                        generator.createElement('div', 'op-title', '', null, [\n                            generator.createElement(\n                                'p',\n                                '',\n                                WOP.brand.code + `.monitoring.${typeLc}.description`\n                            ),\n                            downloadBtn\n                        ]),\n                        rows.length ? renderTableHeading(logsPage, typeLc) : (shouldRenderHeader ? renderTableHeading(logsPage, typeLc) : ''),\n                        rows.length\n                            ? dataTableComponent.createDataTable(headerCells, rows, `op-notifications-table`)\n                            : dataTableComponent.createNoItemsMessage(`monitoring.${typeLc}.noLogsMessage`)\n                    ])\n                );\n        };\n\n        /**\n         * @param {WebhookLogsData | MonitoringLogsData} logsPage Webhook logs page.\n         * @param {string} type\n         */\n        const renderTableHeading = (logsPage, type) => {\n            return generator.createElement('div', 'op-table-heading', '', null, [\n                renderSearchField(type),\n                renderPagination(logsPage, type)\n            ]);\n        };\n\n        /**\n         * @param {string} type\n         * @returns {*|HTMLElement}\n         */\n        const renderSearchField = (type) => {\n            let wrapper = generator.createElement('div', 'op-search-wrapper');\n            let searchContainer = generator.createElement('div', 'op-search-container');\n            let searchWrapper = generator.createElement('div', 'op-search-field-wrapper');\n            let searchIcon = generator.createElement('span', 'op-search-icon');\n            let searchField = generator.createElement('input', 'op-search-input');\n\n            searchField.type = 'text';\n            searchField.placeholder = translationService.translate('monitoring.search.placeholder');\n\n            if (currentSearchTerm !== '') {\n                searchField.value = currentSearchTerm;\n            }\n\n            searchWrapper.appendChild(searchIcon);\n            searchWrapper.appendChild(searchField);\n\n            let button = generator.createButton({\n                type: 'primary',\n                label: translationService.translate('general.search')\n            });\n\n            function search() {\n                utilities.showLoader();\n                shouldRenderHeader = true;\n                let url = '';\n                let renderer = null;\n                let searchTerm = WOP.sanitize(searchField.value);\n\n                switch (type) {\n                    case 'webhooks':\n                        currentSearchTerm = searchTerm;\n                        url = `${configuration.getWebhookLogsUrl}&pageNumber=${page}&pageSize=${limit}&searchTerm=${searchTerm}`;\n                        renderer = renderWebhookLogsTable;\n                        break;\n                    case 'logs':\n                        currentSearchTerm = searchTerm;\n                        url = `${configuration.getMonitoringLogsUrl}&pageNumber=${page}&pageSize=${limit}&searchTerm=${searchTerm}`;\n                        renderer = renderMonitoringLogsTable;\n                        break;\n                }\n\n                api\n                    .get(url, () => {\n                    })\n                    .then(renderer)\n                    .finally(() => {\n                        utilities.hideLoader();\n                    });\n            }\n\n            button.addEventListener('click', function () {\n                search();\n            });\n\n            searchField.addEventListener('keydown', (e) => {\n                if (e.key === 'Enter') {\n                    e.preventDefault();\n                    e.stopPropagation();\n                    search();\n                }\n            });\n\n            searchContainer.appendChild(searchWrapper);\n            searchContainer.appendChild(button);\n            wrapper.appendChild(searchContainer);\n\n            return wrapper;\n        };\n\n        /**\n         * @param {WebhookLogsData | MonitoringLogsData} logsPage Webhook logs page.\n         * @param {string} type\n         *\n         * @returns {*|HTMLElement}\n         */\n        const renderPagination = (logsPage, type) => {\n            const rerenderPage = () => {\n                let url = '', renderer;\n                switch (type) {\n                    case 'webhooks':\n                        url = `${configuration.getWebhookLogsUrl}&pageNumber=${page}&pageSize=${limit}`;\n\n                        if (currentSearchTerm !== '') {\n                            url += '&searchTerm=' + currentSearchTerm;\n                        }\n\n                        renderer = renderWebhookLogsTable;\n                        break;\n                    case 'logs':\n                        url = `${configuration.getMonitoringLogsUrl}&pageNumber=${page}&pageSize=${limit}`;\n\n                        if (currentSearchTerm !== '') {\n                            url += '&searchTerm=' + currentSearchTerm;\n                        }\n\n                        renderer = renderMonitoringLogsTable;\n                        break;\n                }\n\n                utilities.showLoader();\n\n                api\n                    .get(url, () => {\n                    })\n                    .then(renderer)\n                    .finally(() => {\n                        utilities.hideLoader();\n                    });\n            }\n\n            let paginator = generator.createElement('div', 'op-paginator');\n            let label = generator.createElement(\n                'div',\n                '',\n                translationService.translate(\n                    'monitoring.pagination.numberOfItems',\n                    [logsPage.beginning, logsPage.end, logsPage.numberOfItems]\n                )\n            );\n            paginator.appendChild(label);\n\n            const dropdownWrapper = generator.createElement('div', '');\n            const dropdown = generator.createElement('div', 'op-single-select-dropdown');\n            const dropdownButton = generator.createElement('button', 'op-number-of-items-button');\n            const dropdownArrow = generator.createElement('span', 'op-number-of-items');\n            const list = generator.createElement('ul', 'opp-dropdown-list');\n            const value10 = generator.createElement('li', '', '10');\n            const value25 = generator.createElement('li', '', '25');\n            const value50 = generator.createElement('li', '', '50');\n\n            value10.addEventListener('click', function () {\n                limit = 10;\n                page = 1;\n                rerenderPage();\n            });\n            value25.addEventListener('click', function () {\n                limit = 25;\n                page = 1;\n                rerenderPage();\n            });\n            value50.addEventListener('click', function () {\n                limit = 50;\n                page = 1;\n                rerenderPage();\n            })\n            list.appendChild(value10);\n            list.appendChild(value25);\n            list.appendChild(value50);\n            dropdownButton.appendChild(dropdownArrow);\n            dropdownButton.addEventListener('click', (e) => {\n                e.preventDefault();\n                e.stopPropagation();\n                list.classList.toggle('ops--show');\n            });\n            document.addEventListener('mouseup', function (e) {\n                if (!dropdown.contains(e.target)) {\n                    list.classList.remove('ops--show');\n                }\n            });\n\n            dropdown.appendChild(dropdownButton);\n            dropdown.appendChild(list);\n            dropdownWrapper.appendChild(dropdown);\n            paginator.appendChild(dropdownWrapper);\n\n            let navigation = generator.createElement('div', 'op-navigation');\n            let previousPage = generator.createElement('div', 'op-previous-page');\n            let previousPageIcon = generator.createElement('span', 'op-previous-page-icon');\n\n            previousPage.addEventListener('click', function () {\n                page = page - 1;\n\n                rerenderPage();\n            });\n\n            if (page === 1) {\n                previousPage.classList.add('op-inactive');\n            }\n\n            previousPage.appendChild(previousPageIcon);\n            navigation.appendChild(previousPage);\n\n            let nextPage = generator.createElement('div', 'op-next-page');\n            let nextPageIcon = generator.createElement('span', 'op-next-page-icon');\n\n            nextPage.addEventListener('click', function () {\n                page = page + 1;\n\n                rerenderPage();\n            });\n\n            if (!logsPage.nextPageAvailable) {\n                nextPage.classList.add('op-inactive');\n            }\n\n            nextPage.appendChild(nextPageIcon);\n            navigation.appendChild(nextPage);\n            paginator.appendChild(navigation);\n\n            return paginator;\n        };\n    }\n\n    WOP.MonitoringController = MonitoringController;\n})();\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/controllers/MonitoringController.js?");

/***/ }),

/***/ "./src/controllers/PaymentsController.js":
/*!***********************************************!*\
  !*** ./src/controllers/PaymentsController.js ***!
  \***********************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef TranslatableLabel\n     *\n     * @property {string}\n     */\n\n    /**\n     * @typedef PaymentMethod\n     * @property {string} paymentProductId\n     * @property {TranslatableLabel[]} name\n     * @property {string} paymentGroup\n     * @property {string[]} integrationTypes\n     * @property {boolean} enabled\n     */\n\n    const paymentMethodsLearnMoreLinks = {\n        cards: 'index?payment-method=Cards%20%28debit%20%26%20credit%29',\n        hosted_checkout: '',\n        5405: 'alipay',\n        302: 'applepay',\n        5408: 'bank-transfer',\n        3103: 'bimpli-cado',\n        5001: 'bizum',\n        5601: 'cadhoc',\n        5403: 'cheque-vacances-connect',\n        5133: 'cetelem-3x-4x',\n        5129: 'cofidis-3x-4x',\n        5100: 'cpay',\n        2: 'american-express',\n        3012: 'bancontact',\n        130: 'cartes-bancaires',\n        132: 'diners',\n        128: 'discover',\n        125: 'jcb',\n        3: 'mastercard',\n        117: 'maestro',\n        56: 'union-pay',\n        1: 'visa',\n        5406: 'eps',\n        320: 'google-pay',\n        809: 'ideal',\n        3112: 'illicado',\n        5700: 'intersolve',\n        3301: 'klarna',\n        5908: 'mb-way',\n        5402: 'mealvouchers',\n        5500: 'multibanco',\n        5111: 'oney-3x-4x',\n        5112: 'oney-3x-4x',\n        5127: 'oney-bank-card',\n        5125: 'oney-financement-long',\n        5600: 'oneybrandedgiftcard',\n        3124: 'przelewy24',\n        840: 'paypal',\n        3203: 'postfinance-pay',\n        771: 'sepa-direct-debit',\n        5131: 'sofinco-3x-4x',\n        3116: 'spirit-of-cadeau',\n        5407: 'twint',\n        5404: 'wechat'\n    };\n\n    const paymentGroups = [\n        'mobile',\n        'realTimeBanking',\n        'giftCards',\n        'prepaid',\n        'instalment',\n        'cards',\n        'eWallet',\n        'postpaid',\n        'directDebit',\n        'hosted'\n    ];\n\n    const integrationTypes = [\n        'hosted',\n        'redirect',\n        'tokenization'\n    ];\n\n    /**\n     * @typedef AdditionalDataConfig\n     * @property {boolean?} showLogos\n     * @property {boolean?} singleClickPayment\n     * @property {boolean?} sendBasket\n     * @property {boolean?} installments\n     * @property {boolean?} installmentAmounts\n     * @property {string[]?} installmentCountries\n     * @property {string?} supportedInstallments\n     * @property {number?} minimumAmount\n     * @property {string?} numberOfInstallments\n     * @property {string?} bankIssuer\n     * @property {string?} merchantId\n     * @property {string?} publicKeyId\n     * @property {string?} storeId\n     * @property {string?} gatewayMerchantId\n     * @property {string?} merchantName\n     * @property {boolean?} displayButtonOn\n     */\n\n    /**\n     * @typedef PaymentMethodConfiguration\n     * @property {boolean} isNew\n     * @property {boolean} excludeFromPayByLink\n     * @property {string} methodId\n     * @property {string} code\n     * @property {string?} name\n     * @property {string?} description\n     * @property { 'none' | 'fixed' | 'percent' | 'combined' } surchargeType\n     * @property {number?} fixedSurcharge\n     * @property {number?} percentSurcharge\n     * @property {number?} surchargeLimit\n     * @property {string?} logo\n     * @property {Blob?} logoFile\n     * @property {'creditOrDebitCard' | 'buyNowPayLater' | 'cashOrAtm' | 'directDebit' | 'onlinePayments' | 'wallet' |\n     *     'prepaidAndGiftCard' | 'mobile'} paymentType\n     * @property {AdditionalDataConfig?} additionalData\n     */\n    /**\n     * Handles payments pages logic.\n     *\n     * @param {{getAvailablePaymentsUrl: string, enableMethodUrl: string,\n     *     saveMethodConfigurationUrl: string, getMethodConfigurationUrl: string,\n     *     paymentMethodLogoUrl: string, getLanguagesUrl: string\n     *     }} configuration\n     * @constructor\n     */\n    function PaymentsController(configuration) {\n        /** @type AjaxServiceType */\n        const api = WOP.ajaxService;\n\n        const {\n            templateService,\n            translationService,\n            elementGenerator: generator,\n            validationService: validator,\n            components,\n            utilities\n        } = WOP;\n\n        const dataTableComponent = WOP.components.DataTable;\n\n        /** @type {HTMLElement} */\n        let page;\n\n        /** @type {Record<string, string[]>} */\n        let activeFilters = {};\n\n        /** @type {PaymentMethod[]} */\n        let availableMethods = [];\n\n        /** @type {number} */\n        let numberOfChanges = 0;\n\n        /**\n         * Replaces an active page with the other one rendered by a provider renderer method.\n         *\n         * @param {() => void} renderer\n         */\n        const switchPage = (renderer) => {\n            utilities.showLoader();\n            document.querySelector('.op-form-footer')?.remove();\n            if (!page) {\n                page = generator.createElement('div', 'op-payments-page');\n            } else {\n                templateService.clearComponent(page);\n            }\n\n            activeFilters = {};\n            renderer();\n        };\n\n        /**\n         * Filters methods based on the current filter.\n         *\n         * @returns {PaymentMethod[]}\n         */\n        const applyFilter = () => {\n            return availableMethods.filter((method) => {\n                if (activeFilters.integrationType?.length && !activeFilters.integrationType.some(item => method.integrationTypes.includes(\n                    item))) {\n                    return false;\n                }\n\n                if (\n                    activeFilters.paymentGroups?.length &&\n                    !activeFilters.paymentGroups.includes(method.paymentGroup)\n                ) {\n                    return false;\n                }\n\n                if (activeFilters.paymentProduct?.length &&\n                    !method.name.value.toLowerCase().includes(activeFilters.paymentProduct.toLowerCase())) {\n                    return false;\n                }\n\n                return true;\n            });\n        };\n\n        function openModal(method) {\n            api.get(configuration.getMethodConfigurationUrl.replace(\n                    '{methodId}',\n                    method.paymentProductId\n                )\n            ).then((response) => {\n                api.get(configuration.getLanguagesUrl).then((languages) => {\n                    templateService.getMainPage().appendChild(generator.createElement(\n                        'div',\n                        'op-dark-mask'\n                    ));\n\n                    const modal = WOP.components.SlidingModal.create(\n                        {\n                            paymentProductId: method.paymentProductId,\n                            enabled: response.enabled,\n                            name: response.name,\n                            integrationTypes: method.integrationTypes,\n                            paymentGroup: method.paymentGroup,\n                            template: response.template,\n                            paymentAction: response.paymentAction,\n                            logo: configuration.paymentMethodLogoUrl + method.paymentProductId + '.svg',\n                            additionalData: response.additionalData\n                        },\n                        configuration.saveMethodConfigurationUrl,\n                        languages\n                    );\n                    page.appendChild(modal);\n                    page.classList.add('op-settings-modal-opened');\n\n                    setTimeout(() => {\n                        modal.classList.add('op-open');\n                        utilities.hideLoader();\n                    }, 200);\n                })\n            })\n        }\n\n        function renderPaymentMethodsList(form, methods) {\n            const methodsList = generator.createElement('div');\n\n            methods.forEach((method) => {\n                const wrapper = generator.createElement('div', 'op-payment-component');\n                const logo = generator.createElement('img', 'op-payment-logo');\n                logo.src = configuration.paymentMethodLogoUrl + method.paymentProductId + '.svg';\n                wrapper.appendChild(logo);\n                const methodDetails = generator.createElement('div', 'op-payment-details-wrapper');\n                const methodNameWrapper = generator.createElement('div', 'op-payment-details');\n                const methodName = generator.createElement(\n                    'p',\n                    'op-payment-name',\n                    WOP.sanitize(translationService.translate(method.name.value)),\n                    null,\n                    null,\n                    false,\n                    false\n                );\n                methodNameWrapper.appendChild(methodName);\n                method.integrationTypes.forEach((type) => {\n                    const typeElement = generator.createElement(\n                        'span',\n                        'op-integration-type ' + 'op-' + type,\n                        'payments.integrationType.' + type\n                    );\n                    methodNameWrapper.appendChild(typeElement);\n                });\n                methodDetails.appendChild(methodNameWrapper);\n                wrapper.appendChild(methodDetails);\n                let paymentGroup = generator.createElement(\n                    'p',\n                    'op-payment-group',\n                    'payments.paymentGroups.' + method.paymentGroup\n                );\n\n                if (method.paymentGroup === 'hosted') {\n                    paymentGroup = generator.createElement(\n                        'p',\n                        'op-payment-group',\n                        WOP.brand.code + '.payments.paymentGroups.' + method.paymentGroup\n                    );\n                }\n\n                methodDetails.appendChild(paymentGroup);\n                const actions = generator.createElement('div', 'op-more-actions');\n                const toggleWrapper = generator.createElement('div', 'opp-field-component');\n                const toggleLabel = generator.createElement('label', 'op-toggle');\n                const toggleInput = generator.createElement(\n                    'input',\n                    'opp-toggle-input',\n                    '',\n                    {'type': 'checkbox', 'checked': method.enabled}\n                );\n                toggleInput.addEventListener('click', function (event) {\n                    utilities.showLoader();\n                    const url = configuration.enableMethodUrl;\n                    const data = {\n                        paymentProductId: method.paymentProductId,\n                        enabled: !method.enabled\n                    }\n\n                    method.enabled = !method.enabled;\n\n                    api.post(url, data).then((response) => {\n                        utilities.hideLoader();\n                    }).catch((errorResponse) => {\n                        this.checked = method.enabled;\n                        utilities.hideLoader();\n                    });\n                });\n                const toggleSpan = generator.createElement('span', 'opp-toggle-round');\n                toggleLabel.appendChild(toggleInput);\n                toggleLabel.appendChild(toggleSpan);\n                toggleWrapper.appendChild(toggleLabel);\n                actions.appendChild(toggleWrapper);\n                const moreActionsWrapper = generator.createElement('div', 'op-link-dropdown');\n                const moreActions = generator.createElement('div', 'op-list-dropdown');\n                const moreActionsButton = generator.createElement(\n                    'button',\n                    'op-more-actions-button opt--ghost',\n                    '\\u00B7\\u00B7\\u00B7'\n                );\n                moreActionsButton.addEventListener('click', (event) => {\n                    event.preventDefault();\n                    event.stopPropagation();\n                    moreActionsList.classList.toggle('ops--show');\n                    wrapper.classList.toggle('ops--active');\n                });\n\n                const moreActionsList = generator.createElement('ul', 'opp-dropdown-list');\n                const settings = generator.createElement(\n                    'li',\n                    'opp-dropdown-list-item-icon-before op-settings',\n                    'payments.list.settings'\n                );\n                const learnMore = generator.createElement(\n                    'li',\n                    'opp-dropdown-list-item-icon-before op-learn-more',\n                    'payments.list.learnMore'\n                );\n                settings.addEventListener('click', (event) => {\n                    moreActionsList.classList.toggle('ops--show');\n                    openModal(method);\n                });\n\n                learnMore.addEventListener('click', (event) => {\n                    moreActionsList.classList.toggle('ops--show');\n                    window.open(translationService.translate(WOP.brand.code + '.documentationLink')\n                        + paymentMethodsLearnMoreLinks[method.paymentProductId], '_blank');\n                });\n                document.addEventListener('mouseup', function (e) {\n                    if (!moreActionsList.contains(e.target)) {\n                        moreActionsList.classList.remove('ops--show');\n                    }\n                });\n\n                moreActionsList.appendChild(settings);\n                moreActionsList.appendChild(learnMore);\n                moreActions.appendChild(moreActionsButton);\n                moreActions.appendChild(moreActionsList);\n                moreActionsWrapper.appendChild(moreActions);\n                actions.appendChild(moreActionsWrapper);\n                wrapper.appendChild(actions);\n\n                methodsList.appendChild(wrapper);\n            });\n\n            form.appendChild(renderPaymentsTableFilter());\n            form.appendChild(methodsList);\n            page.appendChild(form);\n\n            templateService.getMainPage().append(page);\n        }\n\n        /**\n         * Renders the active payments form.\n         */\n        const renderActivePaymentsForm = () => {\n            const form = generator.createElement('form', 'op-payments-form');\n            const title = generator.createElement('p', 'op-payments-title', 'payments.title', null, null, true);\n            const divider = generator.createElement('div', 'op-payments-divider');\n\n            form.appendChild(title);\n            form.appendChild(divider);\n\n            const storedFilters = window.sessionStorage.getItem('activeFilters');\n            if (storedFilters) {\n                try {\n                    activeFilters = JSON.parse(storedFilters);\n                } catch (e) {\n                    console.error('Failed to parse stored filters:', e);\n                    activeFilters = {};\n                }\n            }\n\n            api.get(configuration.getAvailablePaymentsUrl)\n                .then((methods) => {\n                    templateService.clearMainPage();\n                    availableMethods = methods;\n                    const filteredMethods = Object.keys(activeFilters).length > 0 ? applyFilter() : methods;\n                    renderPaymentMethodsList(form, filteredMethods);\n                })\n                .catch(() => false)\n                .finally(() => {\n                    let header = templateService.getHeaderSection();\n                    let title = header.querySelector('.op-main-title');\n                    title.innerText = WOP.sanitize(translationService.translate('payments.pageTitle'));\n                    utilities.hideLoader();\n                    WOP.state.setHeader();\n                    WOP.state.initializeFooter();\n                });\n        };\n\n        /**\n         * Creates payments table filer.\n         */\n        const renderPaymentsTableFilter = () => {\n            let filters = generator.createElement('div', 'opp-table-filters');\n            let title = generator.createElement(\n                'div',\n                'op-title',\n                '',\n                '',\n                [\n                    generator.createElement(\n                        'span',\n                        'op-filter-icon'\n                    ),\n                    generator.createElement(\n                        'p',\n                        '',\n                        translationService.translate('payments.filter.filter')\n                    ),\n                    generator.createElement(\n                        'div',\n                        'op-vertical-divider'\n                    )\n                ]\n            );\n            let resetBtn = generator.createButton(\n                {\n                    type: 'ghost',\n                    size: 'small',\n                    className: 'opm--icon ops--hidden',\n                    label: 'payments.filter.resetAll',\n                    onClick: () => {\n                        activeFilters = {};\n                        window.sessionStorage.removeItem('activeFilters');\n                        let form = document.querySelector('.op-payments-form');\n                        templateService.clearComponent(form);\n\n                        const title = generator.createElement('p', 'op-payments-title', 'payments.title', null, null, true);\n                        const divider = generator.createElement('div', 'op-payments-divider');\n\n                        form.appendChild(title);\n                        form.appendChild(divider);\n\n                        renderPaymentMethodsList(form, applyFilter());\n                    }\n                }\n            );\n            if (Object.values(activeFilters).reduce((result, options) => result + options.length, 0) === 0) {\n                resetBtn.classList.add('ops--hidden');\n            } else {\n                resetBtn.classList.remove('ops--hidden');\n            }\n\n            let container = generator.createElement('div', 'opp-table-filter-wrapper', '', null, [\n                filters\n            ]);\n\n            const changeFilter = (filter, values) => {\n                activeFilters[filter] = values;\n                window.sessionStorage.setItem('activeFilters', JSON.stringify(activeFilters));\n\n                if (Object.values(activeFilters).reduce((result, options) => result + options.length, 0) === 0) {\n                    resetBtn.classList.add('ops--hidden');\n                } else {\n                    resetBtn.classList.remove('ops--hidden');\n                }\n                let form = document.querySelector('.op-payments-form');\n                templateService.clearComponent(form);\n\n                const title = generator.createElement('p', 'op-payments-title', 'payments.title', null, null, true);\n                const divider = generator.createElement('div', 'op-payments-divider');\n\n                form.appendChild(title);\n                form.appendChild(divider);\n\n                renderPaymentMethodsList(form, applyFilter());\n            };\n            let searchFiled = generator.createElement(\n                'input',\n                'op-product-name-search',\n                activeFilters.paymentProduct || translationService.translate('payments.filter.paymentProduct.label'),\n                {\n                    placeholder: translationService.translate('payments.filter.paymentProduct.placeholder'),\n                    onChange: (event) => changeFilter('paymentProduct', event.target.value)\n                }\n            );\n\n            if (activeFilters.paymentProduct) {\n                searchFiled.value = activeFilters.paymentProduct;\n            }\n\n            searchFiled.addEventListener('keydown', (e) => {\n                if (e.key === 'Enter') {\n                    e.preventDefault();\n                    e.stopPropagation();\n                    changeFilter('paymentProduct', e.target.value);\n                }\n            });\n\n            filters.append(\n                ...[\n                    title,\n                    components.TableFilter.create({\n                        name: 'integrationType',\n                        isMultiselect: true,\n                        label: translationService.translate('payments.filter.types.label'),\n                        values: activeFilters.integrationType || [],\n                        options: [\n                            {label: translationService.translate('payments.integrationType.hosted'), value: 'hosted'},\n                            {\n                                label: translationService.translate('payments.integrationType.redirect'),\n                                value: 'redirect'\n                            },\n                            {\n                                label: translationService.translate('payments.integrationType.tokenization'),\n                                value: 'tokenization'\n                            }\n                        ],\n                        selectPlaceholder: 'payments.filter.types.selectPlaceholder',\n                        onChange: (values) => changeFilter('integrationType', values)\n                    }),\n                    components.TableFilter.create({\n                        name: 'paymentGroups',\n                        isMultiselect: true,\n                        label: translationService.translate('payments.filter.paymentGroups.label'),\n                        values: activeFilters.paymentGroups || [],\n                        options: [\n                            {label: translationService.translate('payments.paymentGroups.mobile'), value: 'mobile'},\n                            {\n                                label: translationService.translate('payments.paymentGroups.realTimeBanking'),\n                                value: 'realTimeBanking'\n                            },\n                            {\n                                label: translationService.translate('payments.paymentGroups.giftCards'),\n                                value: 'giftCards'\n                            },\n                            {label: translationService.translate('payments.paymentGroups.prepaid'), value: 'prepaid'},\n                            {\n                                label: translationService.translate('payments.paymentGroups.instalment'),\n                                value: 'instalment'\n                            },\n                            {label: translationService.translate('payments.paymentGroups.cards'), value: 'cards'},\n                            {label: translationService.translate('payments.paymentGroups.eWallet'), value: 'eWallet'},\n                            {\n                                label: translationService.translate('payments.paymentGroups.postpaid'),\n                                value: 'postpaid'\n                            },\n                            {\n                                label: translationService.translate('payments.paymentGroups.directDebit'),\n                                value: 'directDebit'\n                            },\n                            {\n                                label: translationService.translate(WOP.brand.code + '.payments.paymentGroups.hosted'),\n                                value: 'hosted'\n                            },\n                        ],\n                        selectPlaceholder: 'payments.filter.paymentGroups.selectPlaceholder',\n                        onChange: (values) => changeFilter('paymentGroups', values)\n                    }),\n                    searchFiled,\n                    resetBtn\n                ]\n            );\n\n            return container;\n        };\n\n        /**\n         * Displays page content.\n         *\n         * @param {{ storeId: string }} config\n         */\n        this.display = ({storeId}) => {\n            configuration.getAvailablePaymentsUrl = configuration.getAvailablePaymentsUrl.replace('{storeId}', storeId);\n            configuration.enableMethodUrl = configuration.enableMethodUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.saveMethodConfigurationUrl = configuration.saveMethodConfigurationUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.getMethodConfigurationUrl = configuration.getMethodConfigurationUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            configuration.getLanguagesUrl = configuration.getLanguagesUrl.replace(\n                '{storeId}',\n                storeId\n            );\n            switchPage(renderActivePaymentsForm);\n        };\n\n        /**\n         * Sets the unsaved changes.\n         *\n         * @return {boolean}\n         */\n        this.hasUnsavedChanges = () => {\n            if (numberOfChanges > 0) {\n                return true;\n            }\n        };\n    }\n\n    WOP.PaymentsController = PaymentsController;\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/controllers/PaymentsController.js?");

/***/ }),

/***/ "./src/controllers/SettingsController.js":
/*!***********************************************!*\
  !*** ./src/controllers/SettingsController.js ***!
  \***********************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef PaymentStatus\n     *\n     * @property {string} label\n     * @property {string} value\n     */\n\n    /**\n     * @typedef ConnectionInfo\n     * @property {string} pspid\n     * @property {string} apiKey\n     * @property {string} apiSecret\n     * @property {string} webhooksKey\n     * @property {string} webhooksSecret\n     */\n\n    /**\n     * @typedef AccountSettings\n     *\n     * @property {'test' | 'live'} mode\n     * @property {ConnectionInfo?} sandboxData\n     * @property {ConnectionInfo?} liveData\n     */\n\n    /**\n     * @typedef PaymentSettings\n     *\n     * @property {'authorize' | 'authorize-capture'} paymentAction\n     * @property {-1 | 60 | 120 | 240 | 480 | 1440 | 2880 | 7200} automaticCapture\n     * @property {int} numberOfPaymentAttempts\n     * @property {boolean} applySurcharge\n     * @property {string} paymentCapturedStatus\n     * @property {string} paymentErrorStatus\n     * @property {string} paymentPendingStatus\n     * @property {string} paymentAuthorizedStatus\n     * @property {string} paymentCancelledStatus\n     * @property {string} paymentRefundedStatus\n     * @property {string} template\n     * @property {string} paymentPartiallyRefundedStatus\n     */\n\n    /**\n     * @typedef Restrictions\n     *\n     * @property {array} allowedOnlyFor\n     * @property {array} availableForCountries\n     * @property {array} availableFor\n     */\n\n    /**\n     * @typedef LogSettings\n     *\n     * @property {boolean} debugMode\n     * @property {int} logDays\n     */\n\n    /**\n     * @typedef PayByLinkSettings\n     *\n     * @property {boolean} enabled\n     * @property {string} title\n     * @property {int} expirationTime\n     */\n\n    /**\n     * @typedef GeneralSettings\n     *\n     * @property {AccountSettings} accountSettings\n     * @property {PaymentSettings} paymentSettings\n     * @property {Restrictions} restrictions\n     * @property {LogSettings} logSettings\n     * @property {PayByLinkSettings} payByLinkSettings\n     */\n\n    /**\n     * Handles settings page logic.\n     *\n     * @param {{\n     *  getGeneralSettingsUrl: string,\n     *  getPaymentStatusesUrl: string,\n     *  saveConnectionUrl: string,\n     *  savePaymentSettingsUrl: string,\n     *  saveLogSettingsUrl: string,\n     *  savePayByLinkSettingsUrl: string,\n     *  webhooksUrl: string\n     *  disconnectUrl: string\n     *  getRestrictionsUrl: string\n     *  saveRestrictionsUrl: string}}  configuration\n     * @constructor\n     */\n    function SettingsController(configuration) {\n        /** @type AjaxServiceType */\n        const api = WOP.ajaxService;\n\n        const translationService = WOP.translationService;\n\n        const {\n            templateService,\n            elementGenerator: generator,\n            validationService: validator,\n            components,\n            utilities\n        } = WOP;\n        /** @type string */\n        let currentStoreId = '';\n        /** @type HTMLElement | null */\n        let accountForm = null;\n        /** @type HTMLElement | null */\n        let paymentForm = null;\n        /** @type HTMLElement | null */\n        let restrictionsForm = null;\n        /** @type HTMLElement | null */\n        let logForm = null;\n        /** @type HTMLElement | null */\n        let payByLinkForm = null;\n        /** @type HTMLElement | null */\n        let disconnectForm = null;\n\n        /** @type AccountSettings */\n        let activeAccountSettings;\n        /** @type AccountSettings */\n        let changedAccountSettings;\n        /** @type PaymentSettings */\n        let activePaymentSettings;\n        /** @type PaymentSettings */\n        let changedPaymentSettings;\n        /** @type Restrictions */\n        let activeRestrictions;\n        /** @type Restrictions */\n        let changedRestrictions;\n        /** @type LogSettings */\n        let activeLogSettings;\n        /** @type LogSettings */\n        let changedLogSettings;\n        /** @type PayByLinkSettings */\n        let activePayByLinkSettings;\n        /** @type PayByLinkSettings */\n        let changedPayByLinkSettings;\n\n        /** @type PaymentStatus[] */\n        let paymentStatuses;\n\n        /**\n         * Displays page content.\n         *\n         * @param {{ state?: string, storeId: string }} config\n         */\n        this.display = ({storeId}) => {\n            currentStoreId = storeId;\n            templateService.clearMainPage();\n            [\n                'getGeneralSettingsUrl',\n                'getPaymentStatusesUrl',\n                'saveConnectionUrl',\n                'savePaymentSettingsUrl',\n                'saveLogSettingsUrl',\n                'savePayByLinkSettingsUrl',\n                'saveRestrictionsUrl',\n                'webhooksUrl',\n                'disconnectUrl'\n            ].forEach((prop) => {\n                configuration[prop] = configuration[prop].replace('{storeId}', storeId);\n            });\n\n            return renderPage();\n        };\n\n        /**\n         * Sets the unsaved changes.\n         *\n         * @return {boolean}\n         */\n        this.hasUnsavedChanges = () => false;\n\n        const scrollToTop = () => {\n            document.querySelector('#op-page > main')?.scrollTo({top: 0, left: 0, behavior: 'smooth'});\n        };\n\n        const renderPage = () => {\n            utilities.showLoader();\n\n            scrollToTop();\n            let url = configuration.getGeneralSettingsUrl;\n            let renderer = renderGeneralSettingsForm;\n\n            return api\n                .get(url, () => null)\n                .then(renderer)\n                .catch(renderer);\n        };\n\n        /**\n         * Renders the general settings form.\n         *\n         * @param {GeneralSettings} settings\n         */\n        const renderGeneralSettingsForm = (settings) => {\n            let url = configuration.getPaymentStatusesUrl;\n\n            api.get(url, () => null)\n                .then((response) => {\n                    paymentStatuses = response;\n\n                    activeAccountSettings = utilities.cloneObject(settings.accountSettings);\n                    activePaymentSettings = utilities.cloneObject(settings.paymentSettings);\n                    activeLogSettings = utilities.cloneObject(settings.logSettings);\n                    activePayByLinkSettings = utilities.cloneObject(settings.payByLinkSettings);\n                    activeRestrictions = utilities.cloneObject(settings.restrictions);\n\n                    changedAccountSettings = utilities.cloneObject(settings.accountSettings);\n                    changedPaymentSettings = utilities.cloneObject(settings.paymentSettings);\n                    changedLogSettings = utilities.cloneObject(settings.logSettings);\n                    changedPayByLinkSettings = utilities.cloneObject(settings.payByLinkSettings);\n                    changedRestrictions = utilities.cloneObject(settings.restrictions);\n\n                    if (changedPayByLinkSettings.title === '') {\n                        changedPayByLinkSettings.title = translationService.translate(WOP.brand.code + '.generalSettings.payByLinkSettings.default');\n                    }\n\n                    let restrictionsUrl = configuration.getRestrictionsUrl;\n\n                    api.get(restrictionsUrl, () => null)\n                        .then((response) => {\n                                let content = generator.createElement('div', 'op-settings-page');\n\n                                content.appendChild(renderAccountForm());\n                                content.appendChild(generator.createElement('div', 'op-divider'));\n                                content.appendChild(renderPaymentSettingsForm());\n                                content.appendChild(generator.createElement('div', 'op-divider'));\n                                content.appendChild(renderRestrictions(response));\n                                content.appendChild(generator.createElement('div', 'op-divider'));\n                                content.appendChild(renderLogForm());\n                                content.appendChild(generator.createElement('div', 'op-divider'));\n                                content.appendChild(renderPayByLinkForm());\n                                content.appendChild(generator.createElement('div', 'op-divider'));\n                                content.appendChild(renderDisconnectForm());\n\n                                templateService.getMainPage().appendChild(content);\n\n                                handlePayByLinkDependencies('enabled', activePayByLinkSettings.enabled);\n                            }\n                        );\n                })\n                .finally(() => {\n                        let header = templateService.getHeaderSection();\n                        let title = header.querySelector('.op-main-title');\n                        title.innerText = WOP.sanitize(translationService.translate('generalSettings.title'));\n                        utilities.hideLoader();\n                        WOP.state.setHeader();\n                        WOP.state.initializeFooter();\n                    }\n                );\n        };\n\n        const renderAccountForm = () => {\n            if (accountForm) {\n                templateService.clearComponent(accountForm);\n            }\n\n            let activeConnection = activeAccountSettings.liveData;\n            if (activeAccountSettings.mode === 'test') {\n                activeConnection = activeAccountSettings.sandboxData;\n            }\n\n            const webhookUrlDiv = generator.createElement(\n                'div',\n                'op-webhooks-url-wrapper'\n            );\n            const webhooksUrl = generator.createElement(\n                'span',\n                'op-webhooks-url',\n                WOP.state.formatUrl(configuration.webhooksUrl)\n            );\n            const webhookCopy = generator.createElement(\n                'span',\n                'op-webhooks-url-copy'\n            );\n            webhookCopy.addEventListener('click', function () {\n                navigator.clipboard.writeText(WOP.state.formatUrl(configuration.webhooksUrl));\n                utilities.createToasterMessage('general.copied');\n            });\n            webhookUrlDiv.appendChild(webhooksUrl);\n            webhookUrlDiv.appendChild(webhookCopy);\n            const webhooksUrlWrapper = generator.createFieldWrapper(\n                webhookUrlDiv,\n                'connection.webhooksUrl.title',\n                'connection.webhooksUrl.description'\n            );\n\n            const saveButton = generator.createButton({\n                type: 'primary',\n                name: 'saveAccountBtn',\n                disabled: true,\n                label: 'general.saveChanges',\n                onClick: () => {\n                    let mode = document.querySelector('[name=\"mode\"]'),\n                        apiKey = document.querySelector('[name=\"apiKey\"]'),\n                        pspid = document.querySelector('[name=\"pspid\"]'),\n                        apiSecret = document.querySelector('[name=\"apiSecret\"]'),\n                        webhooksKey = document.querySelector('[name=\"webhooksKey\"]'),\n                        webhooksSecret = document.querySelector('[name=\"webhooksSecret\"]');\n                    const isValid =\n                        validator.validateRequiredField(mode) &&\n                        validator.validateRequiredField(pspid, 'connection.pspid.error') &&\n                        validator.validateRequiredField(apiKey, 'connection.apiKey.error') &&\n                        validator.validateRequiredField(apiSecret, 'connection.apiSecret.error') &&\n                        validator.validateRequiredField(webhooksKey, 'connection.webhooksKey.error') &&\n                        validator.validateRequiredField(webhooksSecret, 'connection.webhooksSecret.error');\n\n                    if (isValid) {\n                        utilities.showLoader();\n                        api.post(\n                            configuration.saveConnectionUrl,\n                            {\n                                mode: changedAccountSettings.mode,\n                                testData: {\n                                    pspid: changedAccountSettings.sandboxData.pspid,\n                                    apiKey: changedAccountSettings.sandboxData.apiKey,\n                                    apiSecret: changedAccountSettings.sandboxData.apiSecret,\n                                    webhooksKey: changedAccountSettings.sandboxData.webhooksKey,\n                                    webhooksSecret: changedAccountSettings.sandboxData.webhooksSecret\n                                },\n                                liveData: {\n                                    pspid: changedAccountSettings.liveData.pspid,\n                                    apiKey: changedAccountSettings.liveData.apiKey,\n                                    apiSecret: changedAccountSettings.liveData.apiSecret,\n                                    webhooksKey: changedAccountSettings.liveData.webhooksKey,\n                                    webhooksSecret: changedAccountSettings.liveData.webhooksSecret\n                                }\n                            }\n                        )\n                            .then((response) => {\n                                if (response.errorMessage === undefined) {\n                                    handleSaveSuccess('accountSettings');\n\n                                    return;\n                                }\n\n                                handleSaveFailure('accountSettings');\n                            })\n                            .catch(() => {\n                                handleSaveFailure('accountSettings');\n                            })\n                            .finally(() => {\n                                utilities.hideLoader();\n                            });\n                    }\n                }\n            });\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n\n            buttonWrapper.append(saveButton);\n\n            accountForm = generator.createElement('div', 'op-card', '', null, [\n                generator.createElement('div', 'op-card-title', '', null, [\n                    generator.createElement(\n                        'h1',\n                        '',\n                        translationService.translate('generalSettings.accountSettings.title')\n                    ),\n                    generator.createElement(\n                        'p',\n                        '',\n                        translationService.translate(WOP.brand.code + '.generalSettings.accountSettings.description')\n                    )\n                ]),\n                generator.createElement('div', 'op-card-content', '', null, [\n                    generator.createDropdownField({\n                        name: 'mode',\n                        value: activeAccountSettings.mode || 'test',\n                        label: 'connection.mode.title',\n                        description: 'connection.mode.description',\n                        options: [\n                            {label: 'connection.mode.options.sandbox', value: 'test'},\n                            {label: 'connection.mode.options.live', value: 'live'}\n                        ],\n                        onChange: (value) => handleAccountSettingsChange('mode', value)\n                    }),\n                    generator.createTextField({\n                        name: 'pspid',\n                        value: activeConnection.pspid,\n                        label: 'connection.pspid.title',\n                        description: 'connection.pspid.description',\n                        error: 'connection.pspid.error',\n                        onChange: (value) => handleAccountSettingsChange('pspid', value)\n                    }),\n                    generator.createTextField({\n                        name: 'apiKey',\n                        value: activeConnection.apiKey,\n                        label: 'connection.apiKey.title',\n                        description: 'connection.apiKey.description',\n                        error: 'connection.apiKey.error',\n                        onChange: (value) => handleAccountSettingsChange('apiKey', value)\n                    }),\n                    generator.createPasswordField({\n                        name: 'apiSecret',\n                        value: activeConnection.apiSecret,\n                        label: 'connection.apiSecret.title',\n                        placeholder: translationService.translate(\n                            'connection.apiSecret.placeholder',\n                            [activeAccountSettings.mode || 'sandbox']\n                        ),\n                        description: 'connection.apiSecret.description',\n                        error: 'connection.apiSecret.error',\n                        onChange: (value) => handleAccountSettingsChange('apiSecret', value)\n                    }),\n                    generator.createTextField({\n                        name: 'webhooksKey',\n                        value: activeConnection.webhooksKey,\n                        label: 'connection.webhooksKey.title',\n                        placeholder: translationService.translate('connection.webhooksKey.placeholder'),\n                        description: 'connection.webhooksKey.description',\n                        error: 'connection.webhooksKey.error',\n                        onChange: (value) => handleAccountSettingsChange('webhooksKey', value)\n                    }),\n                    generator.createPasswordField({\n                        name: 'webhooksSecret',\n                        value: activeConnection.webhooksSecret,\n                        label: 'connection.webhooksSecret.title',\n                        placeholder: translationService.translate('connection.webhooksSecret.placeholder'),\n                        description: 'connection.webhooksSecret.description',\n                        error: 'connection.webhooksSecret.error',\n                        onChange: (value) => handleAccountSettingsChange('webhooksSecret', value)\n                    }),\n                    webhooksUrlWrapper,\n                    buttonWrapper\n                ])\n            ]);\n\n            return accountForm;\n        };\n\n        const handleAccountSettingsChange = (prop, value) => {\n            if (changedAccountSettings.mode === 'test') {\n                changedAccountSettings.sandboxData[prop] = WOP.sanitize(value);\n            } else {\n                changedAccountSettings.liveData[prop] = WOP.sanitize(value);\n            }\n\n            let apiKey = document.querySelector('[name=\"apiKey\"]'),\n                pspid = document.querySelector('[name=\"pspid\"]'),\n                apiSecret = document.querySelector('[name=\"apiSecret\"]'),\n                webhooksKey = document.querySelector('[name=\"webhooksKey\"]'),\n                webhooksSecret = document.querySelector('[name=\"webhooksSecret\"]'),\n                saveButton = document.querySelector('[name=\"saveAccountBtn\"]');\n\n            if (prop === 'mode') {\n                let key = value === 'test' ? 'sandboxData' : 'liveData';\n\n                apiKey.value = activeAccountSettings[key].apiKey;\n                pspid.value = activeAccountSettings[key].pspid;\n                apiSecret.value = activeAccountSettings[key].apiSecret;\n                webhooksKey.value = activeAccountSettings[key].webhooksKey;\n                webhooksSecret.value = activeAccountSettings[key].webhooksSecret;\n                changedAccountSettings.mode = value;\n            } else {\n                let field = document.querySelector('[name=\"' + prop + '\"]');\n\n                validator.validateRequiredField(field, 'connection.' + prop + '.error');\n            }\n\n            saveButton.disabled = (!pspid.value || !apiKey.value || !apiSecret.value || !webhooksKey.value\n                || !webhooksSecret.value) && changedAccountSettings !== activeAccountSettings;\n        }\n\n        const renderPaymentSettingsForm = () => {\n            if (paymentForm) {\n                templateService.clearComponent(paymentForm);\n            }\n\n            let statusOptions = [];\n\n            paymentStatuses.forEach(status => {\n                statusOptions.push({label: status.label, value: status.value});\n            })\n\n            let saveButton = generator.createButton({\n                    type: 'primary',\n                    name: 'paymentSettingsBtn',\n                    disabled: true,\n                    label: 'general.saveChanges',\n                    onClick: () => {\n                        let paymentAction = paymentForm.querySelector('[name=\"paymentAction\"]'),\n                            automaticCapture = paymentForm.querySelector('[name=\"automaticCapture\"]'),\n                            paymentCapturedStatus = paymentForm.querySelector('[name=\"paymentCapturedStatus\"]'),\n                            paymentErrorStatus = paymentForm.querySelector('[name=\"paymentErrorStatus\"]'),\n                            paymentPendingStatus = paymentForm.querySelector('[name=\"paymentPendingStatus\"]'),\n                            paymentAuthorizedStatus = paymentForm.querySelector('[name=\"paymentAuthorizedStatus\"]'),\n                            paymentCancelledStatus = paymentForm.querySelector('[name=\"paymentCancelledStatus\"]'),\n                            paymentRefundedStatus = paymentForm.querySelector('[name=\"paymentRefundedStatus\"]'),\n                            paymentPartiallyRefundedStatus = paymentForm.querySelector('[name=\"paymentPartiallyRefundedStatus\"]');\n\n                        let isValid =\n                            validator.validateRequiredField(paymentAction) &&\n                            validator.validateRequiredField(automaticCapture) &&\n                            validator.validateRequiredField(paymentCapturedStatus) &&\n                            validator.validateRequiredField(paymentErrorStatus) &&\n                            validator.validateRequiredField(paymentPendingStatus) &&\n                            validator.validateRequiredField(paymentAuthorizedStatus) &&\n                            validator.validateRequiredField(paymentCancelledStatus) &&\n                            validator.validateRequiredField(paymentRefundedStatus) &&\n                            validator.validateRequiredField(paymentPartiallyRefundedStatus);\n\n                        if (isValid) {\n                            utilities.showLoader();\n                            api.post(configuration.savePaymentSettingsUrl, changedPaymentSettings)\n                                .then(() => handleSaveSuccess('paymentSettings'))\n                                .catch(() => handleSaveFailure('paymentSettings'))\n                                .finally(() => {\n                                    utilities.hideLoader();\n                                });\n                        }\n                    }\n                }\n            );\n\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n            buttonWrapper.append(saveButton);\n\n            paymentForm = generator.createElement('div', 'op-card', '', null, [\n                    generator.createElement('div', 'op-card-title', '', null, [\n                        generator.createElement(\n                            'h1',\n                            '',\n                            translationService.translate('generalSettings.paymentSettings.title')\n                        ),\n                        generator.createElement(\n                            'p',\n                            '',\n                            translationService.translate('generalSettings.paymentSettings.description')\n                        )\n                    ]),\n                    generator.createElement('div', 'op-card-content', '', null, [\n                            generator.createDropdownField({\n                                name: 'paymentAction',\n                                value: activePaymentSettings.paymentAction || 'authorize-capture',\n                                label: 'generalSettings.paymentSettings.paymentAction.title',\n                                description: 'generalSettings.paymentSettings.paymentAction.description',\n                                options: [\n                                    {\n                                        label: 'generalSettings.paymentSettings.paymentAction.values.authorize',\n                                        value: 'FINAL_AUTHORIZATION'\n                                    },\n                                    {\n                                        label: 'generalSettings.paymentSettings.paymentAction.values.authorizeCapture',\n                                        value: 'SALE'\n                                    }\n                                ],\n                                onChange: (value) => handlePaymentsSettingsChange('paymentAction', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'automaticCapture',\n                                value: activePaymentSettings.automaticCapture || -1,\n                                label: 'generalSettings.paymentSettings.automaticCapture.title',\n                                description: 'generalSettings.paymentSettings.automaticCapture.description',\n                                options: [\n                                    {label: 'generalSettings.paymentSettings.automaticCapture.values.never', value: -1},\n                                    {label: 'generalSettings.paymentSettings.automaticCapture.values.oneHour', value: 60},\n                                    {label: 'generalSettings.paymentSettings.automaticCapture.values.twoHours', value: 120},\n                                    {\n                                        label: 'generalSettings.paymentSettings.automaticCapture.values.fourHours',\n                                        value: 240\n                                    },\n                                    {\n                                        label: 'generalSettings.paymentSettings.automaticCapture.values.eightHours',\n                                        value: 480\n                                    },\n                                    {label: 'generalSettings.paymentSettings.automaticCapture.values.oneDay', value: 1440},\n                                    {label: 'generalSettings.paymentSettings.automaticCapture.values.twoDays', value: 2880},\n                                    {\n                                        label: 'generalSettings.paymentSettings.automaticCapture.values.fiveDays',\n                                        value: 7200\n                                    },\n                                ],\n                                onChange: (value) => handlePaymentsSettingsChange('automaticCapture', value)\n                            }),\n                            generator.createTextField(\n                                {\n                                    name: 'template',\n                                    value: activePaymentSettings.template,\n                                    type: 'text',\n                                    label: 'payments.configure.fields.templateName.label',\n                                    description: 'payments.configure.fields.templateName.description',\n                                    onChange: (value) => handlePaymentsSettingsChange('template', value, false)\n                                }\n                            ),\n                            generator.createNumberField({\n                                name: 'numberOfPaymentAttempts',\n                                value: activePaymentSettings.numberOfPaymentAttempts || 10,\n                                label: 'generalSettings.paymentSettings.attemptNumber.title',\n                                description: 'generalSettings.paymentSettings.attemptNumber.description',\n                                onChange: (value) => handlePaymentsSettingsChange('numberOfPaymentAttempts', value)\n                            }),\n                            generator.createFormFields([\n                                {\n                                    name: 'applySurcharge',\n                                    value: activePaymentSettings.applySurcharge,\n                                    type: 'checkbox',\n                                    className: '',\n                                    label: `generalSettings.paymentSettings.applySurcharge.title`,\n                                    description: `generalSettings.paymentSettings.applySurcharge.description`,\n                                    onChange: (value) => handlePaymentsSettingsChange('applySurcharge', value)\n                                }\n                            ])[0],\n                            generator.createDropdownField({\n                                name: 'paymentCapturedStatus',\n                                value: activePaymentSettings.paymentCapturedStatus,\n                                label: 'generalSettings.paymentSettings.paymentCapturedStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentCapturedStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentCapturedStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentErrorStatus',\n                                value: activePaymentSettings.paymentErrorStatus,\n                                label: 'generalSettings.paymentSettings.paymentErrorStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentErrorStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentErrorStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentPendingStatus',\n                                value: activePaymentSettings.paymentPendingStatus,\n                                label: 'generalSettings.paymentSettings.paymentPendingStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentPendingStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentPendingStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentAuthorizedStatus',\n                                value: activePaymentSettings.paymentAuthorizedStatus,\n                                label: 'generalSettings.paymentSettings.paymentAuthorizedStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentAuthorizedStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentAuthorizedStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentCancelledStatus',\n                                value: activePaymentSettings.paymentCancelledStatus,\n                                label: 'generalSettings.paymentSettings.paymentCancelledStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentCancelledStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentCancelledStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentRefundedStatus',\n                                value: activePaymentSettings.paymentRefundedStatus,\n                                label: 'generalSettings.paymentSettings.paymentRefundedStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentRefundedStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentRefundedStatus', value)\n                            }),\n                            generator.createDropdownField({\n                                name: 'paymentPartiallyRefundedStatus',\n                                value: activePaymentSettings.paymentPartiallyRefundedStatus,\n                                label: 'generalSettings.paymentSettings.paymentPartiallyRefundedStatus.title',\n                                description: 'generalSettings.paymentSettings.paymentPartiallyRefundedStatus.description',\n                                options: statusOptions,\n                                onChange: (value) => handlePaymentsSettingsChange('paymentPartiallyRefundedStatus', value)\n                            }),\n                            buttonWrapper\n                        ]\n                    )\n                ]\n            );\n\n            return paymentForm;\n        }\n\n        const handlePaymentsSettingsChange = (prop, value) => {\n            let paymentSettingsBtn = paymentForm.querySelector('[name=\"paymentSettingsBtn\"]');\n\n            if (prop === 'numberOfPaymentAttempts') {\n                let numberOfAttempts = paymentForm.querySelector('[name=\"numberOfPaymentAttempts\"]');\n                if (value < 1 || value > 10) {\n                    validator.setError(numberOfAttempts, 'generalSettings.paymentSettings.attemptNumber.error');\n                    paymentSettingsBtn.disabled = true;\n\n                    return;\n                } else {\n                    validator.removeError(numberOfAttempts);\n                }\n            }\n\n            changedPaymentSettings[prop] = value;\n\n            paymentSettingsBtn.disabled = changedPaymentSettings.paymentAction === activePaymentSettings.paymentAction &&\n                changedPaymentSettings.numberOfPaymentAttempts === activePaymentSettings.numberOfPaymentAttempts &&\n                changedPaymentSettings.applySurcharge === activePaymentSettings.applySurcharge &&\n                changedPaymentSettings.automaticCapture === activePaymentSettings.automaticCapture &&\n                changedPaymentSettings.template === activePaymentSettings.template &&\n                changedPaymentSettings.paymentCapturedStatus === activePaymentSettings.paymentCapturedStatus &&\n                changedPaymentSettings.paymentErrorStatus === activePaymentSettings.paymentErrorStatus &&\n                changedPaymentSettings.paymentPendingStatus === activePaymentSettings.paymentPendingStatus &&\n                changedPaymentSettings.paymentAuthorizedStatus === activePaymentSettings.paymentAuthorizedStatus &&\n                changedPaymentSettings.paymentCancelledStatus === activePaymentSettings.paymentCancelledStatus &&\n                changedPaymentSettings.paymentRefundedStatus === activePaymentSettings.paymentRefundedStatus &&\n                changedPaymentSettings.paymentPartiallyRefundedStatus === activePaymentSettings.paymentPartiallyRefundedStatus;\n        }\n\n        const renderRestrictions = (response) => {\n            if (restrictionsForm) {\n                templateService.clearComponent(restrictionsForm);\n            }\n\n            let saveButton = generator.createButton({\n                type: 'primary',\n                name: 'restrictionsSettingsBtn',\n                disabled: true,\n                label: 'general.saveChanges',\n                onClick: () => {\n                    utilities.showLoader();\n                    api.post(configuration.saveRestrictionsUrl, changedRestrictions)\n                        .then((response) => {\n                            if (response.success) {\n                                handleSaveSuccess('restrictions');\n                            } else {\n                                handleSaveFailure('restrictions');\n                            }\n                        })\n                        .catch(() => handleSaveFailure('restrictions'))\n                        .finally(() => {\n                            utilities.hideLoader();\n                        });\n                }\n            });\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n            buttonWrapper.append(saveButton);\n\n            restrictionsForm = generator.createElement('div', 'op-card', '', null, [\n                generator.createElement('div', 'op-card-title', '', null, [\n                    generator.createElement(\n                        'h1',\n                        '',\n                        translationService.translate('generalSettings.restrictions.title')\n                    ),\n                    generator.createElement(\n                        'p',\n                        '',\n                        translationService.translate('generalSettings.restrictions.description')\n                    )\n                ]),\n                generator.createElement('div', 'op-card-content', '', null, [\n                    ...generator.createFormFields([\n                        {\n                            name: 'allowedOnlyFor',\n                            values: activeRestrictions.allowedOnlyFor,\n                            type: 'multiselect',\n                            className: '',\n                            label: `generalSettings.restrictions.allowedOnlyFor.title`,\n                            placeholder: '',\n                            options: response.allowedOnlyFor,\n                            onChange: (value) => handleRestrictionsChange('allowedOnlyFor', value),\n                            useAny: false\n                        },\n                        {\n                            name: 'availableCountries',\n                            values: activeRestrictions.availableForCountries?.length > 0\n                                ? activeRestrictions.availableForCountries\n                                : [''],\n                            type: 'multiselect',\n                            lockedValues: [''],\n                            className: '',\n                            label: `generalSettings.restrictions.availableForCountries.title`,\n                            placeholder: '',\n                            options: response.availableForCountries,\n                            onChange: (value) => {\n                                const newValue = value.includes('') ? value : ['', ...value];\n                                handleRestrictionsChange('availableForCountries', newValue);\n                            },\n                            useAny: false\n                        },\n                        {\n                            name: 'availableFor',\n                            values: activeRestrictions.availableFor,\n                            type: 'multiselect',\n                            className: '',\n                            label: `generalSettings.restrictions.availableFor.title`,\n                            placeholder: '',\n                            options: response.availableFor,\n                            onChange: (value) => handleRestrictionsChange('availableFor', value),\n                            useAny: false\n                        }\n                    ]),\n                    buttonWrapper\n                ])\n            ]);\n\n            return restrictionsForm;\n        }\n\n        const handleRestrictionsChange = (prop, value) => {\n            let restrictionsBtn = restrictionsForm.querySelector('[name=\"restrictionsSettingsBtn\"]');\n\n            changedRestrictions[prop] = value;\n\n            // Enable/disable save button based on whether there are changes\n            const hasChanges =\n                JSON.stringify(changedRestrictions.allowedOnlyFor) !== JSON.stringify(activeRestrictions.allowedOnlyFor) ||\n                JSON.stringify(changedRestrictions.availableForCountries) !== JSON.stringify(activeRestrictions.availableForCountries) ||\n                JSON.stringify(changedRestrictions.availableFor) !== JSON.stringify(activeRestrictions.availableFor);\n\n            restrictionsBtn.disabled = !hasChanges;\n        }\n\n        const renderLogForm = () => {\n            if (logForm) {\n                templateService.clearComponent(logForm);\n            }\n\n            let saveButton = generator.createButton({\n                    type: 'primary',\n                    name: 'logSettingsBtn',\n                    disabled: true,\n                    label: 'general.saveChanges',\n                    onClick: () => {\n                        let logDays = logForm.querySelector('[name=\"logDays\"]');\n\n                        let isValid = validator.validateRequiredField(logDays);\n\n                        if (isValid) {\n                            utilities.showLoader();\n                            api.post(configuration.saveLogSettingsUrl, changedLogSettings)\n                                .then(() => handleSaveSuccess('logSettings'))\n                                .catch(() => handleSaveFailure('logSettings'))\n                                .finally(() => {\n                                    utilities.hideLoader();\n                                });\n                        }\n                    }\n                }\n            );\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n            buttonWrapper.append(saveButton);\n\n            logForm = generator.createElement('div', 'op-card', '', null, [\n                    generator.createElement('div', 'op-card-title', '', null, [\n                        generator.createElement(\n                            'h1',\n                            '',\n                            translationService.translate('generalSettings.logSettings.title')\n                        ),\n                        generator.createElement(\n                            'p',\n                            '',\n                            translationService.translate('generalSettings.logSettings.description')\n                        )\n                    ]),\n                    generator.createElement('div', 'op-card-content', '', null, [\n                        ...generator.createFormFields([\n                                {\n                                    name: 'debugMode',\n                                    value: activeLogSettings.debugMode,\n                                    type: 'checkbox',\n                                    className: '',\n                                    label: `generalSettings.logSettings.debugMode.title`,\n                                    onChange: (value) => handleLogSettingsChange('debugMode', value)\n                                },\n                                {\n                                    name: 'logDays',\n                                    value: activeLogSettings.logDays,\n                                    type: 'number',\n                                    className: '',\n                                    label: `generalSettings.logSettings.logDays.title`,\n                                    description: `generalSettings.logSettings.logDays.description`,\n                                    onChange: (value) => handleLogSettingsChange('logDays', value)\n                                }\n                            ]\n                        ),\n                        buttonWrapper\n                    ])\n                ]\n            );\n\n            return logForm;\n        }\n\n        const renderPayByLinkForm = () => {\n            if (payByLinkForm) {\n                templateService.clearComponent(payByLinkForm);\n            }\n\n            let payByLinkBtn = generator.createButton({\n                type: 'primary',\n                name: 'payByLinkBtn',\n                disabled: true,\n                label: 'general.saveChanges',\n                onClick: () => {\n                    utilities.showLoader();\n                    api.post(configuration.savePayByLinkSettingsUrl, changedPayByLinkSettings)\n                        .then(() => handleSaveSuccess('payByLinkSettings'))\n                        .catch(() => handleSaveFailure('payByLinkSettings'))\n                        .finally(() => {\n                            utilities.hideLoader();\n                        });\n                }\n            });\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n            buttonWrapper.append(payByLinkBtn);\n\n            payByLinkForm = generator.createElement('div', 'op-card', '', null, [\n                    generator.createElement('div', 'op-card-title', '', null, [\n                        generator.createElement(\n                            'h1',\n                            '',\n                            translationService.translate('generalSettings.payByLinkSettings.title')\n                        ),\n                        generator.createElement(\n                            'p',\n                            '',\n                            translationService.translate('generalSettings.payByLinkSettings.description')\n                        )\n                    ]),\n                    generator.createElement('div', 'op-card-content', '', null, [\n                        ...generator.createFormFields([\n                                {\n                                    name: 'enabled',\n                                    value: activePayByLinkSettings.enabled,\n                                    type: 'checkbox',\n                                    className: '',\n                                    label: `generalSettings.payByLinkSettings.enable.title`,\n                                    description: WOP.brand.code + `.generalSettings.payByLinkSettings.enable.description`,\n                                    onChange: (value) => handlePayByLinkSettingsChange('enabled', value)\n                                },\n                                {\n                                    name: 'title',\n                                    value: activePayByLinkSettings.title !== '' ? activePayByLinkSettings.title\n                                        : translationService.translate(WOP.brand.code + '.generalSettings.payByLinkSettings.default'),\n                                    type: 'text',\n                                    className: '',\n                                    label: `generalSettings.payByLinkSettings.payByLinkTitle.title`,\n                                    description: `generalSettings.payByLinkSettings.payByLinkTitle.description`,\n                                    onChange: (value) => handlePayByLinkSettingsChange('title', value)\n                                },\n                                {\n                                    name: 'expirationTime',\n                                    value: activePayByLinkSettings.expirationTime,\n                                    type: 'number',\n                                    className: '',\n                                    label: `generalSettings.payByLinkSettings.expirationTime.title`,\n                                    description: `generalSettings.payByLinkSettings.expirationTime.description`,\n                                    onChange: (value) => handlePayByLinkSettingsChange('expirationTime', value)\n                                }\n                            ]\n                        ),\n                        buttonWrapper\n                    ])\n                ]\n            );\n\n            return payByLinkForm;\n        }\n\n        const handlePayByLinkSettingsChange = (prop, value) => {\n            let payByLinkBtn = payByLinkForm.querySelector('[name=\"payByLinkBtn\"]');\n            if (prop === 'expirationTime') {\n                let expirationTime = payByLinkForm.querySelector('[name=\"expirationTime\"]');\n                if (value < 0 || value > 180) {\n                    validator.setError(expirationTime, 'generalSettings.payByLinkSettings.expirationTime.error');\n                    payByLinkBtn.disabled = true;\n\n                    return;\n                } else {\n                    validator.removeError(expirationTime);\n                }\n            }\n\n            changedPayByLinkSettings[prop] = value;\n\n            handlePayByLinkDependencies(prop, value);\n\n            payByLinkBtn.disabled = changedPayByLinkSettings.enabled === activePayByLinkSettings.enabled &&\n                changedPayByLinkSettings.title === activePayByLinkSettings.title &&\n                changedPayByLinkSettings.expirationTime === activePayByLinkSettings.expirationTime;\n        }\n\n        const handlePayByLinkDependencies = (prop, value) => {\n            if (prop === 'enabled') {\n                let title = utilities.getAncestor(payByLinkForm.querySelector(\n                        '[name=\"title\"]'), 'op-field-wrapper'),\n                    expirationTime = utilities.getAncestor(\n                        payByLinkForm.querySelector('[name=\"expirationTime\"]'),\n                        'op-field-wrapper'\n                    );\n                if (value === true) {\n                    utilities.showElement(title);\n                    utilities.showElement(expirationTime);\n                } else {\n                    utilities.hideElement(title);\n                    utilities.hideElement(expirationTime);\n                }\n            }\n        }\n\n        const showDisconnectModal = () => {\n            showConfirmModal().then((confirmed) => confirmed && handleDisconnect());\n        }\n\n        const showConfirmModal = () => {\n            return new Promise((resolve) => {\n                const modal = components.Modal.create({\n                    title: `generalSettings.disconnect.disconnectModal.title`,\n                    className: `op-disconnect-modal`,\n                    content: [generator.createElement('p', '', `generalSettings.disconnect.disconnectModal.message`)],\n                    footer: true,\n                    buttons: [\n                        {\n                            type: 'secondary',\n                            label: 'general.cancel',\n                            onClick: () => {\n                                modal.close();\n                                resolve(false);\n                            }\n                        },\n                        {\n                            type: 'primary',\n                            className: 'opm--destructive',\n                            label: 'general.confirm',\n                            onClick: () => {\n                                modal.close();\n                                resolve(true);\n                            }\n                        }\n                    ]\n                });\n\n                modal.open();\n            });\n        }\n\n        function handleDisconnect() {\n            utilities.showLoader();\n            api.get(configuration.disconnectUrl).then((response) => {\n                    WOP.state.display();\n                }\n            )\n                .finally(() => {\n                    utilities.hideLoader();\n                });\n        }\n\n        const renderDisconnectForm = () => {\n            if (disconnectForm) {\n                templateService.clearComponent(disconnectForm);\n            }\n\n            let disconnectBtn = generator.createButton({\n                    type: 'primary',\n                    name: 'saveButton',\n                    className: 'opm--destructive',\n                    disabled: false,\n                    label: 'generalSettings.disconnect.disconnect',\n                    onClick: () => {\n                        showDisconnectModal();\n                    }\n                }\n            );\n            const buttonWrapper = generator.createElement('div', 'op-button-wrapper');\n            buttonWrapper.append(disconnectBtn);\n\n            disconnectForm = generator.createElement('div', 'op-card', '', null, [\n                generator.createElement('div', 'op-card-title', '', null, [\n                    generator.createElement(\n                        'h1',\n                        '',\n                        translationService.translate('generalSettings.disconnect.title')\n                    ),\n                    generator.createElement(\n                        'p',\n                        '',\n                        translationService.translate(WOP.brand.code + '.generalSettings.disconnect.description')\n                    )\n                ]),\n                generator.createElement('div', 'op-card-content', '', null, [\n                    generator.createElement(\n                        'p',\n                        '',\n                        translationService.translate('generalSettings.disconnect.warning')\n                    ),\n                    buttonWrapper\n                ])\n            ]);\n\n            return disconnectForm;\n        }\n\n        const handleLogSettingsChange = (prop, value) => {\n            let logBtn = logForm.querySelector('[name=\"logSettingsBtn\"]');\n            if (prop === 'logDays') {\n                let days = logForm.querySelector('[name=\"logDays\"]');\n                if (value < 1 || value > 14) {\n                    validator.setError(days, 'generalSettings.logSettings.logDays.error');\n                    logBtn.disabled = true;\n\n                    return;\n                } else {\n                    validator.removeError(days);\n                }\n            }\n\n            changedLogSettings[prop] = value;\n\n            logBtn.disabled = changedLogSettings.logDays === activeLogSettings.logDays &&\n                changedLogSettings.debugMode === activeLogSettings.debugMode;\n        }\n\n        const handleSaveSuccess = (section) => {\n            showFlashMessage('generalSettings.' + section + '.message', 'success');\n            templateService.clearMainPage();\n            renderPage().then(r => {\n            });\n        }\n\n        const handleSaveFailure = (section) => {\n            showFlashMessage('generalSettings.' + section + '.error', 'error');\n        }\n\n        /**\n         * Displays the flash message.\n         *\n         * @param {string} message Translation key or message\n         * @param {'success' | 'error'} status\n         */\n        const showFlashMessage = (message, status = 'success') => {\n            utilities.createToasterMessage(message, status);\n        };\n    }\n\n    WOP.SettingsController = SettingsController;\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/controllers/SettingsController.js?");

/***/ }),

/***/ "./src/controllers/StateController.js":
/*!********************************************!*\
  !*** ./src/controllers/StateController.js ***!
  \********************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef Store\n     * @property {string} storeId\n     * @property {string} storeName\n     */\n    /**\n     * @typedef Merchant\n     * @property {string} merchantId\n     * @property {string} merchantName\n     */\n\n    /**\n     * @typedef StateConfiguration\n     * @property {string?} pagePlaceholder\n     * @property {string} stateUrl\n     * @property {string} storesUrl\n     * @property {string} currentStoreUrl\n     * @property {string} connectionDetailsUrl\n     * @property {string} versionUrl\n     * @property {string} downloadVersionUrl\n     * @property {Object} brand\n     * @property {string?} systemId\n     * @property {Record<string, any>} pageConfiguration\n     * @property {Record<string, any>} templates\n     */\n\n    /**\n     * Main controller of the application.\n     *\n     * @param {StateConfiguration} configuration\n     *\n     * @constructor\n     */\n    function StateController(configuration) {\n        /** @type AjaxServiceType */\n        const api = WOP.ajaxService;\n\n        const {\n            pageControllerFactory,\n            utilities,\n            templateService,\n            elementGenerator,\n            translationService\n        } = WOP;\n\n        let currentState = '';\n        let previousState = '';\n        let controller = null;\n\n        /**\n         * Main entry point for the application.\n         * Determines the current state and runs the start controller.\n         */\n        this.display = () => {\n            utilities.showLoader();\n            templateService.setTemplates(configuration.templates || {});\n\n            window.addEventListener('hashchange', updateStateOnHashChange, false);\n\n            displayPageBasedOnState().catch(() => {\n                initializeHeader(configuration.brand.code);\n                this.initializeFooter();\n                this.disableHeaderTabs();\n                return this.setHeader();\n            }).finally(() => {\n                utilities.hideLoader();\n            })\n        };\n\n        /**\n         * Navigates to a state.\n         *\n         * @param {string} state\n         * @param {Record<string, any> | null?} additionalConfig\n         * @param {boolean} [force=false]\n         */\n        this.goToState = (state, additionalConfig = null, force = false) => {\n            if (currentState === state && !force) {\n                return;\n            }\n\n            window.location.hash = state;\n\n            const config = {\n                storeId: this.getStoreId(),\n                ...(additionalConfig || {})\n            };\n\n            const [controllerName, page, stateParam] = state.split('-');\n            controller = pageControllerFactory.getInstance(\n                controllerName,\n                getControllerConfiguration(controllerName, page, stateParam)\n            );\n\n            if (controller) {\n                controller.display(config);\n            }\n\n            previousState = currentState;\n            currentState = state;\n        };\n\n        /**\n         * Enables the header tabs.\n         */\n        this.enableHeaderTabs = () => {\n            document\n                .querySelectorAll('.op-main-header-right .op-header-tab')\n                .forEach((item) => item.classList.remove('ops--disabled'));\n        };\n\n        /**\n         * Disables the header tabs.\n         */\n        this.disableHeaderTabs = () => {\n            document\n                .querySelectorAll('.op-main-header-right .op-header-tab')\n                .forEach((item) => item.classList.add('ops--disabled'));\n        };\n\n        /**\n         * Updates the main header.\n         *\n         * @returns {Promise<void>}\n         */\n        this.setHeader = () => {\n            return setConnectionData();\n        };\n\n        const updateStateOnHashChange = () => {\n            const state = window.location.hash.substring(1);\n            if (state) {\n                this.goToState(state);\n                updateHeaderTabs();\n            }\n\n            getHeader().classList.remove('ops--menu-active');\n        };\n\n        /**\n         * Selects active header tab based on the location hash.\n         */\n        const updateHeaderTabs = () => {\n            const sidebar = getHeader();\n            sidebar.querySelectorAll('.opp-menu-item a').forEach((el) => el.classList.remove('ops--active'));\n            sidebar.querySelector(`[href=\"${location.hash}\"]`)?.classList.add('ops--active');\n        };\n\n        /**\n         * Gets the header DOM element.\n         *\n         * @returns {HTMLElement}\n         */\n        const getHeader = () => {\n            return document.querySelector('#op-page #op-main-header');\n        };\n\n        /**\n         * Renders a confirmation modal for a store change when there are unsaved changes.\n         */\n        const renderSwitchToStoreModal = () => {\n            return new Promise((resolve) => {\n                const modal = WOP.components.Modal.create({\n                    title: 'payments.switchToStore.title',\n                    content: [\n                        WOP.elementGenerator.createElement(\n                            'span',\n                            '',\n                            'payments.switchToStore.description'\n                        )\n                    ],\n                    footer: true,\n                    canClose: false,\n                    buttons: [\n                        {\n                            type: 'secondary',\n                            label: 'general.back',\n                            onClick: () => {\n                                modal.close();\n                                resolve(false);\n                            }\n                        },\n                        {\n                            type: 'primary',\n                            className: 'opt--primary',\n                            label: 'general.yes',\n                            onClick: () => {\n                                modal.close();\n                                resolve(true);\n                            }\n                        }\n                    ]\n                });\n\n                modal.open();\n            });\n        };\n\n        /**\n         * Updated the connection data in the main header.\n         *\n         * @returns {Promise<any>}\n         */\n        const setConnectionData = () => {\n            return api\n                .get(configuration.connectionDetailsUrl.replace('{storeId}', this.getStoreId()), () => null, true)\n                .then(\n                    /** @param {Connection} connection */\n                    (connection) => {\n                        if (connection.mode === undefined) {\n                            return;\n                        }\n\n                        const modeElements = document.querySelectorAll('.op-status');\n\n                        modeElements.forEach((modeElem) => {\n                            const stateElem = modeElem.querySelector('.op-mode');\n\n                            if (stateElem) {\n                                modeElem.removeChild(stateElem);\n                            }\n\n                            modeElem.insertBefore(elementGenerator.createModeElement(connection.mode), modeElem.firstChild);\n                        });\n                    }\n                );\n        };\n\n        /**\n         * Initializes the header.\n         */\n        const initializeHeader = (brand, state) => {\n            let existingHeader = getHeader();\n\n            if (existingHeader) {\n                templateService.clearComponent(existingHeader);\n            }\n\n            let name = translationService.translate('general.documentation');\n            let options = [\n                {\n                    label: 'general.readyToGoLive',\n                    link: translationService.translate(WOP.brand.code + '.links.readyToGoLive')\n                },\n                {\n                    label: 'general.createAccount',\n                    link: translationService.translate(WOP.brand.code + '.links.createAccount')\n                },\n                {\n                    label: 'general.configurePlugin',\n                    link: translationService.translate(WOP.brand.code + '.links.configurePlugin')\n                },\n                {\n                    label: 'general.generalDocumentation',\n                    link: translationService.translate(WOP.brand.code + '.links.generalDocumentation')\n                }\n            ];\n            const header = elementGenerator.createHeaderItem(brand, {name, options}, state);\n            let headerPlaceholder = document.querySelector('#op-main-header');\n            headerPlaceholder.appendChild(header);\n\n            updateHeaderTabs();\n        };\n\n        this.initializeFooter = () => {\n            api.get(configuration.versionUrl, null, true)\n                .then((version) => {\n                    let existingNeedHelp = document.querySelector('.op-need-help');\n\n                    if (existingNeedHelp) {\n                        existingNeedHelp.remove();\n                    }\n\n                    let needHelp = elementGenerator.createElement('span', 'op-need-help', 'general.needHelp');\n                    needHelp.addEventListener('click', () => {\n                        window.open(translationService.translate('general.helpLink'), '_blank');\n                    });\n                    templateService.getMainPage().appendChild(needHelp);\n\n                    const footer = WOP.components.Footer.create({\n                        newVersion: version.latest,\n                        installedVersion: version.installed\n                    });\n\n                    const footerPlaceholder = document.querySelector('#op-footer');\n\n                    templateService.clearComponent(footerPlaceholder);\n                    footerPlaceholder.appendChild(footer);\n                });\n        };\n\n        /**\n         * Returns the current merchant state.\n         *\n         * @return {Promise<\"connection\" | \"dashboard\">}\n         */\n        this.getCurrentMerchantState = () => {\n            return api\n                .get(configuration.stateUrl.replace('{storeId}', this.getStoreId()), () => {\n                })\n                .then((response) => response?.state || 'connection');\n        };\n\n        /**\n         * Opens a specific page based on the current state.\n         */\n        const displayPageBasedOnState = () => {\n            return this.getCurrentMerchantState().then((state) => {\n                // if user is logged in, go to payments\n                switch (state) {\n                    case 'connection':\n                        initializeHeader(configuration.brand.code, state);\n                        this.disableHeaderTabs();\n                        this.setHeader();\n                        this.goToState('connection', null, true);\n                        this.initializeFooter();\n\n                        break;\n                    default:\n                        initializeHeader(configuration.brand.code, state);\n                        let hash = window.location.hash.substring(1);\n                        let goTo = 'payments';\n\n                        if (hash && hash !== 'connection') {\n                            goTo = hash;\n                        }\n\n                        this.goToState(goTo, null, true);\n                        this.setHeader();\n                        this.initializeFooter();\n                        break;\n                }\n            });\n        };\n\n        /**\n         * Gets controller configuration.\n         *\n         * @param {string} controllerName\n         * @param {string?} page\n         * @param {string?} stateParam\n         * @return {Record<string, any>}}\n         */\n        const getControllerConfiguration = (controllerName, page, stateParam) => {\n            let config = utilities.cloneObject(configuration.pageConfiguration[controllerName] || {});\n\n            page && (config.page = page);\n            stateParam && (config.stateParam = stateParam);\n\n            return config;\n        };\n\n        /**\n         * Sets the store ID.\n         *\n         * @param {string} storeId\n         */\n        this.setStoreId = (storeId) => {\n            sessionStorage.setItem('op-active-store-id', storeId);\n        };\n\n        /**\n         * Gets the store ID.\n         *\n         * @returns {string}\n         */\n        this.getStoreId = () => {\n            return sessionStorage.getItem('op-active-store-id');\n        };\n\n        /**\n         * Replaces storeId in the url.\n         *\n         * @param {string} url\n         * @returns {string}\n         */\n        this.formatUrl = (url) => {\n            return url.replace('{storeId}', this.getStoreId());\n        }\n    }\n\n    WOP.StateController = StateController;\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/controllers/StateController.js?");

/***/ }),

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

eval("__webpack_require__(/*! ./services/AjaxService */ \"./src/services/AjaxService.js\");\n__webpack_require__(/*! ./services/ResponseService */ \"./src/services/ResponseService.js\");\n__webpack_require__(/*! ./services/TranslationService */ \"./src/services/TranslationService.js\");\n__webpack_require__(/*! ./services/TemplateService */ \"./src/services/TemplateService.js\");\n__webpack_require__(/*! ./services/UtilityService */ \"./src/services/UtilityService.js\");\n__webpack_require__(/*! ./services/ValidationService */ \"./src/services/ValidationService.js\");\n__webpack_require__(/*! ./services/ElementGenerator */ \"./src/services/ElementGenerator.js\");\n__webpack_require__(/*! ./services/PageControllerFactory */ \"./src/services/PageControllerFactory.js\");\n__webpack_require__(/*! ./services/Sanitizer */ \"./src/services/Sanitizer.js\");\n\n__webpack_require__(/*! ./components/data-table/DataTableComponent */ \"./src/components/data-table/DataTableComponent.js\");\n__webpack_require__(/*! ./components/dropdown/DropdownComponent */ \"./src/components/dropdown/DropdownComponent.js\");\n__webpack_require__(/*! ./components/header-menu/HeaderMenu */ \"./src/components/header-menu/HeaderMenu.js\");\n__webpack_require__(/*! ./components/multiselect-dropdown/MultiselectDropdownComponent */ \"./src/components/multiselect-dropdown/MultiselectDropdownComponent.js\");\n__webpack_require__(/*! ./components/modal/ModalComponent */ \"./src/components/modal/ModalComponent.js\");\n__webpack_require__(/*! ./components/table-filter/TableFilterComponent */ \"./src/components/table-filter/TableFilterComponent.js\");\n__webpack_require__(/*! ./components/header/Header */ \"./src/components/header/Header.js\");\n__webpack_require__(/*! ./components/footer/Footer */ \"./src/components/footer/Footer.js\");\n__webpack_require__(/*! ./components/link-dropdown/LinkDropDownComponent */ \"./src/components/link-dropdown/LinkDropDownComponent.js\");\n__webpack_require__(/*! ./components/sliding-modal/SlidingModal */ \"./src/components/sliding-modal/SlidingModal.js\");\n__webpack_require__(/*! ./components/translatable-label/TranslatableLabel */ \"./src/components/translatable-label/TranslatableLabel.js\");\n\n__webpack_require__(/*! ./controllers/StateController */ \"./src/controllers/StateController.js\");\n__webpack_require__(/*! ./controllers/ConnectionController */ \"./src/controllers/ConnectionController.js\");\n__webpack_require__(/*! ./controllers/MonitoringController */ \"./src/controllers/MonitoringController.js\");\n__webpack_require__(/*! ./controllers/PaymentsController */ \"./src/controllers/PaymentsController.js\");\n__webpack_require__(/*! ./controllers/SettingsController */ \"./src/controllers/SettingsController.js\");\n\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/index.js?");

/***/ }),

/***/ "./src/services/AjaxService.js":
/*!*************************************!*\
  !*** ./src/services/AjaxService.js ***!
  \*************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n/**\n * @typedef AjaxServiceType\n * @property {(url:string, errorCallback?: (error?: Record<string, any>) => Promise<any> | any, fallthrough?:\n *     boolean) => Promise<any>} get\n * @property {(url:string, data?: any, customHeader?: Record<string, string>, errorCallback: (error?:\n *     Record<string, any>) => Promise<void>) => Promise<any>} post\n * @property {(url:string, data?: any, customHeader?: Record<string, string>, errorCallback: (error?:\n *     Record<string, any>) => Promise<void>) => Promise<any>} put\n * @property {(url:string, data?: any, errorCallback?: (error?: Record<string, any>) => Promise<void>) =>\n *     Promise<any>} delete\n */\n(function () {\n    /**\n     * Ajax/API service.\n     *\n     * @returns {AjaxServiceType}\n     */\n    const AjaxService = () => {\n        let callValidationState = '';\n\n        /**\n         * Handles the server response.\n         * @param {Response} response\n         * @param {(error: Record<string, any>) => Promise<void>?} errorCallback\n         * @returns {Record<string, any>}\n         */\n        const handleResponse = (response, errorCallback) => {\n            if (!errorCallback) {\n                errorCallback = WOP.responseService.errorHandler;\n            }\n\n            try {\n                if (response.ok) {\n                    return response.json();\n                }\n\n                if (response.status === 401) {\n                    // reset the state so all requests should become obsolete\n                    callValidationState = Math.random().toString(36);\n\n                    return response.json().then(WOP.responseService.unauthorizedHandler).catch(errorCallback);\n                }\n\n                if (response.status === 400) {\n                    return response.json().then(errorCallback);\n                }\n            } catch (e) {}\n\n            // Every branch of this function must return a thenable, because the caller chains .then()\n            // on the result. Error callbacks commonly return null (see the `() => null` handlers in the\n            // controllers), so a status that is neither ok, 401 nor 400 - a 429 from the rate limiter,\n            // or any 403/404/500 - used to return null here and throw\n            // \"can't access property then, handleResponse(...) is null\", leaving the page on a spinner\n            // that never clears instead of surfacing the error.\n            return Promise.resolve(errorCallback({ status: response.status, error: response.statusMessage }));\n        };\n\n        /**\n         * Performs GET ajax request.\n         *\n         * @param {string} url The URL to call.\n         * @param {(error: Record<string, any>) => Promise<void>?} errorCallback\n         * @param {boolean?} [fallthrough=false]\n         * @returns {Promise<any>}\n         */\n        const get = (url, errorCallback, fallthrough = false) =>\n            call({\n                method: 'GET',\n                url,\n                errorCallback,\n                fallthrough\n            });\n\n        /**\n         * Performs POST ajax request.\n         *\n         * @param {string} url The URL to call.\n         * @param {Record<string, any>?} data\n         * @param {Record<string, string>?} customHeader\n         * @param {(error: Record<string, any>) => Promise<void>?} errorCallback\n         */\n        const post = (url, data, customHeader, errorCallback) =>\n            call({\n                method: 'POST',\n                url,\n                data,\n                errorCallback,\n                customHeader\n            });\n\n        /**\n         * Performs PUT ajax request.\n         *\n         * @param {string} url The URL to call.\n         * @param {Record<string, any>} data\n         * @param {Record<string, string>?} customHeader\n         * @param {(error: Record<string, any>) => Promise<void>?} errorCallback\n         */\n        const put = (url, data, customHeader, errorCallback) =>\n            call({\n                method: 'PUT',\n                url,\n                data,\n                errorCallback,\n                customHeader\n            });\n\n        /**\n         * Performs DELETE ajax request.\n         *\n         * @param {string} url The URL to call.\n         * @param {Record<string, any>?} data\n         * @param {(error: Record<string, any>) => Promise<void>?} errorCallback\n         */\n        const del = (url, data, errorCallback) =>\n            call({\n                method: 'DELETE',\n                url,\n                data,\n                errorCallback\n            });\n\n        /**\n         * Performs ajax call.\n         *\n         * @param {'GET' | 'POST' | 'PUT' | 'DELETE'} method The HTTP method.\n         * @param {string} url The URL to call.\n         * @param {Record<string, any>?} data The data to send.\n         * @param {(error: Record<string, any>) => Promise<any>?} errorCallback An error callback. If not set, the\n         *     default one will be used.\n         * @param {Record<string, string>?} customHeader\n         * @param {boolean} fallthrough Indicates whether the request should not be cancelled on generic cancel call.\n         *\n         * @returns {Promise<Record<string, any>>}\n         */\n        const call = ({ method, url, data, errorCallback, customHeader, fallthrough = false }) => {\n            const callState = callValidationState;\n\n            return new Promise((resolve, reject) => {\n                url = url.replace('https:', '');\n                url = url.replace('http:', '');\n\n                const headers = {\n                    'Content-Type': 'application/json',\n                    ...(customHeader || {})\n                };\n\n                if (headers['Content-Type'] === 'multipart/form-data') {\n                    delete headers['Content-Type'];\n                }\n\n                const body = data\n                    ? headers['Content-Type'] === 'application/json'\n                        ? JSON.stringify(data)\n                        : data\n                    : undefined;\n\n                fetch(url, { method, headers, body }).then((response) => {\n                    if (!fallthrough && callState !== callValidationState) {\n                        // Obsolete request. Some call cancelled all other requests.\n                        console.debug('cancelling an obsolete request', url);\n                        reject({ errorCode: 0 });\n                    } else {\n                        handleResponse(response, errorCallback).then(resolve).catch(reject);\n                    }\n                });\n            });\n        };\n\n        return {\n            get,\n            post,\n            put,\n            delete: del\n        };\n    };\n\n    WOP.ajaxService = AjaxService();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/AjaxService.js?");

/***/ }),

/***/ "./src/services/ElementGenerator.js":
/*!******************************************!*\
  !*** ./src/services/ElementGenerator.js ***!
  \******************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef Option\n     * @property {string?} label\n     * @property {any} value\n     */\n\n    /**\n     * @typedef {Object.<string, *>} ElementProps\n     * @property {string?} name\n     * @property {any?} value\n     * @property {string?} className\n     * @property {string?} placeholder\n     * @property {(value: any) => any?} onChange\n     * @property {string?} label\n     * @property {string?} description\n     * @property {string?} error\n     */\n\n    /**\n     * @typedef {ElementProps} FormField\n     * @property {'text' | 'number' | 'radio' |'dropdown' | 'checkbox' | 'file' | 'multiselect' | 'button' |\n     *     'buttonLink'} type\n     */\n\n    const translationService = WOP.translationService;\n\n    /**\n     * Prevents default event handling.\n     * @param {Event} e\n     */\n    const preventDefaults = (e) => {\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    /**\n     * Creates a generic HTML node element and assigns provided class and inner text.\n     *\n     * @param {keyof HTMLElementTagNameMap} type Represents the name of the tag\n     * @param {string?} className CSS class\n     * @param {string?} innerHTMLKey Inner text translation key.\n     * @param {Record<string, any>?} properties An object of additional properties.\n     * @param {HTMLElement[]?} children\n     * @param {boolean} allowHtml\n     * @param {boolean} shouldSplit\n     * @returns {HTMLElement}\n     */\n    const createElement = (type, className, innerHTMLKey, properties, children, allowHtml = false, shouldSplit = true) => {\n        const child = document.createElement(type);\n        className && child.classList.add(...className.trim().split(' '));\n        if (innerHTMLKey) {\n            let params = innerHTMLKey.split('|');\n            if (!shouldSplit) {\n                params = [innerHTMLKey];\n            }\n\n            if (allowHtml) {\n                child.innerHTML = WOP.sanitize(translationService.translate(params[0], params.slice(1)));\n            } else {\n                child.innerText = WOP.sanitize(translationService.translate(params[0], params.slice(1)));\n            }\n        }\n\n        if (properties) {\n            if (properties.dataset) {\n                Object.assign(child.dataset, properties.dataset);\n                delete properties.dataset;\n            }\n\n            Object.assign(child, properties);\n            if (properties.onChange) {\n                child.addEventListener('change', properties.onChange, false);\n            }\n\n            if (properties.onClick) {\n                child.addEventListener('click', properties.onClick, false);\n            }\n        }\n\n        if (children) {\n            child.append(...children);\n        }\n\n        return child;\n    };\n\n    /**\n     * Creates an element out of provided HTML markup.\n     *\n     * @param {string} html\n     * @returns {HTMLElement}\n     */\n    const createElementFromHTML = (html) => {\n        const element = document.createElement('div');\n        element.innerHTML = html;\n\n        return element.firstElementChild;\n    };\n\n    /**\n     * Creates a button.\n     *\n     * @param {{ label?: string, type?: 'primary' | 'secondary' | 'ghost', size?: 'small' | 'medium', className?:\n     *     string, [key: string]: any, onClick?: () => void}} props\n     * @return {HTMLButtonElement}\n     */\n    const createButton = ({ type, size, className, onClick, label, ...properties }) => {\n        const cssClass = ['op-button'];\n        type && cssClass.push('opt--' + type);\n        size && cssClass.push('opm--' + size);\n        className && cssClass.push(className);\n\n        const button = createElement('button', cssClass.join(' '), '', { type: 'button', ...properties }, [\n            createElement('span', '', label)\n        ]);\n\n        onClick &&\n        button.addEventListener(\n            'click',\n            (event) => {\n                preventDefaults(event);\n                onClick();\n            },\n            false\n        );\n\n        return button;\n    };\n\n    /**\n     * Creates a link that looks like a button.\n     *\n     * @param {{text?: string, className?: string, href: string, useDownload?: boolean, downloadFile?: string}} props\n     * @return {HTMLLinkElement}\n     */\n    const createButtonLink = ({ text, className = '', href, useDownload, downloadFile }) => {\n        const link = createElement('a', className, `<span>${text}</span>`, { href: href, target: '_blank' });\n        if (useDownload) {\n            link.setAttribute('download', downloadFile);\n        }\n\n        return link;\n    };\n\n    /**\n     * Creates an input field wrapper around the provided input element.\n     *\n     * @param {HTMLElement} input The input element.\n     * @param {string?} label Label translation key.\n     * @param {string?} description Description translation key.\n     * @param {string?} error Error translation key.\n     * @return {HTMLDivElement}\n     */\n    const createFieldWrapper = (input, label, description, error) => {\n        const field = createElement('div', 'op-field-wrapper');\n        let titleWrapper;\n        if (label) {\n            titleWrapper = createElement('div', 'op-field-title-wrapper');\n            titleWrapper.appendChild(createElement('h3', 'opp-field-title', label));\n            field.appendChild(titleWrapper);\n        }\n\n        if (description && translationService.translate(description) !== '') {\n            if (titleWrapper !== undefined) {\n                titleWrapper.appendChild(createHint('', description, 'right',''));\n                field.appendChild(titleWrapper);\n            } else {\n                field.appendChild(createHint('', description, 'right',''));\n            }\n        }\n\n        field.appendChild(input);\n\n        if (error) {\n            field.appendChild(createElement('span', 'opp-input-error', error));\n        }\n\n        return field;\n    };\n\n    /**\n     * Creates store switcher.\n     *\n     * @param {{value: string, label: string}[]} options\n     * @param {string?} name\n     * @param {string?} title\n     * @param {string?} value\n     * @param {(value: string) => Promise<boolean>?} onBeforeChange\n     * @param {(value: string) => void?} onChange\n     * @param {boolean?} updateTextOnChange\n     * @return {HTMLDivElement}\n     */\n    const createStoreSwitcher = (options, name, value, onBeforeChange, onChange, updateTextOnChange = true) => {\n        const hiddenInput = createElement('input', 'opp-hidden-input', '', { type: 'hidden', name, value });\n        const wrapper = createElement('div', 'op-store-selector');\n        const list = createElement('ul', 'opp-dropdown-list');\n        const switchButton = createElement('button', 'opp-dropdown-button opp-field-component', '', {\n            type: 'button'\n        });\n        const selectedItem = options.find((option) => option.value === value) || options[0];\n        const buttonSpan = createElement('span', '', selectedItem.label);\n\n        switchButton.append(buttonSpan);\n        const listItems = [];\n\n        const handleOnOptionChange = (listItem, storeId) => {\n            hiddenInput.value = storeId;\n            updateTextOnChange && (switchButton.firstElementChild.innerHTML = WOP.sanitize(listItem.innerText));\n            list.classList.remove('ops--show');\n\n            listItems.forEach((li) => li.classList.remove('ops--selected'));\n            listItem.classList.add('ops--selected');\n            onChange && onChange(storeId);\n        };\n\n        options.forEach((option) => {\n            const listItem = createElement('li', 'opp-store', option.label);\n            listItems.push(listItem);\n            list.append(listItem);\n            if (option.value === selectedItem.value) {\n                listItem.classList.add('ops--selected');\n            }\n\n            listItem.addEventListener('click', () => {\n                if (option.value === hiddenInput.value) {\n                    list.classList.remove('ops--show');\n                    return;\n                }\n\n                if (!onBeforeChange) {\n                    handleOnOptionChange(listItem, WOP.sanitize(option.value));\n                } else {\n                    onBeforeChange(WOP.sanitize(option.value)).then((resume) => {\n                        if (resume) {\n                            handleOnOptionChange(listItem, WOP.sanitize(option.value));\n                        } else {\n                            list.classList.remove('ops--show');\n                        }\n                    });\n                }\n            });\n        });\n\n        switchButton.addEventListener('click', (event) => {\n            preventDefaults(event);\n            list.classList.toggle('ops--show');\n        });\n\n        document.documentElement.addEventListener('click', () => {\n            list.classList.remove('ops--show');\n        });\n\n        wrapper.append(hiddenInput, switchButton, list);\n\n        return wrapper;\n    };\n\n    /**\n     * @param {string} mode\n     * @return {HTMLDivElement}\n     */\n    const createModeElement = (mode) => {\n        const modeDiv = createElement('div', 'op-mode');\n        const indicator = createElement('span', 'op-icon');\n\n        if (mode === 'test') {\n            indicator.classList.add('op-sandbox');\n        } else {\n            indicator.classList.add('op-live');\n        }\n\n        const modeText = createElement('p', 'op-mode-text', 'general.mode.' + mode);\n        modeDiv.appendChild(indicator);\n        modeDiv.appendChild(modeText);\n\n        return modeDiv;\n    };\n\n    /**\n     * Creates dropdown wrapper around the provided dropdown element.\n     *\n     * @param {ElementProps & DropdownComponentModel} props The properties.\n     * @return {HTMLDivElement}\n     */\n    const createDropdownField = ({ label, description, error, ...dropdownProps }) => {\n        return createFieldWrapper(WOP.components.Dropdown.create(dropdownProps), label, description, error);\n    };\n\n    /**\n     * Creates dropdown wrapper around the provided dropdown element.\n     *\n     * @param {(ElementProps & MultiselectDropdownComponentModel)} props The properties.\n     * @return {HTMLDivElement}\n     */\n    const createMultiselectDropdownField = ({ label, description, error, ...dropdownProps }) => {\n        return createFieldWrapper(\n            WOP.components.MultiselectDropdown.create(dropdownProps),\n            label,\n            description,\n            error\n        );\n    };\n\n    /**\n     * Creates dropdown with links.\n     *\n     * @param options\n     * @param name\n     * @param className\n     *\n     * @returns {HTMLElement}\n     */\n    const createLinkDropdownField = ({options, name, className}) => {\n        return WOP.components.LinkDropDownComponent.create({options, name, className});\n    }\n\n    /**\n     * Creates a password input field.\n     *\n     * @param {ElementProps} props The properties.\n     * @return {HTMLElement}\n     */\n    const createPasswordField = ({ className = '', label, description, error, onChange, ...rest }) => {\n        const wrapper = createElement('div', `op-password ${className}`);\n        const input = createElement('input', 'opp-field-component', '', { type: 'password', ...rest });\n        onChange && input.addEventListener('change', (event) => onChange(WOP.sanitize(event.currentTarget?.value)));\n\n        wrapper.append(input);\n\n        return createFieldWrapper(wrapper, label, description, error);\n    };\n\n    /**\n     * Creates a text input field.\n     *\n     * @param {ElementProps & { type?: 'text' | 'number' }} props The properties.\n     * @return {HTMLElement}\n     */\n    const createTextField = ({ className = '', label, description, error, onChange, ...rest }) => {\n        /** @type HTMLInputElement */\n        const input = createElement('input', `opp-field-component ${className}`, '', { type: 'text', ...rest });\n        onChange && input.addEventListener('change', (event) => onChange(WOP.sanitize(event.currentTarget?.value)));\n\n        return createFieldWrapper(input, label, description, error);\n    };\n\n    /**\n     * Creates a number input field.\n     *\n     * @param {ElementProps} props The properties.\n     * @return {HTMLElement}\n     */\n    const createNumberField = ({ onChange, ...rest }) => {\n        const handleChange = (value) => onChange(value === '' ? null : Number(value));\n\n        return createTextField({ type: 'number', step: '1', onChange: handleChange, ...rest });\n    };\n\n    /**\n     * Creates a radio group field.\n     *\n     * @param {ElementProps} props The properties.\n     * @return {HTMLElement}\n     */\n    const createRadioGroupField = ({ name, value, className, options, label, description, error, onChange }) => {\n        const wrapper = createElement('div', 'op-radio-input-group');\n        options.forEach((option) => {\n            const label = createElement('label', 'op-radio-input');\n            const props = { type: 'radio', value: option.value, name };\n            if (value === option.value) {\n                props.checked = 'checked';\n            }\n\n            label.append(createElement('input', className, '', props), createElement('span', '', option.label));\n            wrapper.append(label);\n            onChange && label.addEventListener('click', () => onChange(WOP.sanitize(option.value)));\n        });\n\n        return createFieldWrapper(wrapper, label, description, error);\n    };\n\n    /**\n     * Creates a checkbox field.\n     *\n     * @param {ElementProps} props The properties.\n     * @return {HTMLElement}\n     */\n    const createCheckboxField = ({ className = '', label, description, error, onChange, value, ...rest }) => {\n        /** @type HTMLInputElement */\n        const checkbox = createElement('input', 'opp-toggle-input', '', { type: 'checkbox', checked: value, ...rest });\n        onChange && checkbox.addEventListener('change', () => onChange(checkbox.checked));\n\n        const fieldWrapper = createElement('div', 'op-checkbox-field-wrapper');\n        const fieldTitle =  createElement('h3', 'opp-field-title', label, null);\n        let classes = 'op-toggle';\n\n        if (description) {\n            fieldTitle.appendChild(createElement('span', 'opp-field-subtitle', description));\n            classes = 'op-toggle op-has-description';\n        }\n\n        fieldWrapper.appendChild(fieldTitle);\n        fieldWrapper.appendChild(\n            createElement('label', classes, '', null, [checkbox, createElement('span', 'opp-toggle-round')])\n        );\n\n        const field = createElement('div', 'op-field-wrapper opt--checkbox', '', null, [\n            fieldWrapper\n        ]);\n\n        if (error) {\n            field.appendChild(createElement('span', 'opp-input-error', error));\n        }\n\n        return field;\n    };\n\n    /**\n     * Creates a button field.\n     *\n     * @param {ElementProps & { onClick?: () => void , buttonType?: string, buttonSize?: string,\n     *     buttonLabel?: string}} props The properties.\n     * @return {HTMLElement}\n     */\n    const createButtonField = ({ label, description, buttonType, buttonSize, buttonLabel, onClick, error }) => {\n        const button = createButton({\n            type: buttonType,\n            size: buttonSize,\n            className: '',\n            label: translationService.translate(buttonLabel),\n            onClick: onClick\n        });\n\n        return createFieldWrapper(button, label, description, error);\n    };\n\n    /**\n     * Creates a field with a link that looks like a button.\n     *\n     * @param {ElementProps & {text: string, href: string}} props\n     */\n    const createButtonLinkField = ({ label, text, description, href, error }) => {\n        const buttonLink = createButtonLink({\n            text: translationService.translate(text),\n            className: '',\n            href: href\n        });\n\n        return createFieldWrapper(buttonLink, label, description, error);\n    };\n\n    /**\n     * Creates a flash message.\n     *\n     * @param {string|string[]} messageKey\n     * @param {'error' | 'warning' | 'success'} status\n     * @param {number?} clearAfter Time in ms to remove alert message.\n     * @return {HTMLElement}\n     */\n    const createFlashMessage = (messageKey, status, clearAfter) => {\n        const hideHandler = () => {\n            wrapper.remove();\n        };\n        const wrapper = createElement('div', `op-alert opt--${status}`);\n        let messageBlock;\n        if (Array.isArray(messageKey)) {\n            const [titleKey, descriptionKey] = messageKey;\n            messageBlock = createElement('div', 'opp-alert-title', '', null, [\n                createElement('span', 'opp-message', '', null, [\n                    createElement('span', 'opp-message-title', titleKey),\n                    createElement('span', 'opp-message-description', descriptionKey)\n                ])\n            ]);\n        } else {\n            messageBlock = createElement('span', 'opp-alert-title', messageKey);\n        }\n\n        const button = createButton({ onClick: hideHandler });\n\n        if (clearAfter) {\n            setTimeout(hideHandler, clearAfter);\n        }\n\n        wrapper.append(messageBlock, button);\n\n        return wrapper;\n    };\n\n    /**\n     * Adds a label with a hint.\n     *\n     * @param {string} label\n     * @param {string} hint\n     * @param {'left' | 'right' | 'top' | 'bottom'} position\n     * @param {string?} className\n     * @returns HTMLElement\n     */\n    const createHint = (label, hint, position, className = '') => {\n        const element = createElement('div', `op-hint ${className}`, label);\n        const questionMark = createElement('span', '', '?');\n        element.appendChild(questionMark);\n        element.append(createElement('span', 'opp-tooltip opt--' + position, hint));\n        element.addEventListener('mouseenter', () => {\n            element.classList.add('ops--active');\n        });\n        element.addEventListener('mouseout', () => {\n            element.classList.remove('ops--active');\n        });\n\n        return element;\n    };\n\n    /**\n     * Creates a toaster message.\n     *\n     * @param {string} label\n     * @param {'success' | 'error' | 'info'} type\n     * @param {number} timeout Clear timeout in ms.\n     * @returns {HTMLElement}\n     */\n    const createToaster = (label, type, timeout = 5000) => {\n        let elements = [];\n\n        if (type === 'error') {\n            elements.push(createElement('span', 'op-cross-icon'));\n        }\n\n        elements.push(createElement('span', 'opp-toaster-title', label));\n        let button = createElement('button', 'op-button', '', null, [createElement('span')]);\n        button.addEventListener('click', () => toaster.remove());\n        elements.push(button);\n\n        const toaster = createElement('div', 'op-toaster op-' + type, '', null,\n            elements\n        );\n\n        let existingToasters = document.querySelectorAll('.op-toaster');\n\n        if (existingToasters.length > 0) {\n            toaster.style.top = `${110 + existingToasters.length*70}px`\n        }\n\n        button.addEventListener('click', () => toaster.remove());\n\n        setTimeout(() => toaster.remove(), timeout);\n\n        return toaster;\n    };\n\n    /**\n     *\n     * @param {ElementProps & { supportedMimeTypes: string[] }} props\n     * @returns {HTMLDivElement}\n     */\n    const createFileUploadField = ({\n                                       name,\n                                       placeholder,\n                                       label,\n                                       description,\n                                       error,\n                                       value,\n                                       onChange,\n                                       supportedMimeTypes\n                                   }) => {\n        const setActive = (e) => {\n            preventDefaults(e);\n            wrapper.classList.add('ops--active');\n        };\n\n        const setInactive = (e) => {\n            preventDefaults(e);\n            wrapper.classList.remove('ops--active');\n        };\n\n        const previewFile = (file, img) => {\n            let reader = new FileReader();\n            reader.readAsDataURL(file);\n            reader.onloadend = function () {\n                img.src = reader.result;\n            };\n        };\n\n        const handleDrop = (e) => {\n            const file = e.dataTransfer?.files?.[0] || null;\n            if (file) {\n                handleFileChange(file);\n            }\n        };\n\n        const handleFileChange = (file) => {\n            if (!supportedMimeTypes.includes(file.type)) {\n                WOP.validationService.setError(wrapper, 'validation.invalidImageType');\n                return;\n            }\n\n            if (file.size > 10000000) {\n                WOP.validationService.setError(wrapper, 'validation.invalidImageSize');\n                return;\n            }\n\n            onChange(file);\n            WOP.validationService.removeError(wrapper);\n            textElem.classList.remove('ops--empty');\n            textElem.innerText = WOP.sanitize(file.name);\n            const img = createElement('img');\n            textElem.prepend(img);\n            previewFile(file, img);\n        };\n\n        const wrapper = createElement('div', 'op-file-drop-zone opp-field-component');\n        const labelElem = createElement('label', 'opp-input-file-label');\n        const textElem = createElement('span', 'opp-file-label' + (!value ? ' ops--empty' : ''), placeholder);\n        if (value) {\n            textElem.prepend(createElement('img', '', '', { src: value }));\n        }\n\n        const fileUpload = createElement('input', 'opp-input-file', '', {\n            type: 'file',\n            accept: 'image/*',\n            name: name\n        });\n        fileUpload.addEventListener('change', () => handleFileChange(fileUpload.files?.[0]));\n\n        labelElem.append(textElem, fileUpload);\n        wrapper.append(labelElem);\n\n        ['dragenter', 'dragover'].forEach((eventName) => {\n            wrapper.addEventListener(eventName, setActive, false);\n        });\n        ['dragleave', 'drop'].forEach((eventName) => {\n            wrapper.addEventListener(eventName, setInactive, false);\n        });\n        wrapper.addEventListener('drop', handleDrop, false);\n\n        return createFieldWrapper(wrapper, label, description, error);\n    };\n\n    /**\n     * Adds a form footer with save and cancel buttons.\n     *\n     * @param {() => void} onSave\n     * @param {() => void} onCancel\n     * @param {string} cancelLabel\n     * @param {HTMLButtonElement[]} extraButtons\n     * @returns HTMLElement\n     */\n    const createFormFooter = (onSave, onCancel, cancelLabel = 'general.cancel', extraButtons = []) => {\n        return createElement('div', 'op-form-footer', '', null, [\n            createElement('span', 'opp-changes-count', 'general.unsavedChanges'),\n            createElement('div', 'opp-actions', '', null, [\n                ...extraButtons,\n                createButton({\n                    type: 'secondary',\n                    className: 'opp-cancel',\n                    label: cancelLabel,\n                    onClick: onCancel,\n                    disabled: true\n                }),\n                createButton({\n                    type: 'primary',\n                    className: 'opp-save',\n                    label: 'general.saveChanges',\n                    onClick: onSave,\n                    disabled: true\n                })\n            ])\n        ]);\n    };\n\n    /**\n     * Creates form fields based on the fields configurations.\n     *\n     * @param {FormField[]} fields\n     */\n    const createFormFields = (fields) => {\n        /** @type HTMLElement[] */\n        const result = [];\n        fields.forEach(({ type, ...rest }) => {\n            switch (type) {\n                case 'text':\n                    result.push(createTextField({ ...rest, className: 'op-text-input' }));\n                    break;\n                case 'number':\n                    result.push(createNumberField({ ...rest, className: 'op-text-input' }));\n                    break;\n                case 'dropdown':\n                    result.push(createDropdownField(rest));\n                    break;\n                case 'multiselect':\n                    result.push(createMultiselectDropdownField(rest));\n                    break;\n                case 'radio':\n                    result.push(createRadioGroupField(rest));\n                    break;\n                case 'checkbox':\n                    result.push(createCheckboxField(rest));\n                    break;\n                case 'file':\n                    result.push(createFileUploadField(rest));\n                    break;\n                case 'button':\n                    result.push(createButtonField(rest));\n                    break;\n                case 'buttonLink':\n                    result.push(createButtonLinkField(rest));\n                    break;\n            }\n\n            rest.className && result[result.length - 1].classList.add(...rest.className.trim().split(' '));\n        });\n\n        return result;\n    };\n\n    /**\n     * Creates a main header item.\n     *\n     * @param {string} brand\n     * @param {LinkDropDownComponentModel} linkDropDown\n     * @param {string} page\n     *\n     * @returns {HTMLElement}\n     */\n    const createHeaderItem = (brand, linkDropDown, page) => {\n        return WOP.components.Header.create({brand, linkDropDown, page})\n    };\n\n    WOP.elementGenerator = {\n        createElement,\n        createElementFromHTML,\n        createButton,\n        createHint,\n        createDropdownField,\n        createMultiselectDropdownField,\n        createLinkDropdownField,\n        createPasswordField,\n        createTextField,\n        createNumberField,\n        createRadioGroupField,\n        createFlashMessage,\n        createStoreSwitcher,\n        createModeElement,\n        createFileUploadField,\n        createButtonField,\n        createButtonLinkField,\n        createFormFields,\n        createFormFooter,\n        createToaster,\n        createHeaderItem,\n        createFieldWrapper\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/ElementGenerator.js?");

/***/ }),

/***/ "./src/services/PageControllerFactory.js":
/*!***********************************************!*\
  !*** ./src/services/PageControllerFactory.js ***!
  \***********************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    function PageControllerFactory() {\n        /**\n         * Instantiates page controller;\n         *\n         * @param {string} controller\n         * @param {Record<string, any>} configuration\n         */\n        this.getInstance = (controller, configuration) => {\n            let parts = controller.split('-');\n            let name = '';\n            for (let part of parts) {\n                part = part.charAt(0).toUpperCase() + part.slice(1);\n                name += part;\n            }\n\n            name += 'Controller';\n\n            return WOP[name] ? new WOP[name](configuration) : null;\n        };\n    }\n\n    WOP.pageControllerFactory = new PageControllerFactory();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/PageControllerFactory.js?");

/***/ }),

/***/ "./src/services/ResponseService.js":
/*!*****************************************!*\
  !*** ./src/services/ResponseService.js ***!
  \*****************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * The ResponseService constructor.\n     *\n     * @constructor\n     */\n    function ResponseService() {\n        /**\n         * Handles an error response from the submit action.\n         *\n         * @param {{error?: string, errorCode?: string, status?: number}} response\n         * @returns {Promise<void>}\n         */\n        this.errorHandler = (response) => {\n            if (response.status !== 401) {\n                const { utilities } = WOP;\n                utilities.createToasterMessage('general.errors.' + response.errorCode, 'error');\n            }\n\n            return Promise.reject(response);\n        };\n\n        /**\n         * Handles 401 response.\n         *\n         * @param {{error?: string, errorCode?: string}} response\n         * @returns {Promise<void>}\n         */\n        this.unauthorizedHandler = (response) => {\n            WOP.utilities.create401FlashMessage(`general.errors.${response.errorCode}`);\n            WOP.state.goToState('connection');\n\n            return Promise.reject({ ...response, status: 401 });\n        };\n    }\n\n    WOP.responseService = new ResponseService();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/ResponseService.js?");

/***/ }),

/***/ "./src/services/Sanitizer.js":
/*!***********************************!*\
  !*** ./src/services/Sanitizer.js ***!
  \***********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var dompurify__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! dompurify */ \"./node_modules/dompurify/dist/purify.es.mjs\");\n\n\n/**\n * Recursively sanitizes all string values within any data structure to protect against XSS attacks.\n *\n * @param input\n * @returns {{}|*|string}\n */\nconst sanitize = (input) => {\n    if (typeof input === 'string') {\n        return dompurify__WEBPACK_IMPORTED_MODULE_0__[\"default\"].sanitize(input);\n    }\n\n    if (Array.isArray(input)) {\n        return input.map(sanitize);\n    }\n\n    if (input !== null && typeof input === 'object') {\n        const sanitized = {};\n        for (const key in input) {\n            if (input.hasOwnProperty(key)) {\n                sanitized[key] = sanitize(input[key]);\n            }\n        }\n        return sanitized;\n    }\n\n    return input;\n}\n\nWOP.sanitize = sanitize;\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/Sanitizer.js?");

/***/ }),

/***/ "./src/services/TemplateService.js":
/*!*****************************************!*\
  !*** ./src/services/TemplateService.js ***!
  \*****************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    function TemplateService() {\n        /**\n         * The configuration object for all templates.\n         */\n        let templates = {};\n        let mainPlaceholder = '#op-main-page-holder';\n\n        /**\n         * Gets the main page DOM element.\n         *\n         * @returns {HTMLElement}\n         */\n        this.getMainPage = () => document.querySelector(mainPlaceholder);\n\n        /**\n         * Gets the main header element.\n         *\n         * @returns {HTMLElement}\n         */\n        this.getHeaderSection = () => document.getElementById('op-main-header');\n\n        /**\n         * Clears the main page.\n         *\n         * @return {HTMLElement}\n         */\n        this.clearMainPage = () => {\n            this.clearComponent(this.getMainPage());\n        };\n\n        /**\n         * Sets the content templates.\n         *\n         * @param {{}} configuration\n         */\n        this.setTemplates = (configuration) => {\n            templates = configuration;\n        };\n\n        /**\n         * Gets the template with translated text.\n         *\n         * @param {string} templateId\n         *\n         * @return {string} HTML as string.\n         */\n        this.getTemplate = (templateId) => translate(templates[templateId]);\n\n        /**\n         * Removes component's children.\n         *\n         * @param {Element} component\n         */\n        this.clearComponent = (component) => {\n            while (component.firstChild) {\n                component.removeChild(component.firstChild);\n            }\n        };\n\n        /**\n         * Replaces all translation keys in the provided HTML.\n         *\n         * @param {string} html\n         * @return {string}\n         */\n        const translate = (html) => {\n            return html ? WOP.translationService.translateHtml(html) : '';\n        };\n    }\n\n    WOP.templateService = new TemplateService();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/TemplateService.js?");

/***/ }),

/***/ "./src/services/TranslationService.js":
/*!********************************************!*\
  !*** ./src/services/TranslationService.js ***!
  \********************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * A Translation service. This class turns an input key and params to the translated text.\n     * The translations are used from the global WOP.translations object. It expects two keys in this object:\n     * 'current' and 'default', where 'current' holds the translations for the current language,\n     * and 'default' holds the translations in the default language. The 'default' will be used as a fallback if\n     * the 'current' object does not have the given entry. Both properties should be objects with the \"section - key\"\n     * format. For example:\n     *  current: {\n     *      login: {\n     *          title: 'The title',\n     *          subtitle: 'This is the subtitle of the %s app.'\n     *      },\n     *      secondPage: {\n     *          title: 'The second page title',\n     *          description: 'Use this page to set the second thing.'\n     *      }\n     *  }\n     *\n     *  With this in mind, the translation keys are in format \"section.key\", for example \"login.title\".\n     *\n     * @constructor\n     */\n    function TranslationService() {\n        /**\n         * Gets the translation from the dictionary if exists.\n         *\n         * @param {'default' | 'current'} type\n         * @param {string} group\n         * @param {string | string[]} key\n         * @returns {null|string}\n         */\n        const getTranslation = (type, group, key) => {\n            if (WOP.translations[type][group] && WOP.translations[type][group]) {\n                let value = WOP.translations[type][group];\n                if (Array.isArray(key)) {\n                    return key.reduce((value, key) => {\n                        if (value && value.hasOwnProperty(key)) {\n                            return value[key];\n                        }\n\n                        return null;\n                    }, value);\n                }\n\n                if (value && value.hasOwnProperty(key)) {\n                    return value[key];\n                }\n\n                return null;\n            }\n\n            return null;\n        };\n\n        /**\n         * Replaces the parameters in the given text, if any.\n         *\n         * @param {string} text\n         * @param {[]} params\n         * @return {string}\n         */\n        const replaceParams = (text, params) => {\n            if (!params) {\n                return text;\n            }\n\n            let i = 0;\n            return text.replace(/%s/g, function () {\n                const param = params[i] !== undefined ? params[i] : '%s';\n                i++;\n\n                return param;\n            });\n        };\n\n        /**\n         * Returns a translated string based on the input key and given parameters. If the string to translate\n         * has parameters, the placeholder is \"%s\". For example: Input key %s is not valid. This method will\n         * replace parameters in the order given in the params array, if any.\n         *\n         * @param {string} key The translation key in format \"group.key\".\n         * @param {[]} [params] An array of parameters to be replaced in the output string.\n         *\n         * @return {string}\n         */\n        this.translate = (key, params) => {\n            const [group, ...keys] = key.split('.');\n\n            const result = getTranslation('current', group, keys) || getTranslation('default', group, keys);\n            if (result !== null) {\n                return replaceParams(result, params);\n            }\n\n            return replaceParams(key, params);\n        };\n\n        /**\n         * Replaces the translations in the given HTML code.\n         *\n         * @param {string} html\n         * @return {string} The updated HTML.\n         */\n        this.translateHtml = (html) => {\n            // Replace the placeholders for translations. They are in the format {$key|param1|param2}.\n            let format = /{\\$[.\\-_A-Za-z|]+}/g;\n            const me = this;\n\n            return html.replace(format, (key) => {\n                // remove the placeholder characters to get \"key|param1|param2\"\n                key = key.substring(2, key.length - 1);\n                // split parameters\n                let params = key.split('|');\n\n                return me.translate(params[0], params.slice(1)) || key;\n            });\n        };\n    }\n\n    WOP.translationService = new TranslationService();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/TranslationService.js?");

/***/ }),

/***/ "./src/services/UtilityService.js":
/*!****************************************!*\
  !*** ./src/services/UtilityService.js ***!
  \****************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    function UtilityService() {\n        let loaderCount = 0;\n\n        /**\n         * Shows the HTML node.\n         *\n         * @param {HTMLElement} element\n         */\n        this.showElement = (element) => {\n            element?.classList.remove('ops--hidden');\n        };\n\n        /**\n         * Hides the HTML node.\n         *\n         * @param {HTMLElement} element\n         */\n        this.hideElement = (element) => {\n            element?.classList.add('ops--hidden');\n        };\n\n        /**\n         * Enables loading spinner.\n         */\n        this.showLoader = () => {\n            if (loaderCount === 0) {\n                this.showElement(document.getElementById('op-spinner'));\n            }\n\n            loaderCount++;\n        };\n\n        /**\n         * Hides loading spinner.\n         */\n        this.hideLoader = () => {\n            if (loaderCount > 0) {\n                loaderCount--;\n            }\n\n            if (loaderCount === 0) {\n                this.hideElement(document.getElementById('op-spinner'));\n            }\n        };\n\n        /**\n         * Shows flash message.\n         *\n         * @note Only one flash message will be shown at the same time.\n         *\n         * @param {string} message\n         * @param {'error' | 'warning' | 'success'} status\n         * @param {number?} clearAfter Time in ms to remove alert message.\n         */\n        this.createFlashMessage = (message, status, clearAfter) => {\n            return WOP.elementGenerator.createFlashMessage(message, status, clearAfter);\n        };\n\n        /**\n         * Creates the 401 error flash message.\n         *\n         * @param {string} message\n         */\n        this.create401FlashMessage = (message) => {\n            this.remove401Message();\n            const messageElement = WOP.elementGenerator.createFlashMessage(message, 'error');\n            messageElement.classList.add('opv--401-error');\n            WOP.templateService.getHeaderSection().append(messageElement);\n        };\n\n        /**\n         * Removes the 401 flash message.\n         */\n        this.remove401Message = () => {\n            WOP.templateService\n                .getHeaderSection()\n                .querySelectorAll(`.opv--401-error`)\n                .forEach((e) => e.remove());\n        };\n\n        /**\n         * Creates a toaster message.\n         *\n         * @param {string} message A message translation key.\n         * @param {'success' | 'error' | 'info'} type\n         */\n        this.createToasterMessage = (message, type = 'success') => {\n            document.getElementById('op-page').append(WOP.elementGenerator.createToaster(message, type));\n        };\n\n        /**\n         * Updates a form's footer state based on the number of changes.\n         *\n         * @param {number} numberOfChanges\n         * @param {boolean} disableCancel\n         */\n        this.renderFooterState = (numberOfChanges, disableCancel = true) => {\n            if (numberOfChanges) {\n                document.querySelector('.op-form-footer .opp-changes-count')?.classList.add('ops--active');\n                document.querySelector('.op-form-footer .opp-actions .opp-save').disabled = false;\n                document.querySelector('.op-form-footer .opp-actions .opp-cancel').disabled = false;\n            } else {\n                document.querySelector('.op-form-footer .opp-changes-count')?.classList.remove('ops--active');\n                document.querySelector('.op-form-footer .opp-actions .opp-save').disabled = true;\n                document.querySelector('.op-form-footer .opp-actions .opp-cancel').disabled = disableCancel;\n            }\n        };\n\n        /**\n         * Creates deep clone of an object with object's properties.\n         * Removes object's methods.\n         *\n         * @note Object cannot have values that cannot be converted to json (undefined, infinity etc).\n         *\n         * @param {object} obj\n         * @return {object}\n         */\n        this.cloneObject = (obj) => JSON.parse(JSON.stringify(obj || {}));\n\n        /**\n         * Gets the first ancestor element with the corresponding class name.\n         *\n         * @param {HTMLElement} element\n         * @param {string} className\n         * @return {HTMLElement}\n         */\n        this.getAncestor = (element, className) => {\n            let parent = element?.parentElement;\n\n            while (parent) {\n                if (parent.classList.contains(className)) {\n                    break;\n                }\n\n                parent = parent.parentElement;\n            }\n\n            return parent;\n        };\n\n        /**\n         * Check if two arrays are equal.\n         *\n         * @param {any[]} source\n         * @param {any[]} target\n         * @return {boolean} TRUE if arrays are equal; otherwise, FALSE.\n         */\n        this.compareArrays = (source, target) => {\n            if (source.length !== target.length) {\n                return false;\n            }\n\n            const sortedSource = source.slice().sort();\n            const sortedTarget = target.slice().sort();\n\n            for (let i = 0; i < sortedSource.length; i++) {\n                if (sortedSource[i] !== sortedTarget[i]) {\n                    return false;\n                }\n            }\n\n            return true;\n        };\n    }\n\n    WOP.utilities = new UtilityService();\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/UtilityService.js?");

/***/ }),

/***/ "./src/services/ValidationService.js":
/*!*******************************************!*\
  !*** ./src/services/ValidationService.js ***!
  \*******************************************/
/***/ (() => {

eval("if (!window.WOP) {\n    window.WOP = {};\n}\n\n(function () {\n    /**\n     * @typedef ValidationMessage\n     * @property {string} code The message code.\n     * @property {string} field The field name that the error is related to.\n     * @property {string} message The error message.\n     */\n\n    const validationRule = {\n        numeric: 'numeric',\n        integer: 'integer',\n        required: 'required',\n        greaterThanZero: 'greaterThanZero',\n        minValue: 'minValue',\n        maxValue: 'maxValue',\n        nonNegative: 'nonNegative',\n        greaterThanX: 'greaterThanX'\n    };\n\n    const { templateService, utilities, translationService } = WOP;\n\n    /**\n     * Validates if the input has a value. If the value is not set, adds an error class to the input element.\n     *\n     * @param {HTMLInputElement|HTMLSelectElement} input\n     * @param {string?} message\n     * @return {boolean}\n     */\n    const validateRequiredField = (input, message) => {\n        return validateField(input, !input.value?.trim() || (input.type === 'checkbox' && !input.checked), message);\n    };\n\n    /**\n     * Validates a numeric input.\n     *\n     * @param {HTMLInputElement} input\n     * @param {string?} message\n     * @return {boolean} Indication of the validity.\n     */\n    const validateNumber = (input, message) => {\n        const ruleset = input.dataset?.validationRule ? input.dataset.validationRule.split(',') : [];\n        let result = true;\n\n        if (!validateField(input, Number.isNaN(input.value), message)) {\n            return false;\n        }\n\n        const value = Number(input.value);\n        ruleset.forEach((rule) => {\n            if (!result) {\n                // break on first false rule\n                return;\n            }\n\n            let condition = false;\n            let subValue = null;\n            if (rule.includes('|')) {\n                [rule, subValue] = rule.split('|');\n            }\n\n            // condition should be positive for valid values\n            switch (rule) {\n                case validationRule.integer:\n                    condition = Number.isInteger(value);\n                    break;\n                case validationRule.greaterThanZero:\n                    condition = value > 0;\n                    break;\n                case validationRule.minValue:\n                    condition = value >= Number(subValue);\n                    break;\n                case validationRule.maxValue:\n                    condition = value <= Number(subValue);\n                    break;\n                case validationRule.nonNegative:\n                    condition = value >= 0;\n                    break;\n                case validationRule.required:\n                    condition = !!input.value?.trim();\n                    break;\n                case validationRule.greaterThanX:\n                    condition = value >= Number(document.querySelector(`input[name=\"${subValue}\"]`)?.value);\n                    break;\n                default:\n                    return;\n            }\n\n            if (!validateField(input, !condition, message)) {\n                result = false;\n            }\n        });\n\n        return result;\n    };\n\n    /**\n     * Validates a list of numbers.\n     *\n     * @param {HTMLInputElement} input\n     * @param {boolean} [required=true]\n     * @param {boolean} [decimal=true]\n     * @returns {boolean}\n     */\n    const validateNumberList = (input, required = true, decimal = true) => {\n        let error;\n        const value = input.value;\n        if (!value.trim()) {\n            if (!required) {\n                return true;\n            }\n\n            error = 'validation.requiredField';\n        } else {\n            const values = value.split(',').map((value) => value.trim());\n            if (values.map((value) => Number.isNaN(Number(value)) || Number(value) <= 0).includes(true)) {\n                error = decimal ? 'validation.invalidNumberInList' : 'validation.invalidWholeNumberInList';\n            } else if (\n                values.filter((value, index) => {\n                    return values.indexOf(value) !== index;\n                }).length > 0\n            ) {\n                error = 'validation.duplicateNumberInList';\n            } else if (!decimal) {\n                values.forEach((value) => {\n                    if (!Number.isInteger(Number(value))) {\n                        error = 'validation.invalidWholeNumberInList';\n                    }\n                });\n            }\n        }\n\n        return validateField(input, !!error, error);\n    };\n\n    /**\n     * Validates if the input is a valid email. If not, adds the error class to the input element.\n     *\n     * @param {HTMLInputElement} input\n     * @param {string?} message\n     * @return {boolean}\n     */\n    const validateEmail = (input, message) => {\n        let regex =\n            /^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\n        return validateField(input, !regex.test(String(input.value).toLowerCase()), message);\n    };\n\n    /**\n     * Validates if the input is a valid URL. If not, adds an error class to the input element.\n     *\n     * @param {HTMLInputElement} input\n     * @param {string?} message\n     * @return {boolean}\n     */\n    const validateUrl = (input, message) => {\n        let regex = /(https?:\\/\\/)([\\w\\-])+\\.([a-zA-Z]{2,63})([\\/\\w-]*)*\\/?\\??([^#\\n\\r]*)?#?([^\\n\\r]*)/m;\n\n        return validateField(input, !regex.test(String(input.value).toLowerCase()), message);\n    };\n\n    /**\n     * Validates if the input field is longer than a specified number of characters.\n     * If so, adds an error class to the input element.\n     *\n     * @param {HTMLInputElement} input\n     * @param {string?} message\n     * @return {boolean}\n     */\n    const validateMaxLength = (input, message) => {\n        return validateField(input, input.dataset.maxLength && input.value.length > input.dataset.maxLength, message);\n    };\n\n    /**\n     * Handles validation errors. These errors come from the back end.\n     *\n     * @param {ValidationMessage[]} errors\n     */\n    const handleValidationErrors = (errors) => {\n        for (const error of errors) {\n            markFieldGroupInvalid(`[name=${error.field}]`, error.message);\n        }\n    };\n\n    /**\n     * Marks a field as invalid.\n     *\n     * @param {string} fieldSelector The field selector.\n     * @param {string} message The message to display.\n     * @param {Element} [parent] A parent element.\n     */\n    const markFieldGroupInvalid = (fieldSelector, message, parent) => {\n        if (!parent) {\n            parent = templateService.getMainPage();\n        }\n\n        const inputEl = parent.querySelector(fieldSelector);\n        inputEl && setError(inputEl, message);\n    };\n\n    /**\n     * Sets error for an input.\n     *\n     * @param {HTMLElement} element\n     * @param {string?} message\n     */\n    const setError = (element, message) => {\n        const parent = utilities.getAncestor(element, 'op-field-wrapper');\n        parent && parent.classList.add('ops--error');\n        if (message) {\n            let errorField = parent.querySelector('.opp-input-error');\n            if (!errorField) {\n                errorField = WOP.elementGenerator.createElement('span', 'opp-input-error', message);\n                parent.append(errorField);\n            }\n\n            errorField.innerHTML = WOP.sanitize(translationService.translate(message));\n        }\n    };\n\n    /**\n     * Removes error from input form group element.\n     *\n     * @param {HTMLElement} element\n     */\n    const removeError = (element) => {\n        const parent = utilities.getAncestor(element, 'op-field-wrapper');\n        parent && parent.classList.remove('ops--error');\n    };\n\n    /**\n     * Validates the condition against the input field and marks field invalid if the error condition is met.\n     *\n     * @param {HTMLElement} element\n     * @param {boolean} errorCondition Error condition.\n     * @param {string?} message\n     * @return {boolean}\n     */\n    const validateField = (element, errorCondition, message) => {\n        if (errorCondition) {\n            setError(element, message);\n\n            return false;\n        }\n\n        removeError(element);\n\n        return true;\n    };\n\n    WOP.validationService = {\n        setError,\n        removeError,\n        validateEmail,\n        validateNumber,\n        validateNumberList,\n        validateUrl,\n        validateMaxLength,\n        validateField,\n        validateRequiredField,\n        handleValidationErrors\n    };\n})();\n\n\n//# sourceURL=webpack://online-payments-core-admin-fe/./src/services/ValidationService.js?");

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval devtool is used.
/******/ 	__webpack_require__("./src/index.js");
/******/ 	var __webpack_exports__ = __webpack_require__("./WOP/design/index.scss");
/******/ 	
/******/ })()
;