{"version":3,"file":"bundle.esm.js","sources":["../modules/@helpers/js/keyvaluestorage.js","../modernizr.js","../modules/@helpers/js/enhancements.js","../modules/@helpers/js/observer.js","../modules/search-awesomplete.js","../modules/cz-forms/js/form-validation.js","../../../../node_modules/@lit/reactive-element/css-tag.js","../../../../node_modules/@lit/reactive-element/reactive-element.js","../../../../node_modules/lit-html/lit-html.js","../../../../node_modules/lit-element/lit-element.js","../modules/cz-forms/js/@webcomponent/cz-combobox.js","../modules/@helpers/js/datalayer.js","../modules/@helpers/js/wait.js","../modules/@helpers/js/queue-processing.js","../modules/cz-navigation/js/classNames.js","../modules/cz-navigation/js/domElements.js","../modules/@helpers/js/interpretAction.js","../modules/cz-navigation/js/shared.js","../modules/cz-navigation/js/handleOverlay.js","../modules/@helpers/js/scrollLocker.js","../modules/cz-navigation/js/handleNavContainer.js","../modules/cz-navigation/js/handleNavDomain.js","../modules/cz-navigation/js/handleSearch.js","../modules/cz-navigation/js/handleSubmenus.js","../modules/cz-navigation/js/handleViewportHeights.js","../modules/cz-navigation/js/navigation.js","../../../../node_modules/@cz/webcomponents/src/cz-loader/cz-loader.js","../../../../node_modules/@cz/webcomponents/src/cz-icon/cz-icon.js","../../../../node_modules/@cz/webcomponents/src/cz-contentloader/cz-contentloader.js","../../../../node_modules/lit-html/directive.js","../../../../node_modules/lit-html/directives/unsafe-html.js","../../../../node_modules/@cz/webcomponents/src/helpers/trap-focus.js","../../../../node_modules/@cz/webcomponents/src/helpers/focusable.js","../../../../node_modules/@cz/webcomponents/src/cz-sidepanel/cz-sidepanel.js","../../../../node_modules/@cz/icons/dist/cz/iconSprites.mjs","../modules/cz-collective/js/search-suggestions.js","../modules/cz-vergoeding/js/compare-insurance-table.js","../modules/cz-vergoeding/js/@webcomponent/cz-avtableloader.js","../modules/cz-vergoeding/js/search-compensation.js","../modules/cz-vergoeding/js/@webcomponent/cz-mfaloader.js","../modules/cz-vergoeding/js/@webcomponent/cz-vergelijkerloader.js","../modules/just-navigation/js/handleSearchJust.js","../modules/just-navigation/js/navigationJust.js","../modules.js","../modules/content-enhancements.js","../modules/set-list-icon.js","../main.esm.js","../modules/@helpers/js/clearLayoutProps.js","../modules/cz-action/js/click-action.js","../modules/cz-category-tree/js/categories.js","../modules/cz-datalayer/js/datalayer.js","../modules/@helpers/js/helpers.js","../modules/cz-popup-overlay/js/popup-overlay.js","../modules/cz-revealer/js/revealer.js","../modules/cz-scroll-to-top/js/scroll-to-top.js","../modules/cz-service/js/services.js","../modules/cz-side-overlay/js/side-overlay.js","../modules/cz-whatsthat/js/whats-that.js","../modules/cz-amount/js/super-cents.js","../modules/cz-alert-bar/js/alert-bar.js","../modules/cz-cluster-grid/js/clustergrid-filter.js","../modules/@helpers/js/radiogroup-helper.js","../modules/cz-collective/js/collective-choice.js","../modules/cz-collective/js/collective-search.js","../modules/cz-search/js/search-filter.js","../modules/cz-search/js/search-form.js","../modules/cz-toggle-button/js/toggle-button-listener.js","../modules/cz-toggle-button/js/toggle-button.js","../modules/cz-tooltip/js/tooltip.js","../modules/cz-upload-file/js/file-upload.js","../modules/cz-vergoeding/js/comboboxAutocomplete.js","../modules/just-navigation/js/sticky-nav.js"],"sourcesContent":["function storageAvailable(type) {\n\tlet stor;\n\ttry {\n\t\tstor = window[type];\n\t\tconst x = '__storage_test__';\n\t\tstor.setItem(x, x);\n\t\tstor.removeItem(x);\n\t\treturn true;\n\t}\n\tcatch (e) {\n\t\treturn e instanceof DOMException && (\n\t\t\t// everything except Firefox\n\t\t\te.code === 22 ||\n\t\t\t// Firefox\n\t\t\te.code === 1014 ||\n\t\t\t// test name field too, because code might not be present\n\t\t\t// everything except Firefox\n\t\t\te.name === 'QuotaExceededError' ||\n\t\t\t// Firefox\n\t\t\te.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&\n\t\t\t// acknowledge QuotaExceededError only if there's something already stored\n\t\t\t(stor && stor.length !== 0);\n\t}\n}\n\nconst _store = {};\n\nfunction setItem(key, value) {\n\t_store[key] = value;\n}\nfunction getItem(key) {\n\treturn _store[key];\n}\nfunction removeItem(key) {\n\tdelete _store[key];\n}\n\n// setup memorystorage\nconst pageStorage = {\n\tsetItem,\n\tgetItem,\n\tremoveItem\n}\n\nexport function getStorage(level = '') {\n\tlet storage = pageStorage;\n\tswitch (level) {\n\t\tcase 'persist':\n\t\t\t// setup localstorage, fallback to sessionstorage if not available, and to memorystorage as a last resort\n\t\t\tstorage = storageAvailable(\"localStorage\") ? window.localStorage : storageAvailable(\"sessionStorage\") ? window.sessionStorage : pageStorage;\n\t\t\tbreak;\n\t\tcase 'session':\n\t\t\t// setup sessionstorage, fallback to memorystorage if not available\n\t\t\tstorage = storageAvailable(\"sessionStorage\") ? window.sessionStorage : pageStorage;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\treturn {\n\t\tstoreKeyValue: (key, value) => {\n\t\t\tif (!key || typeof key !== 'string' || !value) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tstorage.setItem(key, value)\n\t\t\t } else {\n\t\t\t\tstorage.setItem(key, JSON.stringify(value))\n\t\t\t }\n\t\t\treturn true;\n\t\t},\n\t\tgetStoredValue: (key) => {\n\t\t\tif (!key || typeof key !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst value = storage.getItem(key)\n\t\t\tif (!value) return\n\n\t\t\ttry {\n\t\t\t // Returns an object if stored value is JSON\n\t\t\t return JSON.parse(value);\n\t\t\t} catch (error) {\n\t\t\t // Returns plain string if stored value is not JSON\n\t\t\t return value;\n\t\t\t}\n\t\t},\n\t\tremoveStoredValue: (key) => {\n\t\t\tif (!key || typeof key !== 'string') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treturn storage.removeItem(key);\n\t\t}\n\t};\n}\n","/*!\n * modernizr v3.13.0\n * Build https://modernizr.com/download?-touchevents-addtest-printshiv-setclasses-testprop-dontmin\n *\n * Copyright (c)\n * Faruk Ates\n * Paul Irish\n * Alex Sexton\n * Ryan Seddon\n * Patrick Kettner\n * Stu Cox\n * Richard Herrera\n * Veeck\n\n * MIT License\n */\n\n/*\n * Modernizr tests which native CSS3 and HTML5 features are available in the\n * current UA and makes the results available to you in two ways: as properties on\n * a global `Modernizr` object, and as classes on the `` element. This\n * information allows you to progressively enhance your pages with a granular level\n * of control over the experience.\n*/\n\n;(function(scriptGlobalObject, window, document, undefined){\n\n var tests = [];\n \n\n /**\n * ModernizrProto is the constructor for Modernizr\n *\n * @class\n * @access public\n */\n var ModernizrProto = {\n _version: '3.13.0',\n\n // Any settings that don't work as separate modules\n // can go in here as configuration.\n _config: {\n 'classPrefix': '',\n 'enableClasses': true,\n 'enableJSClass': true,\n 'usePrefixes': true\n },\n\n // Queue of tests\n _q: [],\n\n // Stub these for people who are listening\n on: function(test, cb) {\n // I don't really think people should do this, but we can\n // safe guard it a bit.\n // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.\n // This is in case people listen to synchronous tests. I would leave it out,\n // but the code to *disallow* sync tests in the real version of this\n // function is actually larger than this.\n var self = this;\n setTimeout(function() {\n cb(self[test]);\n }, 0);\n },\n\n addTest: function(name, fn, options) {\n tests.push({name: name, fn: fn, options: options});\n },\n\n addAsyncTest: function(fn) {\n tests.push({name: null, fn: fn});\n }\n };\n\n \n\n // Fake some of Object.create so we can force non test results to be non \"own\" properties.\n var Modernizr = function() {};\n Modernizr.prototype = ModernizrProto;\n\n // Leak modernizr globally when you `require` it rather than force it here.\n // Overwrite name so constructor name is nicer :D\n Modernizr = new Modernizr();\n\n \n\n var classes = [];\n \n\n /**\n * is returns a boolean if the typeof an obj is exactly type.\n *\n * @access private\n * @function is\n * @param {*} obj - A thing we want to check the type of\n * @param {string} type - A string to compare the typeof against\n * @returns {boolean} true if the typeof the first parameter is exactly the specified type, false otherwise\n */\n function is(obj, type) {\n return typeof obj === type;\n }\n\n ;\n\n /**\n * Run through all tests and detect their support in the current UA.\n *\n * @access private\n * @returns {void}\n */\n function testRunner() {\n var featureNames;\n var feature;\n var aliasIdx;\n var result;\n var nameIdx;\n var featureName;\n var featureNameSplit;\n\n for (var featureIdx in tests) {\n if (tests.hasOwnProperty(featureIdx)) {\n featureNames = [];\n feature = tests[featureIdx];\n // run the test, throw the return value into the Modernizr,\n // then based on that boolean, define an appropriate className\n // and push it into an array of classes we'll join later.\n //\n // If there is no name, it's an 'async' test that is run,\n // but not directly added to the object. That should\n // be done with a post-run addTest call.\n if (feature.name) {\n featureNames.push(feature.name.toLowerCase());\n\n if (feature.options && feature.options.aliases && feature.options.aliases.length) {\n // Add all the aliases into the names list\n for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {\n featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());\n }\n }\n }\n\n // Run the test, or use the raw value if it's not a function\n result = is(feature.fn, 'function') ? feature.fn() : feature.fn;\n\n // Set each of the names on the Modernizr object\n for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {\n featureName = featureNames[nameIdx];\n // Support dot properties as sub tests. We don't do checking to make sure\n // that the implied parent tests have been added. You must call them in\n // order (either in the test, or make the parent test a dependency).\n //\n // Cap it to TWO to make the logic simple and because who needs that kind of subtesting\n // hashtag famous last words\n featureNameSplit = featureName.split('.');\n\n if (featureNameSplit.length === 1) {\n Modernizr[featureNameSplit[0]] = result;\n } else {\n // cast to a Boolean, if not one already or if it doesnt exist yet (like inputtypes)\n if (!Modernizr[featureNameSplit[0]] || Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {\n Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);\n }\n\n Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;\n }\n\n classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));\n }\n }\n }\n }\n ;\n\n /**\n * docElement is a convenience wrapper to grab the root element of the document\n *\n * @access private\n * @returns {HTMLElement|SVGElement} The root element of the document\n */\n var docElement = document.documentElement;\n \n\n /**\n * A convenience helper to check if the document we are running in is an SVG document\n *\n * @access private\n * @returns {boolean}\n */\n var isSVG = docElement.nodeName.toLowerCase() === 'svg';\n\n \n\n /**\n * setClasses takes an array of class names and adds them to the root element\n *\n * @access private\n * @function setClasses\n * @param {string[]} classes - Array of class names\n */\n // Pass in an and array of class names, e.g.:\n // ['no-webp', 'borderradius', ...]\n function setClasses(classes) {\n var className = docElement.className;\n var classPrefix = Modernizr._config.classPrefix || '';\n\n if (isSVG) {\n className = className.baseVal;\n }\n\n // Change `no-js` to `js` (independently of the `enableClasses` option)\n // Handle classPrefix on this too\n if (Modernizr._config.enableJSClass) {\n var reJS = new RegExp('(^|\\\\s)' + classPrefix + 'no-js(\\\\s|$)');\n className = className.replace(reJS, '$1' + classPrefix + 'js$2');\n }\n\n if (Modernizr._config.enableClasses) {\n // Add the new classes\n if (classes.length > 0) {\n className += ' ' + classPrefix + classes.join(' ' + classPrefix);\n }\n if (isSVG) {\n docElement.className.baseVal = className;\n } else {\n docElement.className = className;\n }\n }\n }\n\n ;\n\n /**\n * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support\n *\n * @author kangax\n * @access private\n * @function hasOwnProp\n * @param {object} object - The object to check for a property\n * @param {string} property - The property to check for\n * @returns {boolean}\n */\n\n // hasOwnProperty shim by kangax needed for Safari 2.0 support\n var hasOwnProp;\n\n (function() {\n var _hasOwnProperty = ({}).hasOwnProperty;\n /* istanbul ignore else */\n /* we have no way of testing IE 5.5 or safari 2,\n * so just assume the else gets hit */\n if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {\n hasOwnProp = function(object, property) {\n return _hasOwnProperty.call(object, property);\n };\n }\n else {\n hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */\n return ((property in object) && is(object.constructor.prototype[property], 'undefined'));\n };\n }\n })();\n\n \n\n\n // _l tracks listeners for async tests, as well as tests that execute after the initial run\n ModernizrProto._l = {};\n\n /**\n * Modernizr.on is a way to listen for the completion of async tests. Being\n * asynchronous, they may not finish before your scripts run. As a result you\n * will get a possibly false negative `undefined` value.\n *\n * @memberOf Modernizr\n * @name Modernizr.on\n * @access public\n * @function on\n * @param {string} feature - String name of the feature detect\n * @param {Function} cb - Callback function returning a Boolean - true if feature is supported, false if not\n * @returns {void}\n * @example\n *\n * ```js\n * Modernizr.on('flash', function( result ) {\n * if (result) {\n * // the browser has flash\n * } else {\n * // the browser does not have flash\n * }\n * });\n * ```\n */\n ModernizrProto.on = function(feature, cb) {\n // Create the list of listeners if it doesn't exist\n if (!this._l[feature]) {\n this._l[feature] = [];\n }\n\n // Push this test on to the listener list\n this._l[feature].push(cb);\n\n // If it's already been resolved, trigger it on next tick\n if (Modernizr.hasOwnProperty(feature)) {\n // Next Tick\n setTimeout(function() {\n Modernizr._trigger(feature, Modernizr[feature]);\n }, 0);\n }\n };\n\n /**\n * _trigger is the private function used to signal test completion and run any\n * callbacks registered through [Modernizr.on](#modernizr-on)\n *\n * @memberOf Modernizr\n * @name Modernizr._trigger\n * @access private\n * @function _trigger\n * @param {string} feature - string name of the feature detect\n * @param {Function|boolean} [res] - A feature detection function, or the boolean =\n * result of a feature detection function\n * @returns {void}\n */\n ModernizrProto._trigger = function(feature, res) {\n if (!this._l[feature]) {\n return;\n }\n\n var cbs = this._l[feature];\n\n // Force async\n setTimeout(function() {\n var i, cb;\n for (i = 0; i < cbs.length; i++) {\n cb = cbs[i];\n cb(res);\n }\n }, 0);\n\n // Don't trigger these again\n delete this._l[feature];\n };\n\n /**\n * addTest allows you to define your own feature detects that are not currently\n * included in Modernizr (under the covers it's the exact same code Modernizr\n * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)).\n * Just like the official detects, the result\n * will be added onto the Modernizr object, as well as an appropriate className set on\n * the html element when configured to do so\n *\n * @memberOf Modernizr\n * @name Modernizr.addTest\n * @optionName Modernizr.addTest()\n * @optionProp addTest\n * @access public\n * @function addTest\n * @param {string|object} feature - The string name of the feature detect, or an\n * object of feature detect names and test\n * @param {Function|boolean} test - Function returning true if feature is supported,\n * false if not. Otherwise a boolean representing the results of a feature detection\n * @returns {object} the Modernizr object to allow chaining\n * @example\n *\n * The most common way of creating your own feature detects is by calling\n * `Modernizr.addTest` with a string (preferably just lowercase, without any\n * punctuation), and a function you want executed that will return a boolean result\n *\n * ```js\n * Modernizr.addTest('itsTuesday', function() {\n * var d = new Date();\n * return d.getDay() === 2;\n * });\n * ```\n *\n * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,\n * and to `false` every other day of the week. One thing to notice is that the names of\n * feature detect functions are always lowercased when added to the Modernizr object. That\n * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.\n *\n *\n * Since we only look at the returned value from any feature detection function,\n * you do not need to actually use a function. For simple detections, just passing\n * in a statement that will return a boolean value works just fine.\n *\n * ```js\n * Modernizr.addTest('hasjquery', 'jQuery' in window);\n * ```\n *\n * Just like before, when the above runs `Modernizr.hasjquery` will be true if\n * jQuery has been included on the page. Not using a function saves a small amount\n * of overhead for the browser, as well as making your code much more readable.\n *\n * Finally, you also have the ability to pass in an object of feature names and\n * their tests. This is handy if you want to add multiple detections in one go.\n * The keys should always be a string, and the value can be either a boolean or\n * function that returns a boolean.\n *\n * ```js\n * var detects = {\n * 'hasjquery': 'jQuery' in window,\n * 'itstuesday': function() {\n * var d = new Date();\n * return d.getDay() === 2;\n * }\n * }\n *\n * Modernizr.addTest(detects);\n * ```\n *\n * There is really no difference between the first methods and this one, it is\n * just a convenience to let you write more readable code.\n */\n function addTest(feature, test) {\n\n if (typeof feature === 'object') {\n for (var key in feature) {\n if (hasOwnProp(feature, key)) {\n addTest(key, feature[ key ]);\n }\n }\n } else {\n\n feature = feature.toLowerCase();\n var featureNameSplit = feature.split('.');\n var last = Modernizr[featureNameSplit[0]];\n\n // Again, we don't check for parent test existence. Get that right, though.\n if (featureNameSplit.length === 2) {\n last = last[featureNameSplit[1]];\n }\n\n if (typeof last !== 'undefined') {\n // we're going to quit if you're trying to overwrite an existing test\n // if we were to allow it, we'd do this:\n // var re = new RegExp(\"\\\\b(no-)?\" + feature + \"\\\\b\");\n // docElement.className = docElement.className.replace( re, '' );\n // but, no rly, stuff 'em.\n return Modernizr;\n }\n\n test = typeof test === 'function' ? test() : test;\n\n // Set the value (this is the magic, right here).\n if (featureNameSplit.length === 1) {\n Modernizr[featureNameSplit[0]] = test;\n } else {\n // cast to a Boolean, if not one already\n if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {\n Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);\n }\n\n Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;\n }\n\n // Set a single class (either `feature` or `no-feature`)\n setClasses([(!!test && test !== false ? '' : 'no-') + featureNameSplit.join('-')]);\n\n // Trigger the event\n Modernizr._trigger(feature, test);\n }\n\n return Modernizr; // allow chaining.\n }\n\n // After all the tests are run, add self to the Modernizr prototype\n Modernizr._q.push(function() {\n ModernizrProto.addTest = addTest;\n });\n\n \n\n\n /**\n * @optionName html5printshiv\n * @optionProp html5printshiv\n */\n\n // Take the html5 variable out of the html5shiv scope so we can return it.\n var html5;\n if (!isSVG) {\n /**\n * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n */\n ;(function(window, document) {\n /*jshint evil:true */\n /** version */\n var version = '3.7.3';\n\n /** Preset options */\n var options = window.html5 || {};\n\n /** Used to skip problem elements */\n var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;\n\n /** Not all elements can be cloned in IE **/\n var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;\n\n /** Detect whether the browser supports default html5 styles */\n var supportsHtml5Styles;\n\n /** Name of the expando, to work with multiple documents or to re-shiv one document */\n var expando = '_html5shiv';\n\n /** The id for the the documents expando */\n var expanID = 0;\n\n /** Cached data for each document */\n var expandoData = {};\n\n /** Detect whether the browser supports unknown elements */\n var supportsUnknownElements;\n\n (function() {\n try {\n var a = document.createElement('a');\n a.innerHTML = '';\n //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles\n supportsHtml5Styles = ('hidden' in a);\n\n supportsUnknownElements = a.childNodes.length == 1 || (function() {\n // assign a false positive if unable to shiv\n (document.createElement)('a');\n var frag = document.createDocumentFragment();\n return (\n typeof frag.cloneNode == 'undefined' ||\n typeof frag.createDocumentFragment == 'undefined' ||\n typeof frag.createElement == 'undefined'\n );\n }());\n } catch(e) {\n // assign a false positive if detection fails => unable to shiv\n supportsHtml5Styles = true;\n supportsUnknownElements = true;\n }\n\n }());\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Creates a style sheet with the given CSS text and adds it to the document.\n * @private\n * @param {Document} ownerDocument The document.\n * @param {String} cssText The CSS text.\n * @returns {StyleSheet} The style element.\n */\n function addStyleSheet(ownerDocument, cssText) {\n var p = ownerDocument.createElement('p'),\n parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n p.innerHTML = 'x';\n return parent.insertBefore(p.lastChild, parent.firstChild);\n }\n\n /**\n * Returns the value of `html5.elements` as an array.\n * @private\n * @returns {Array} An array of shived element node names.\n */\n function getElements() {\n var elements = html5.elements;\n return typeof elements == 'string' ? elements.split(' ') : elements;\n }\n\n /**\n * Extends the built-in list of html5 elements\n * @memberOf html5\n * @param {String|Array} newElements whitespace separated list or array of new element names to shiv\n * @param {Document} ownerDocument The context document.\n */\n function addElements(newElements, ownerDocument) {\n var elements = html5.elements;\n if(typeof elements != 'string'){\n elements = elements.join(' ');\n }\n if(typeof newElements != 'string'){\n newElements = newElements.join(' ');\n }\n html5.elements = elements +' '+ newElements;\n shivDocument(ownerDocument);\n }\n\n /**\n * Returns the data associated to the given document\n * @private\n * @param {Document} ownerDocument The document.\n * @returns {Object} An object of data.\n */\n function getExpandoData(ownerDocument) {\n var data = expandoData[ownerDocument[expando]];\n if (!data) {\n data = {};\n expanID++;\n ownerDocument[expando] = expanID;\n expandoData[expanID] = data;\n }\n return data;\n }\n\n /**\n * returns a shived element for the given nodeName and document\n * @memberOf html5\n * @param {String} nodeName name of the element\n * @param {Document} ownerDocument The context document.\n * @returns {Object} The shived element.\n */\n function createElement(nodeName, ownerDocument, data){\n if (!ownerDocument) {\n ownerDocument = document;\n }\n if(supportsUnknownElements){\n return ownerDocument.createElement(nodeName);\n }\n if (!data) {\n data = getExpandoData(ownerDocument);\n }\n var node;\n\n if (data.cache[nodeName]) {\n node = data.cache[nodeName].cloneNode();\n } else if (saveClones.test(nodeName)) {\n node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();\n } else {\n node = data.createElem(nodeName);\n }\n\n // Avoid adding some elements to fragments in IE < 9 because\n // * Attributes like `name` or `type` cannot be set/changed once an element\n // is inserted into a document/fragment\n // * Link elements with `src` attributes that are inaccessible, as with\n // a 403 response, will cause the tab/window to crash\n // * Script elements appended to fragments will execute when their `src`\n // or `text` property is set\n return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;\n }\n\n /**\n * returns a shived DocumentFragment for the given document\n * @memberOf html5\n * @param {Document} ownerDocument The context document.\n * @returns {Object} The shived DocumentFragment.\n */\n function createDocumentFragment(ownerDocument, data){\n if (!ownerDocument) {\n ownerDocument = document;\n }\n if(supportsUnknownElements){\n return ownerDocument.createDocumentFragment();\n }\n data = data || getExpandoData(ownerDocument);\n var clone = data.frag.cloneNode(),\n i = 0,\n elems = getElements(),\n l = elems.length;\n for(;i+~])(' + getElements().join('|') + ')(?=[[\\\\s,>+~#.:]|$)', 'gi'),\n replacement = '$1' + shivNamespace + '\\\\:$2';\n\n while (index--) {\n pair = parts[index] = parts[index].split('}');\n pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);\n parts[index] = pair.join('}');\n }\n return parts.join('{');\n }\n\n /**\n * Removes the given wrappers, leaving the original elements.\n * @private\n * @params {Array} wrappers An array of printable wrappers.\n */\n function removeWrappers(wrappers) {\n var index = wrappers.length;\n while (index--) {\n wrappers[index].removeNode();\n }\n }\n\n /*--------------------------------------------------------------------------*/\n\n /**\n * Shivs the given document for print.\n * @memberOf html5\n * @param {Document} ownerDocument The document to shiv.\n * @returns {Document} The shived document.\n */\n function shivPrint(ownerDocument) {\n var shivedSheet,\n wrappers,\n data = getExpandoData(ownerDocument),\n namespaces = ownerDocument.namespaces,\n ownerWindow = ownerDocument.parentWindow;\n\n if (!supportsShivableSheets || ownerDocument.printShived) {\n return ownerDocument;\n }\n if (typeof namespaces[shivNamespace] == 'undefined') {\n namespaces.add(shivNamespace);\n }\n\n function removeSheet() {\n clearTimeout(data._removeSheetTimer);\n if (shivedSheet) {\n shivedSheet.removeNode(true);\n }\n shivedSheet= null;\n }\n\n ownerWindow.attachEvent('onbeforeprint', function() {\n\n removeSheet();\n\n var imports,\n length,\n sheet,\n collection = ownerDocument.styleSheets,\n cssText = [],\n index = collection.length,\n sheets = Array(index);\n\n // convert styleSheets collection to an array\n while (index--) {\n sheets[index] = collection[index];\n }\n // concat all style sheet CSS text\n while ((sheet = sheets.pop())) {\n // IE does not enforce a same origin policy for external style sheets...\n // but has trouble with some dynamically created stylesheets\n if (!sheet.disabled && reMedia.test(sheet.media)) {\n\n try {\n imports = sheet.imports;\n length = imports.length;\n } catch(er){\n length = 0;\n }\n\n for (index = 0; index < length; index++) {\n sheets.push(imports[index]);\n }\n\n try {\n cssText.push(sheet.cssText);\n } catch(er){}\n }\n }\n\n // wrap all HTML5 elements with printable elements and add the shived style sheet\n cssText = shivCssText(cssText.reverse().join(''));\n wrappers = addWrappers(ownerDocument);\n shivedSheet = addStyleSheet(ownerDocument, cssText);\n\n });\n\n ownerWindow.attachEvent('onafterprint', function() {\n // remove wrappers, leaving the original elements, and remove the shived style sheet\n removeWrappers(wrappers);\n clearTimeout(data._removeSheetTimer);\n data._removeSheetTimer = setTimeout(removeSheet, 500);\n });\n\n ownerDocument.printShived = true;\n return ownerDocument;\n }\n\n /*--------------------------------------------------------------------------*/\n\n // expose API\n html5.type += ' print';\n html5.shivPrint = shivPrint;\n\n // shiv for print\n shivPrint(document);\n\n if(typeof module == 'object' && module.exports){\n module.exports = html5;\n }\n\n }(typeof window !== \"undefined\" ? window : this, document));\n }\n\n ;\n\n /**\n * contains checks to see if a string contains another string\n *\n * @access private\n * @function contains\n * @param {string} str - The string we want to check for substrings\n * @param {string} substr - The substring we want to search the first string for\n * @returns {boolean} true if and only if the first string 'str' contains the second string 'substr'\n */\n function contains(str, substr) {\n return !!~('' + str).indexOf(substr);\n }\n\n ;\n\n /**\n * createElement is a convenience wrapper around document.createElement. Since we\n * use createElement all over the place, this allows for (slightly) smaller code\n * as well as abstracting away issues with creating elements in contexts other than\n * HTML documents (e.g. SVG documents).\n *\n * @access private\n * @function createElement\n * @returns {HTMLElement|SVGElement} An HTML or SVG element\n */\n function createElement() {\n if (typeof document.createElement !== 'function') {\n // This is the case in IE7, where the type of createElement is \"object\".\n // For this reason, we cannot call apply() as Object is not a Function.\n return document.createElement(arguments[0]);\n } else if (isSVG) {\n return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);\n } else {\n return document.createElement.apply(document, arguments);\n }\n }\n\n ;\n\n /**\n * Create our \"modernizr\" element that we do most feature tests on.\n *\n * @access private\n */\n var modElem = {\n elem: createElement('modernizr')\n };\n\n // Clean up this element\n Modernizr._q.push(function() {\n delete modElem.elem;\n });\n\n \n\n var mStyle = {\n style: modElem.elem.style\n };\n\n // kill ref for gc, must happen before mod.elem is removed, so we unshift on to\n // the front of the queue.\n Modernizr._q.unshift(function() {\n delete mStyle.style;\n });\n\n \n\n /**\n * getBody returns the body of a document, or an element that can stand in for\n * the body if a real body does not exist\n *\n * @access private\n * @function getBody\n * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an\n * artificially created element that stands in for the body\n */\n function getBody() {\n // After page load injecting a fake body doesn't work so check if body exists\n var body = document.body;\n\n if (!body) {\n // Can't use the real body create a fake one.\n body = createElement(isSVG ? 'svg' : 'body');\n body.fake = true;\n }\n\n return body;\n }\n\n ;\n\n /**\n * injectElementWithStyles injects an element with style element and some CSS rules\n *\n * @access private\n * @function injectElementWithStyles\n * @param {string} rule - String representing a css rule\n * @param {Function} callback - A function that is used to test the injected element\n * @param {number} [nodes] - An integer representing the number of additional nodes you want injected\n * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes\n * @returns {boolean} the result of the specified callback test\n */\n function injectElementWithStyles(rule, callback, nodes, testnames) {\n var mod = 'modernizr';\n var style;\n var ret;\n var node;\n var docOverflow;\n var div = createElement('div');\n var body = getBody();\n\n if (parseInt(nodes, 10)) {\n // In order not to give false positives we create a node for each test\n // This also allows the method to scale for unspecified uses\n while (nodes--) {\n node = createElement('div');\n node.id = testnames ? testnames[nodes] : mod + (nodes + 1);\n div.appendChild(node);\n }\n }\n\n style = createElement('style');\n style.type = 'text/css';\n style.id = 's' + mod;\n\n // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.\n // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270\n (!body.fake ? div : body).appendChild(style);\n body.appendChild(div);\n\n if (style.styleSheet) {\n style.styleSheet.cssText = rule;\n } else {\n style.appendChild(document.createTextNode(rule));\n }\n div.id = mod;\n\n if (body.fake) {\n //avoid crashing IE8, if background image is used\n body.style.background = '';\n //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\n body.style.overflow = 'hidden';\n docOverflow = docElement.style.overflow;\n docElement.style.overflow = 'hidden';\n docElement.appendChild(body);\n }\n\n ret = callback(div, rule);\n // If this is done after page load we don't want to remove the body so check if body exists\n if (body.fake && body.parentNode) {\n body.parentNode.removeChild(body);\n docElement.style.overflow = docOverflow;\n // Trigger layout so kinetic scrolling isn't disabled in iOS6+\n // eslint-disable-next-line\n docElement.offsetHeight;\n } else {\n div.parentNode.removeChild(div);\n }\n\n return !!ret;\n }\n\n ;\n\n /**\n * domToCSS takes a camelCase string and converts it to hyphen-case\n * e.g. boxSizing -> box-sizing\n *\n * @access private\n * @function domToCSS\n * @param {string} name - String name of camelCase prop we want to convert\n * @returns {string} The hyphen-case version of the supplied name\n */\n function domToCSS(name) {\n return name.replace(/([A-Z])/g, function(str, m1) {\n return '-' + m1.toLowerCase();\n }).replace(/^ms-/, '-ms-');\n }\n\n ;\n\n\n /**\n * wrapper around getComputedStyle, to fix issues with Firefox returning null when\n * called inside of a hidden iframe\n *\n * @access private\n * @function computedStyle\n * @param {HTMLElement|SVGElement} elem - The element we want to find the computed styles of\n * @param {string|null} [pseudo] - An optional pseudo element selector (e.g. :before), of null if none\n * @param {string} prop - A CSS property\n * @returns {CSSStyleDeclaration} the value of the specified CSS property\n */\n function computedStyle(elem, pseudo, prop) {\n var result;\n\n if ('getComputedStyle' in window) {\n result = getComputedStyle.call(window, elem, pseudo);\n var console = window.console;\n\n if (result !== null) {\n if (prop) {\n result = result.getPropertyValue(prop);\n }\n } else {\n if (console) {\n var method = console.error ? 'error' : 'log';\n console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');\n }\n }\n } else {\n result = !pseudo && elem.currentStyle && elem.currentStyle[prop];\n }\n\n return result;\n }\n\n ;\n\n /**\n * nativeTestProps allows for us to use native feature detection functionality if available.\n * some prefixed form, or false, in the case of an unsupported rule\n *\n * @access private\n * @function nativeTestProps\n * @param {Array} props - An array of property names\n * @param {string} value - A string representing the value we want to check via @supports\n * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise\n */\n // Accepts a list of property names and a single value\n // Returns `undefined` if native detection not available\n function nativeTestProps(props, value) {\n var i = props.length;\n // Start with the JS API: https://www.w3.org/TR/css3-conditional/#the-css-interface\n if ('CSS' in window && 'supports' in window.CSS) {\n // Try every prefixed variant of the property\n while (i--) {\n if (window.CSS.supports(domToCSS(props[i]), value)) {\n return true;\n }\n }\n return false;\n }\n // Otherwise fall back to at-rule (for Opera 12.x)\n else if ('CSSSupportsRule' in window) {\n // Build a condition string for every prefixed variant\n var conditionText = [];\n while (i--) {\n conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');\n }\n conditionText = conditionText.join(' or ');\n return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {\n return computedStyle(node, null, 'position') === 'absolute';\n });\n }\n return undefined;\n }\n ;\n\n /**\n * cssToDOM takes a hyphen-case string and converts it to camelCase\n * e.g. box-sizing -> boxSizing\n *\n * @access private\n * @function cssToDOM\n * @param {string} name - String name of hyphen-case prop we want to convert\n * @returns {string} The camelCase version of the supplied name\n */\n function cssToDOM(name) {\n return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {\n return m1 + m2.toUpperCase();\n }).replace(/^-/, '');\n }\n\n ;\n\n // testProps is a generic CSS / DOM property test.\n\n // In testing support for a given CSS property, it's legit to test:\n // `elem.style[styleName] !== undefined`\n // If the property is supported it will return an empty string,\n // if unsupported it will return undefined.\n\n // We'll take advantage of this quick test and skip setting a style\n // on our modernizr element, but instead just testing undefined vs\n // empty string.\n\n // Property names can be provided in either camelCase or hyphen-case.\n\n function testProps(props, prefixed, value, skipValueTest) {\n skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;\n\n // Try native detect first\n if (!is(value, 'undefined')) {\n var result = nativeTestProps(props, value);\n if (!is(result, 'undefined')) {\n return result;\n }\n }\n\n // Otherwise do it properly\n var afterInit, i, propsLength, prop, before;\n\n // If we don't have a style element, that means we're running async or after\n // the core tests, so we'll need to create our own elements to use.\n\n // Inside of an SVG element, in certain browsers, the `style` element is only\n // defined for valid tags. Therefore, if `modernizr` does not have one, we\n // fall back to a less used element and hope for the best.\n // For strict XHTML browsers the hardly used samp element is used.\n var elems = ['modernizr', 'tspan', 'samp'];\n while (!mStyle.style && elems.length) {\n afterInit = true;\n mStyle.modElem = createElement(elems.shift());\n mStyle.style = mStyle.modElem.style;\n }\n\n // Delete the objects if we created them.\n function cleanElems() {\n if (afterInit) {\n delete mStyle.style;\n delete mStyle.modElem;\n }\n }\n\n propsLength = props.length;\n for (i = 0; i < propsLength; i++) {\n prop = props[i];\n before = mStyle.style[prop];\n\n if (contains(prop, '-')) {\n prop = cssToDOM(prop);\n }\n\n if (mStyle.style[prop] !== undefined) {\n\n // If value to test has been passed in, do a set-and-check test.\n // 0 (integer) is a valid property value, so check that `value` isn't\n // undefined, rather than just checking it's truthy.\n if (!skipValueTest && !is(value, 'undefined')) {\n\n // Needs a try catch block because of old IE. This is slow, but will\n // be avoided in most cases because `skipValueTest` will be used.\n try {\n mStyle.style[prop] = value;\n } catch (e) {}\n\n // If the property value has changed, we assume the value used is\n // supported. If `value` is empty string, it'll fail here (because\n // it hasn't changed), which matches how browsers have implemented\n // CSS.supports()\n if (mStyle.style[prop] !== before) {\n cleanElems();\n return prefixed === 'pfx' ? prop : true;\n }\n }\n // Otherwise just return true, or the property name if this is a\n // `prefixed()` call\n else {\n cleanElems();\n return prefixed === 'pfx' ? prop : true;\n }\n }\n }\n cleanElems();\n return false;\n }\n\n ;\n\n /**\n * testProp() investigates whether a given style property is recognized\n * Property names can be provided in either camelCase or hyphen-case.\n *\n * @memberOf Modernizr\n * @name Modernizr.testProp\n * @access public\n * @optionName Modernizr.testProp()\n * @optionProp testProp\n * @function testProp\n * @param {string} prop - Name of the CSS property to check\n * @param {string} [value] - Name of the CSS value to check\n * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported\n * @returns {boolean} an empty string if the property is supported, undefined if its unsupported\n * @example\n *\n * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed\n * version of the string.\n *\n * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)\n *\n * ```js\n * Modernizr.testProp('pointerEvents') // true\n * ```\n *\n * You can also provide a value as an optional second argument to check if a\n * specific value is supported\n *\n * ```js\n * Modernizr.testProp('pointerEvents', 'none') // true\n * Modernizr.testProp('pointerEvents', 'penguin') // false\n * ```\n */\n var testProp = ModernizrProto.testProp = function(prop, value, useValue) {\n return testProps([prop], undefined, value, useValue);\n };\n\n \n\n /**\n * List of property values to set for css tests. See ticket #21\n * https://github.com/modernizr/modernizr/issues/21\n *\n * @memberOf Modernizr\n * @name Modernizr._prefixes\n * @optionName Modernizr._prefixes\n * @optionProp prefixes\n * @access public\n * @example\n *\n * Modernizr._prefixes is the internal list of prefixes that we test against\n * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply\n * an array of hyphen-case vendor prefixes you can use within your code.\n *\n * Some common use cases include\n *\n * Generating all possible prefixed version of a CSS property\n * ```js\n * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');\n *\n * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'\n * ```\n *\n * Generating all possible prefixed version of a CSS value\n * ```js\n * rule = 'display:' + Modernizr._prefixes.join('flex; display:') + 'flex';\n *\n * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'\n * ```\n */\n // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test\n // values in feature detects to continue to work\n var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);\n\n // expose these for the plugin API. Look in the source for how to join() them against your input\n ModernizrProto._prefixes = prefixes;\n\n \n\n /**\n * Modernizr.mq tests a given media query, live against the current state of the window\n * adapted from matchMedia polyfill by Scott Jehl and Paul Irish\n * gist.github.com/786768\n *\n * @memberOf Modernizr\n * @name Modernizr.mq\n * @optionName Modernizr.mq()\n * @optionProp mq\n * @access public\n * @function mq\n * @param {string} mq - String of the media query we want to test\n * @returns {boolean}\n * @example\n * Modernizr.mq allows for you to programmatically check if the current browser\n * window state matches a media query.\n *\n * ```js\n * var query = Modernizr.mq('(min-width: 900px)');\n *\n * if (query) {\n * // the browser window is larger than 900px\n * }\n * ```\n *\n * Only valid media queries are supported, therefore you must always include values\n * with your media query\n *\n * ```js\n * // good\n * Modernizr.mq('(min-width: 900px)');\n *\n * // bad\n * Modernizr.mq('min-width');\n * ```\n *\n * If you would just like to test that media queries are supported in general, use\n *\n * ```js\n * Modernizr.mq('only all'); // true if MQ are supported, false if not\n * ```\n *\n * Note that if the browser does not support media queries (e.g. old IE) mq will\n * always return false.\n */\n var mq = (function() {\n var matchMedia = window.matchMedia || window.msMatchMedia;\n if (matchMedia) {\n return function(mq) {\n var mql = matchMedia(mq);\n return mql && mql.matches || false;\n };\n }\n\n return function(mq) {\n var bool = false;\n\n injectElementWithStyles('@media ' + mq + ' { #modernizr { position: absolute; } }', function(node) {\n bool = computedStyle(node, null, 'position') === 'absolute';\n });\n\n return bool;\n };\n })();\n\n ModernizrProto.mq = mq;\n\n \n/*!\n{\n \"name\": \"Touch Events\",\n \"property\": \"touchevents\",\n \"caniuse\": \"touch\",\n \"tags\": [\"media\", \"attribute\"],\n \"notes\": [{\n \"name\": \"Touch Events spec\",\n \"href\": \"https://www.w3.org/TR/2013/WD-touch-events-20130124/\"\n }],\n \"warnings\": [\n \"** DEPRECATED see https://github.com/Modernizr/Modernizr/pull/2432 **\",\n \"Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device\"\n ],\n \"knownBugs\": [\n \"False-positive on some configurations of Nokia N900\",\n \"False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695\"\n ]\n}\n!*/\n/* DOC\nIndicates if the browser supports the W3C Touch Events API.\n\nThis *does not* necessarily reflect a touchscreen device:\n\n* Older touchscreen devices only emulate mouse events\n* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that\n* Some browsers & OS setups may enable touch APIs when no touchscreen is connected\n* Future browsers may implement other event models for touch interactions\n\nSee this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).\n\nIt's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](https://www.html5rocks.com/en/mobile/touchandmouse/).\n\nThis test will also return `true` for Firefox 4 Multitouch support.\n*/\n\n // Chrome (desktop) used to lie about its support on this, but that has since been rectified: https://bugs.chromium.org/p/chromium/issues/detail?id=36415\n // Chrome also changed its behaviour since v70 and recommends the TouchEvent object for detection: https://www.chromestatus.com/feature/4764225348042752\n Modernizr.addTest('touchevents', function() {\n if (('ontouchstart' in window) || window.TouchEvent || window.DocumentTouch && document instanceof DocumentTouch) {\n return true;\n }\n\n // include the 'heartz' as a way to have a non matching MQ to help terminate the join\n // https://github.com/Modernizr/Modernizr/issues/1814\n var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');\n return mq(query);\n });\n\n\n // Run each test\n testRunner();\n\n // Remove the \"no-js\" class if it exists\n setClasses(classes);\n\n delete ModernizrProto.addTest;\n delete ModernizrProto.addAsyncTest;\n\n // Run the things that are supposed to run after the tests\n for (var i = 0; i < Modernizr._q.length; i++) {\n Modernizr._q[i]();\n }\n\n // Leak Modernizr namespace\n scriptGlobalObject.Modernizr = Modernizr;\n\n\n;\n\n})(window, window, document);\n","import { getStorage } from \"./keyvaluestorage.js\";\n\nconst svgIconSelector = 'svg.c-icon';\nconst fileInfoSelector = 'span.c-file-info';\nconst svgFile = '/images/svg.svg';\n\nfunction getSvgUrl(el) {\n\tconst attributed = el?.getAttribute('data-svg-url');\n\tif (attributed) {\n\t\treturn attributed;\n\t}\n\tconst scriptUrl = getStorage().getStoredValue('scriptUrl') ?? '';\n\tif (scriptUrl){\n\t\tconst path = new URL(scriptUrl)?.pathname;\n\t\tconst endOfResourcePath = path?.indexOf('/js/') ?? -1;\n\t\tif (endOfResourcePath > -1) {\n\t\t\tconst relativePath = path.substring(0,endOfResourcePath);\n\t\t\treturn `${relativePath}${svgFile}`\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction getYesterday(el) { return el?.getAttribute('data-yesterday'); }\n\nfunction renderIconTemplate(el, iconName, svgUrl) {\n\tif (!el || !iconName) {\n\t\treturn false;\n\t}\n\tif (!el.querySelector(svgIconSelector) && svgUrl) {\n\t\treturn ``;\n\t} else {\n\t\treturn false;\n\t}\n}\n\nfunction renderSizeTemplate(el, type, size) {\n\tif (!el) {\n\t\treturn false;\n\t}\n\tif (!el.querySelector(fileInfoSelector) && type && size) {\n\t\treturn `(${type} - ${size})`;\n\t} else {\n\t\treturn false;\n\t}\n}\n/*\n * Add a leading 0 to numbers < max\n */\n\nfunction _pad(n, max = 10) {\n\treturn (n < max) ? ('0' + n) : n;\n}\n\n/*\n * Replaces the string in the data-yesterday attribute\n * with the date of yesterday in the format DD-MM-YYYY\n */\n\nexport function replaceYesterday(node) {\n\t// only preceed if the attribute exists and contains something other than spaces\n\tlet yesterday = getYesterday(node);\n\tif (yesterday && !!yesterday.replace(/\\s/g, '').length) {\n\t\tconst d = new Date();\n\t\td.setDate(d.getDate() - 1); // set date to yesterday\n\t\tconst yesterdate = `${_pad(d.getDate())}-${_pad(d.getMonth() + 1)}-${d.getFullYear()}`;\n\t\tconst html = node.innerHTML;\n\t\tconst regex = new RegExp(yesterday, 'gi');\n\t\tconst replacedHtml = html.replace(regex, yesterdate);\n\n\t\t// Only replace the html when something was replaced\n\t\tif (html !== replacedHtml) {\n\t\t\tnode.innerHTML = replacedHtml;\n\t\t}\n\t}\n}\n\n\nexport function enhanceLinks(node) {\n\tconst _links = [...node.querySelectorAll('a:not(.c-link):not(.c-button):not([id^=term]):not([data-role])')];\n\n\t_links.forEach( link => {\n\t\tif (!(link.querySelector('.c-link__text'))) {\n\t\t\tconst content = link.innerHTML;\n\t\t\tlink.innerHTML = `${content}`;\n\t\t}\n\t\tlink.classList.add('c-link');\n\t});\n}\n\nexport function enhanceExternals(node) {\n\tconst _links = [...node.querySelectorAll('a[rel=\"external\"]')];\n\tconst svgUrl = getSvgUrl(node);\n\n\t_links.forEach(link => {\n\t\tlet svgPart = renderIconTemplate(link, 'external-link', svgUrl);\n\n\t\tif (svgPart){\n\t\t\tlink.insertAdjacentHTML('beforeend', svgPart);\n\t\t}\n\t});\n}\n\nexport function enhanceType(node) {\n\tconst _links = [...node.querySelectorAll('[data-type]')];\n\tconst svgUrl = getSvgUrl(node);\n\n\t_links.forEach(link => {\n\t\tlet type = link.getAttribute('data-type');\n\t\tlet svgPart = renderIconTemplate(link, type, svgUrl);\n\n\t\tif (svgPart) {\n\t\t\tlink.insertAdjacentHTML('afterbegin', svgPart);\n\t\t}\n\t});\n}\n\nexport function enhanceSize(node) {\n\tconst _links = [...node.querySelectorAll('[data-size]')];\n\n\t_links.forEach(link => {\n\t\tlet type = link.getAttribute('data-type');\n\t\tlet size = link.getAttribute('data-size');\n\t\tlet sizePart = renderSizeTemplate(link, type, size);\n\t\tif (sizePart) {\n\t\t\tlink.insertAdjacentHTML('beforeend', sizePart);\n\t\t}\n\t});\n}\n\nexport function runLinkEnhancements(node) {\n\tenhanceLinks(node);\n\tenhanceSize(node);\n\tenhanceType(node);\n\tenhanceExternals(node);\n\treturn node;\n}\n","const triggers = {};\n/**\n * register a trigger\n * @param {string} triggerName - name of the trigger\n */\nexport function registerTrigger(triggerName) {\n if (!triggers[triggerName]) {\n triggers[triggerName] = [];\n }\n}\n/**\n * register multiple triggers at once\n * @param {Array} triggerNames - array of trigger names\n */\nexport function registerTriggers(triggerNames) {\n if (triggerNames && triggerNames.length > 0 && triggerNames.forEach) {\n triggerNames.forEach(registerTrigger);\n }\n}\n\n/**\n * reset all subscriptions to a single trigger\n * @param {string} triggerName - name of the trigger\n */\nexport function resetTrigger(triggerName) {\n triggers[triggerName] = [];\n}\n\n/**\n * reset all subscriptions to every trigger in the array\n * @param {Array} triggerNames - array of trigger names\n */\nexport function resetTriggers(triggerNames) {\n if (triggerNames && triggerNames.length > 0 && triggerNames.forEach) {\n triggerNames.forEach(resetTrigger);\n }\n}\n\n/**\n * subscribe to the notification by triggername\n * @param {string} triggerName - name of the trigger to subscribe to\n * @param {function} fn - function to execute on trigger\n */\nexport function subscribeNotify(triggerName, fn) {\n if (!triggers[triggerName]) {\n triggers[triggerName] = [];\n }\n if (fn && typeof fn === 'function') {\n triggers[triggerName].push(fn)\n }\n}\n\n/**\n * subscribe to the notification by triggername and more specific bij naming the function\n * @param {string} triggerName - name of the trigger to subscribe to\n * @param {function} fn - function to execute on trigger\n * @param {string} name - name of the function to execute\n */\nexport function subscribeNamedNotify(triggerName, {fn, name}) {\n if (!triggers[triggerName]) {\n triggers[triggerName] = [];\n }\n if (fn && typeof fn === 'function' && name && typeof name === 'string') {\n triggers[triggerName].push({name, fn});\n }\n}\n\n/**\n * subscribe to the notification by triggername and more specific bij unique naming on the function\n * so there can only be one function with a certain name subscribed to a trigger enabling returning a value\n * if there is already a function with a certain name subscribed to a trigger it will be replaced\n * @param {string} triggerName - name of the trigger to subscribe to\n * @param {function} fn - function to execute on trigger\n * @param {string} name - unique name of the function to execute\n */\nexport function subscribeUniqueNamedNotify(triggerName, {fn, name}) {\n if (!triggers[triggerName]) {\n triggers[triggerName] = [];\n }\n if (fn && typeof fn === 'function' && name && typeof name === 'string') {\n let tr = triggers[triggerName].find(trigger => trigger.name === name);\n if (tr) {\n tr.fn = fn;\n } else {\n triggers[triggerName].push({name, fn});\n }\n }\n}\n\n/**\n * unsubscribe from the notification by triggername\n * @param {string} triggerName - name of the trigger to unsubscribe from\n * @param {function} fn - function to unsubscribe\n */\nexport function unsubscribeNotify(triggerName, fn) {\n if (!triggers[triggerName]) {\n return;\n }\n if (fn && typeof fn === 'function') {\n triggers[triggerName] = triggers[triggerName].filter(fun => fun !== fn);\n }\n}\n\n/**\n * unsubscribe from the notification by triggername and more specific bij the function name\n * @param {string} triggerName - name of the trigger to unsubscribe from\n * @param {function} fn - function to unsubscribe\n * @param {string} name - name of the function to unsubscribe\n */\nexport function unsubscribeNamedNotify(triggerName, {fn, name}) {\n if (!triggers[triggerName]) {\n return;\n }\n if (fn && typeof fn === 'function' && name && typeof name === 'string') {\n triggers[triggerName] = triggers[triggerName].filter(obj => obj.name !== name && obj.fn !== fn);\n }\n}\n\n/**\n * unsubscribe from the notification by triggername and more specific bij the function name\n * @param {string} triggerName - name of the trigger to unsubscribe from\n * @param {function} fn - function to unsubscribe\n * @param {string} name - name of the function to unsubscribe\n */\nexport function unsubscribeUniqueNamedNotify(triggerName, {fn, name}) {\n if (!triggers[triggerName]) {\n return;\n }\n if (fn && typeof fn === 'function' && name && typeof name === 'string') {\n triggers[triggerName] = triggers[triggerName].filter(obj => obj.name !== name);\n }\n}\n\n/************************\n * All trigger functions are defined as async functions\n * Async functions always return Promises\n * When more than one function has subscribed to the notification they are executed in parallel\n * by means of Promise.all\n ************************/\n\n/**\n * trigger the subscribed functions and possibly pass them some arguments\n * @param {string} triggerName - name of the trigger\n * @param {Array} args - argument collection to pass to the subscribed functions\n * @returns an Array of promises that will resolve with true or reject with an error\n */\nexport async function triggerNotify(triggerName, ...args) {\n if (!triggers[triggerName]) {\n return;\n }\n\n const promiseArray = triggers[triggerName].map(fun => fun(...args));\n return Promise.all(promiseArray);\n}\n\n/**\n * trigger the subscribed functions that have the same name and possibly pass them some arguments\n * @param {string} triggerName - name of the trigger\n * @param {object} args - arguments to pass to the subscribed functions\n * @param {string} name - name of the function\n * @returns an Array of promises that will resolve with true or reject with an error\n */\nexport async function triggerNamedNotify(triggerName, {name, args = {}}) {\n if (!triggers[triggerName] || !(triggers[triggerName].length > 0 && name && typeof name === 'string')) {\n return;\n }\n let namedFuns = triggers[triggerName].filter(obj => obj.name === name && typeof obj.fn === 'function') || [];\n const promiseArray = namedFuns.map(namedFun => namedFun.fn(args));\n return Promise.all(promiseArray);\n}\n\n/**\n * trigger the unique subscribed function with the specified name and possibly pass it some arguments\n * @param {string} triggerName - name of the trigger\n * @param {object} args - arguments to pass to the subscribed functions\n * @param {string} name - name of the function\n * @returns a promise that will resolve with the result of the function or reject with an error\n */\nexport async function triggerUniqueNamedNotify(triggerName, {name, args = {}}) {\n if (!triggers[triggerName]) {\n throw new Error(`trigger with name: ${triggerName} does not exist!`);\n }\n if (triggers[triggerName].length > 0 && name && typeof name === 'string' ) {\n let namedFun = triggers[triggerName].find(obj => obj.name === name && typeof obj.fn === 'function');\n if (namedFun) {\n return namedFun.fn(args);\n }\n }\n}","/**\n * Module based on Lea Verou's Awesomplete, http://leaverou.github.io/awesomplete a simple, lightweight, usable local autocomplete library for modern browsers\n * @author Serge Huijben\n * MIT license\n *\n * autosuggestUrl should be like 'https://autosuggest.iqnomy.com/autosuggest/api/suggest/dictionary/'\n */\nimport { registerTriggers, triggerNotify } from \"./@helpers/js/observer.js\";\n\n\n// Helpers\n\nconst slice = Array.prototype.slice;\n\nconst $ = (expr, con) => typeof expr === 'string' ? (con || document).querySelector(expr) : expr || null;\n\nconst $$ = (expr, con) => slice.call((con || document).querySelectorAll(expr));\n\n$.create = (tag, o) => {\n const element = document.createElement(tag);\n\n for (let i in o) {\n let val = o[i];\n\n if (i === 'inside') {\n $(val).appendChild(element);\n } else if (i === 'after') {\n let afterref = $(val);\n afterref.parentNode.insertBefore(element, afterref.nextSibling);\n } else if (i === 'around') {\n let ref = $(val);\n ref.parentNode.insertBefore(element, ref);\n element.appendChild(ref);\n } else if (i in element) {\n element[i] = val;\n } else {\n element.setAttribute(i, val);\n }\n }\n\n return element;\n};\n\n$.getQueryString = (name, raw = false) => {\n if (!name || typeof name !== 'string') {\n return '';\n }\n let params = location.search && location.search.length > 0 && location.search.indexOf(name) > -1 ? location.search.substring(1).split(\"&\") :\n location.hash && location.hash.length > 0 && location.hash.indexOf(name) > -1 ? location.hash.substring(1).split(\"&\") : [];\n\n for(let i = 0; i < params.length; i++)\n {\n params[i] = params[i].replace(/\\+/g, ' ');\n \n }\n\n for (let param of params) {\n const p = param.split('=');\n if (p[0]?.toLowerCase() === name.toLowerCase())\n return raw ? p[1] : decodeURIComponent(p[1]);\n }\n return '';\n}\n\n$.regExpEscape = (s) => s.replace(/[-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n\n$.siblingIndex = (el) => {\n /* eslint-disable no-cond-assign */\n let i = 0;\n while (el.previousElementSibling) {\n el = el.previousElementSibling;\n i++;\n }\n return i;\n};\n\n// Static methods/properties\nconst FILTER_CONTAINS = (text, input) => new RegExp($.regExpEscape(input.trim()), 'i').test(text);\n\nconst FILTER_STARTSWITH = (text, input) => new RegExp('^' + $.regExpEscape(input.trim()), 'i').test(text);\n\nconst SORT_BYLENGTH = (a, b) => (a.length !== b.length) ? a.length - b.length : a < b ? -1 : 1;\n\nconst MARKTEXT = (text, input) => input === '' ? text : text.replace(new RegExp($.regExpEscape(input.trim()), 'gi'), '$&');\n\nconst ITEM = (html) => `
${html}
`;\n\nconst MAKETEXT = (text, href) => !href ? text : `${text}`;\n\nclass SearchAwesomplete {\n\n constructor(element, {\n caption = 'Suggestions',\n autosuggestUrl = '',\n method = 'GET',\n key = 'key',\n autosuggestKey = 'query',\n autofocus = false,\n sort = true,\n filter = false,\n minChars = 2,\n maxItems = 10,\n autoFirst = false\n } = {}) {\n this._options = {\n caption,\n autosuggestUrl,\n method,\n key,\n autosuggestKey,\n autofocus,\n sort,\n filter,\n minChars,\n maxItems,\n autoFirst\n };\n this._element = element;\n this.input = $(this._element.querySelector('input.c-search-awesomplete__input'));\n this.submitButton = $(this._element.querySelector('[data-search-awesomplete-button]')) // use this attribute only if you want autosuggest on button click\n this.autosuggestDictionary = $(this._element.querySelector('.c-search-awesomplete__hiddendictionary'));\n this.notFoundTemplate = $(this._element.querySelector('[data-awesomplete-404]'));\n\n if (this.input) {\n this._init();\n }\n }\n\n // Setup\n _init() {\n this.input.setAttribute('autocomplete', 'off');\n this.input.setAttribute('aria-autocomplete', 'list');\n this.input.value = $.getQueryString(this._options.key);\n\n this.filter = FILTER_CONTAINS;\n this.sort = SORT_BYLENGTH;\n this.item = ITEM;\n this.makeText = MAKETEXT;\n\n this.index = -1;\n\n this._createElements();\n\n this._bindEvents();\n\n if (this.input.hasAttribute('list')) {\n this.list = '#' + this.input.getAttribute('list');\n this.input.removeAttribute('list');\n } else {\n this.list = this.input.getAttribute('data-list') || this._options.list || [];\n }\n\n if (this.input.value && this._options.autofocus === true)\n window.setTimeout(()=>this.input.focus(),100);\n registerTriggers([\n \"awesomplete-highlight\",\n \"awesomplete-close\",\n \"awesomplete-open\",\n \"awesomplete-select\",\n \"awesomplete-selectcomplete\",\n ]);\n }\n\n // Create necessary elements\n _createElements() {\n\n this.container = $.create('div', {\n className: 'awesomplete',\n around: this.input\n });\n\n this.innerContainer = this._element.tagName === 'FORM' ? $.create('div', {\n className: 'c-search-awesomplete__list',\n hidden: 'hidden',\n inside: this.container\n }) : $.create('div', {\n className: 'c-search-awesomplete__list',\n hidden: 'hidden',\n after: $(this._element.querySelector('form.c-search-form__querybox'))\n });\n\n this.caption = $.create('span', {\n className: 'caption',\n inside: this.innerContainer\n });\n this.caption.innerHTML = this._options.caption;\n\n this.ul = $.create('ul', {\n inside: this.innerContainer\n });\n\n this.notFound = $.create('div', {\n className: 'c-search-awesomplete__list-404',\n inside: this.innerContainer\n });\n\n this.status = $.create('span', {\n className: 't-visuallyhidden',\n role: 'status',\n 'aria-live': 'assertive',\n 'aria-atomic': 'true',\n 'aria-relevant': 'additions',\n inside: this.container\n });\n\n }\n\n // Bind events\n _bindEvents() {\n\n if (this.input) {\n ['click','touchend','focus'].forEach((event) => {\n this.input.addEventListener(event, () => {\n if (this.timeoutID && typeof this.timeoutID === 'number') {\n window.clearTimeout(this.timeoutID);\n }\n this.timeoutID = window.setTimeout(() => {\n if (this.inputValueBackup && this.input.value && this.input.value === this.inputValueBackup && ((this.notFoundBackup && this.notFoundBackup.length > 0) || (this.ulBackup && this.ulBackup.length > 0))) {\n this.ul.innerHTML = this.ulBackup;\n this.notFound.innerHTML = this.notFoundBackup;\n this.open();\n } else if (!this.input.value || this.input.value.length < this._options.minChars) {\n this.close({reason:'clear'});\n } else {\n this.evaluate();\n }\n },200);\n });\n });\n this.input.addEventListener('input', () => this.wrapEvaluation());\n this.input.addEventListener('blur', () => this.close({reason: 'blur'}));\n this.input.addEventListener('keydown', (evt) => {\n const c = evt.keyCode;\n\n // If the dropdown `ul` is in view, then act on keydown for the following keys:\n // Enter / Esc / Up / Down\n if (this.opened) {\n if (c === 13) { // Enter\n if (this.selected) {\n evt.preventDefault();\n this.select();\n } else {\n let count = this.ul.children.length;\n if (count <= 0) {\n let linkToSearch = this.notFound.querySelector('.c-link');\n if (linkToSearch && linkToSearch.getAttribute('aria-selected') && linkToSearch.getAttribute('aria-selected') === 'true' && linkToSearch.href) {\n history.replaceState({foo:'bar'}, \"\", `${window.location.href.split('?')[0]}?${linkToSearch.href.split('?')[1] ? linkToSearch.href.split('?')[1] : '' }`);\n window.location = linkToSearch.href;\n this.close({\n reason: 'link'\n });\n }\n }\n }\n } else if (c === 27) { // Esc\n this.close({\n reason: 'esc'\n });\n } else if (c === 38 || c === 40) { // Down/Up arrow\n evt.preventDefault();\n let count = this.ul.children.length;\n if (count <= 0) {\n let linkToSearch = this.notFound.querySelector('.c-link');\n if (linkToSearch) {\n let toggle = linkToSearch.getAttribute('aria-selected') && linkToSearch.getAttribute('aria-selected') === 'true';\n linkToSearch.setAttribute('aria-selected', !toggle);\n }\n } else {\n this[c === 38 ? 'previous' : 'next'](count);\n }\n }\n }\n });\n const forbiddenChars = /[<>{}[\\]$\"'/]/g;\n // Act on keypress and paste action for the following keys:\n // < > ' \" $ { } [ ] / keys\n this.input.addEventListener('input', (evt) => {\n this.input.value = this.input.value.replace(forbiddenChars, '')\n evt.preventDefault();\n });\n }\n\n if (this.submitButton) {\n this.submitButton.addEventListener('click', (evt) => {\n evt.preventDefault();\n this.evaluate(true);\n });\n }\n\n if (this.input && this.input.form) {\n this.input.form.addEventListener('submit', () => this.close({reason: 'submit'}));\n }\n\n if (this.ul) {\n this.ul.addEventListener('mousedown', (evt) => {\n let li = evt.target;\n\n if (li !== this) {\n\n while (li && !/li/i.test(li.nodeName)) {\n li = li.parentNode;\n }\n\n if (li && evt.button === 0) { // Only select on left click\n evt.preventDefault();\n this.select(li, evt.target);\n }\n }\n });\n }\n }\n\n set list(list) {\n if (Array.isArray(list)) {\n this._list = list;\n } else if (typeof list === 'string' && list.indexOf(',') > -1) {\n this._list = list.split(/\\s*,\\s*/);\n } else { // Element or CSS selector\n list = $(list);\n\n if (list && list.children) {\n const items = [];\n slice.apply(list.children).forEach(function(el) {\n if (!el.disabled) {\n const text = el.textContent.trim();\n const value = el.value || text;\n const label = el.label || text;\n if (value !== '') {\n items.push({\n label: label,\n value: value\n });\n }\n }\n });\n this._list = items;\n }\n }\n\n if (document.activeElement === this.input) {\n this.wrapEvaluation();\n }\n }\n\n get list() {\n return this._list;\n }\n\n get selected() {\n return this.index > -1;\n }\n\n get opened() {\n return !this.innerContainer.hasAttribute('hidden');\n }\n\n close(o) {\n if (!this.opened) {\n return;\n }\n const ms = o && o.reason && o.reason === 'clear' ? 10 : 200;\n window.setTimeout(() => {\n this.innerContainer.setAttribute('hidden', '');\n if (this.input.value && this.input.value.length >= this._options.minChars) {\n this.inputValueBackup = `${this.input.value}`;\n this.notFoundBackup = `${this.notFound.innerHTML}`;\n this.ulBackup = `${this.ul.innerHTML}`;\n }\n this.notFound.innerHTML = '';\n this.ul.innerHTML = '';\n }, ms);\n this.index = -1;\n\n triggerNotify('awesomplete-close', o || {});\n }\n\n open() {\n this.innerContainer.removeAttribute('hidden');\n\n if (this._options.autoFirst && this.index === -1) {\n this.goto(0);\n }\n\n triggerNotify('awesomplete-open');\n }\n\n next(count) {\n this.goto(this.index < count - 1 ? this.index + 1 : -1);\n }\n\n previous(count) {\n this.goto(this.selected ? this.index - 1 : count - 1);\n }\n\n // Should not be used, highlights specific item without any checks!\n goto(i) {\n const lis = this.ul.children;\n\n if (this.selected) {\n lis[this.index].setAttribute('aria-selected', 'false');\n }\n\n this.index = i;\n\n if (i > -1 && lis.length > 0) {\n lis[i].setAttribute('aria-selected', 'true');\n this.status.textContent = lis[i].textContent;\n\n triggerNotify('awesomplete-highlight', {\n text: this.suggestions[this.index]\n });\n }\n }\n\n select(selected, origin) {\n if (selected) {\n this.index = $.siblingIndex(selected);\n } else {\n selected = this.ul.children[this.index];\n }\n\n if (selected) {\n const suggestion = this.suggestions[this.index];\n if (suggestion.href) {\n const searchable = `${this._options.key}=${$.getQueryString(this._options.key, true)}`;\n if (window.location.href.indexOf(searchable) === -1) {\n history.replaceState({foo:'bar'}, \"\", `${window.location.href.indexOf('?') > -1 ? window.location.href + '&' : window.location.href + '?'}${this._options.key}=${this.input.value}`);\n } else if (this.input.value !== $.getQueryString(this._options.key)) {\n history.replaceState({foo:'bar'}, \"\", window.location.href.replace(searchable, `${this._options.key}=${this.input.value}`));\n }\n window.location = suggestion.href;\n this.close({\n reason: 'link'\n });\n } else {\n const allowed = triggerNotify('awesomplete-select', {\n text: suggestion,\n origin: origin || selected\n });\n\n if (allowed) {\n this.input.value = suggestion.label?suggestion.label.replace(//g,'').replace(/<\\/mark>/g,''):'';\n this.close({\n reason: 'select'\n });\n triggerNotify('awesomplete-selectcomplete', {\n text: suggestion\n });\n if (window.$(this._element).is('form')) {\n window.$(this._element).submit();\n } else {\n window.$(this._element).find('form').submit();\n }\n }\n }\n }\n }\n\n wrapEvaluation() {\n if (this.timeoutID && typeof this.timeoutID === 'number') {\n window.clearTimeout(this.timeoutID);\n }\n this.timeoutID = window.setTimeout(() => this.evaluate(), 400);\n }\n\n noSuggestionsFound(value) {\n if (this.notFoundTemplate && this.notFoundTemplate.innerHTML && this.notFoundTemplate.innerHTML.length > 0) {\n this.notFound.innerHTML = this.notFoundTemplate.innerHTML.replace(/\\{0\\}/g, value);\n }\n return !!(this.notFound?.innerHTML?.length > 0);\n }\n\n async evaluate(skipLengthCheck) {\n this.inputValueBackup = '';\n const value = this.input.value;\n const controller = (window.AbortController) ? new AbortController() : {};\n const signal = controller.signal || {};\n\n let fetchPromise;\n if ((skipLengthCheck && value.length > 0)|| value.length >= this._options.minChars) {\n if (this._options.autosuggestUrl) {\n this.notFound.innerHTML = '';\n if (fetchPromise && controller.abort) {\n controller.abort();\n }\n let suggestURL = '';\n let searchData = {};\n let key = this._options.key ? this._options.key : 'key';\n if (this._options.method === \"POST\") {\n suggestURL = `${this._options.autosuggestUrl}${((this.autosuggestDictionary) ? (this.autosuggestDictionary.value) ? this.autosuggestDictionary.value : 'cz-all' : '')}`;\n \n // Create data object\n searchData = {\n \"maxResults\": this._options.maxResults\n };\n // Add key value pair to data object\n searchData[key] = value;\n } else {\n suggestURL = `${this._options.autosuggestUrl}&${this._options.autosuggestKey}=${value}`;\n } \n try {\n fetchPromise = fetch(suggestURL, {\n signal,\n method : this._options.method || \"GET\",\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\"\n },\n body: this._options.method === \"POST\" ? JSON.stringify(searchData) : undefined\n });\n let response = await fetchPromise;\n let result = await response.json();\n\t\t\t\t\t\tthis.ul.innerHTML = '';\n \n if (result) {\n this._list = result;\n if (this._list.length > 0) {\n this.index = -1;\n // Populate list with options that match\n this.suggestions = this._list\n .map((item) => new Suggestion(item))\n .filter((item) => {\n return this._options.filter ? this.filter(item.label,value): true;\n })\n .sort((a,b) => {\n return this._options.sort ? this.sort(a,b): 0\n })\n .slice(0, this._options.maxItems);\n\n let html = this.suggestions.reduce((sentence, suggestion) => `${sentence}${ITEM( MAKETEXT( MARKTEXT( suggestion.label, value ), suggestion.href ))}`, '')\n\n this.ul.innerHTML = html;\n\n if (this.ul.children.length === 0) {\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: 'nomatches'\n });\n }\n } else {\n this.open();\n }\n } else {\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: 'nomatches'\n });\n }\n }\n } else {\n console.error('server returns wrong status');\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: 'nomatches'\n });\n }\n }\n\n } catch (error) {\n this.ul.innerHTML = '';\n\t\t\t\t\t\tconsole.error(error);\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: 'error'\n });\n }\n } finally {\n fetchPromise = undefined;\n }\n } else {\n this.close({\n reason: 'no autosuggest url'\n });\n }\n } else {\n this.close({\n reason: 'to little characters'\n });\n }\n }\n};\n\n// Private class\nclass Suggestion {\n constructor(data) {\n const o = Array.isArray(data) ? {\n label: data[0],\n value: data[1]\n } : typeof data === 'object' && 'text' in data && 'value' in data ? data : {\n label: data,\n value: data\n };\n\n this.label = o.text || o.label || '';\n this.href = o.href || '';\n this.value = o.value;\n }\n\n get length() {\n return this.label.length;\n }\n\n toString() {\n return '' + this.label;\n }\n}\n\nexport default SearchAwesomplete; // as SearchAwesomplete\n","/*\n * Form Validation\n *\n * This class is build around the native validityState. Based on the validity state,\n * custom messages are shown.\n * Each field will be validated after blur.\n * Once a validation is done, it will keep revalidating on each input change.\n * The form will validate all fields on submit.\n *\n * Messages are fetched from the data-validation attributes on the error element\n * within each field (see form-field mustache template).\n *\n*/\n\nclass FormValidation {\n constructor(element, {useAjax = false} = {}) {\n this._element = element;\n this._options = {\n useAjax\n };\n this.init();\n }\n\n init() {\n this.validations = [];\n this.fields = this._element.querySelectorAll('.c-form-field');\n\n // on formsubmit, validate all fields\n this._element.addEventListener('submit', async (event) => {\n this.validations.forEach(validation => validation?.());\n const isValid = this._element.checkValidity();\n if (!isValid || this._options.useAjax) {\n event.preventDefault();\n }\n if (isValid && this._options.useAjax) {\n // do ajax call\n await ajaxSubmit(this._element, this.fields);\n }\n return isValid;\n });\n\n // generate validation function and message per form field\n this.fields.forEach((field) => {\n if (field.querySelector('.c-input-date')) {\n this.validations.push(createDateValidator(field));\n return;\n };\n this.validations.push(createValidator(field));\n });\n }\n}\n\nasync function ajaxSubmit(form, fields) {\n try {\n form.classList.add(\"loading\");\n const formData = new FormData(form);\n const response = await fetch(form.action, {\n method: \"POST\",\n body: formData,\n credentials: \"same-origin\",\n headers: {\n \"X-Requested-With\": \"XMLHttpRequest\",\n },\n });\n const contentType = response.headers.get(\"content-type\");\n form.classList.remove(\"loading\");\n let result = false\n if (contentType?.includes(\"application/json\")) {\n result = await response.json();\n if (!response.ok && result) {\n fields?.forEach?.((field) => {\n const input = field.querySelector(':is(input, select, textarea)[name]');\n let message = result[input.name] || result[input.id];\n if (message) {\n const label = field.querySelector('label');\n const errorBox = field.querySelector('.c-form-field__error');\n const errorText = errorBox.querySelector('.c-form-field__error-message');\n errorText.textContent = message.replace('{0}', label.textContent);;\n errorBox.classList.add('active');\n }\n });\n } else {\n const redirectUrl = result?.redirectUrl;\n if (redirectUrl) {\n window.location.href = redirectUrl;\n }\n }\n return result;\n }\n } catch (error) {\n form.classList.remove(\"loading\");\n console.log(error);\n return;\n }\n}\n\n/*\n * Create validator for a field.\n * Sets up listeners for blur/input and sets a message if validation fails.\n */\nfunction createValidator(field) {\n const inputs = [...field.querySelectorAll(\"input:not([type='submit']), select, textarea\")];\n if (!inputs.length) {\n return;\n }\n\n const label = field.querySelector('label');\n const errorBox = field.querySelector('.c-form-field__error');\n const errorText = errorBox.querySelector('.c-form-field__error-message');\n\n const validationFn = (isBlurred) => {\n if (inputs.every(input => input.validity.valid)) {\n errorBox.classList.remove('active');\n if (inputs.some((input => input.value && isBlurred))) {\n field.classList.add('valid');\n }\n\n return;\n }\n field.classList.remove('valid');\n errorBox.classList.add('active');\n inputs.some(input => {\n for (let state in input.validity) {\n if (state === 'valid') {\n continue;\n }\n if (input.validity[state]) {\n errorText.textContent = setMessage(state, errorBox, label);\n return true;\n }\n }\n return false;\n });\n }\n\n inputs.forEach(\n input => {\n let isBlurred = false;\n input.addEventListener('input', () => isBlurred && validationFn(isBlurred));\n input.addEventListener('blur', () => {\n isBlurred = true;\n validationFn(isBlurred);\n });\n input.validate = () => validationFn(true);\n }\n );\n\n return validationFn;\n}\n\n/*\n * Create validator for a date field.\n * Sets up listeners for blur/input and sets a message if validation fails.\n * Is custom because date field consists of three parts (day, month, year) and is done different.\n * Each field can be actively validated on own restrictions, but the date as a whole will also be checked.\n */\nfunction createDateValidator(field) {\n const minDate = new Date(field.querySelector('.c-input-date')?.dataset['min']);\n const maxDate = new Date(field.querySelector('.c-input-date')?.dataset['max']);\n const inputs = {\n Day: field.querySelector('.c-input-date__day input'),\n Month: field.querySelector('.c-input-date__month input'),\n Year: field.querySelector('.c-input-date__year input')\n };\n const label = field.querySelector('label');\n const errorBox = field.querySelector('.c-form-field__error');\n const errorText = errorBox.querySelector('.c-form-field__error-message');\n\n const validationFn = (isBlurred) => {\n let entriesValid = Object.entries(inputs).every(([scope,input]) => input.validity.valid);\n if (entriesValid) {\n errorBox.classList.remove('active');\n if (Object.entries(inputs).some(([scope, input]) => input.value && isBlurred)) {\n field.classList.add('valid');\n }\n }\n\n let invalid = Object.entries(inputs).some(([scope, input]) => {\n for (let state in input.validity) {\n if (state === 'valid') {\n continue;\n }\n if (input.validity[state]){\n // single field day/month/year is filled incorrectly\n // always use badInput message from whole date field in this case\n errorText.textContent = setMessage('BadInput', errorBox, label);\n return true;\n }\n }\n });\n\n let year = parseInt(inputs.Year.value, 10);\n let month = parseInt(inputs.Month.value, 10) - 1;\n let day = parseInt(inputs.Day.value, 10);\n\n // Check if date is filled at all\n if (Number.isInteger(year) || Number.isInteger(month) || Number.isInteger(day)) {\n let date = new Date(year, month, day);\n if (isNaN(date.valueOf()) || inputs.Year.value.length < 4) {\n errorText.textContent = setMessage('BadInput', errorBox, label);\n invalid = true;\n } else if (maxDate && date.getTime() > maxDate.getTime()) {\n errorText.textContent = setMessage('RangeOverflow', errorBox, label);\n invalid = true;\n } else if (minDate && date.getTime() < minDate.getTime()) {\n errorText.textContent = setMessage('RangeUnderflow', errorBox, label);\n invalid = true;\n }\n }\n\n if (invalid) {\n field.classList.remove('valid');\n errorBox.classList.add('active');\n } else {\n if (Object.values(inputs).some(input => input.value)) {\n field.classList.add('valid');\n }\n errorBox.classList.remove('active');\n }\n }\n\n let isBlurred = false;\n\n Object.entries(inputs).forEach(([scope, input]) => {\n input.addEventListener('input', () => isBlurred && validationFn(isBlurred));\n input.addEventListener('blur', () => {\n if (scope === 'Year') {\n isBlurred = true;\n }\n\n validationFn(isBlurred);\n });\n });\n\n return validationFn;\n}\n\nfunction setMessage(state, errorBox, label, prefix = '') {\n // grab text from matching data property.\n const propName = prefix + state.charAt(0).toUpperCase() + state.slice(1);\n const message = errorBox.dataset[`msg${propName}`] || 'Validatiefout';\n\n // Insert label text dynamically.\n return message.replace('{field}', label.textContent);\n}\n\nexport default FormValidation;","/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&\"adoptedStyleSheets\"in Document.prototype&&\"replace\"in CSSStyleSheet.prototype,s=Symbol(),o=new WeakMap;class n{constructor(t,e,o){if(this._$cssResult$=!0,o!==s)throw Error(\"CSSResult is not constructable. Use `unsafeCSS` or `css` instead.\");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const s=this.t;if(e&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o.set(s,t))}return t}toString(){return this.cssText}}const r=t=>new n(\"string\"==typeof t?t:t+\"\",void 0,s),i=(t,...e)=>{const o=1===t.length?t[0]:e.reduce(((e,s,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if(\"number\"==typeof t)return t;throw Error(\"Value passed to 'css' function must be a 'css' function result: \"+t+\". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.\")})(s)+t[o+1]),t[0]);return new n(o,t,s)},S=(s,o)=>{if(e)s.adoptedStyleSheets=o.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const e of o){const o=document.createElement(\"style\"),n=t.litNonce;void 0!==n&&o.setAttribute(\"nonce\",n),o.textContent=e.cssText,s.appendChild(o)}},c=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e=\"\";for(const s of t.cssRules)e+=s.cssText;return r(e)})(t):t;export{n as CSSResult,S as adoptStyles,i as css,c as getCompatibleStyle,e as supportsAdoptingStyleSheets,r as unsafeCSS};\n//# sourceMappingURL=css-tag.js.map\n","import{getCompatibleStyle as t,adoptStyles as s}from\"./css-tag.js\";export{CSSResult,adoptStyles,css,getCompatibleStyle,supportsAdoptingStyleSheets,unsafeCSS}from\"./css-tag.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const{is:i,defineProperty:e,getOwnPropertyDescriptor:r,getOwnPropertyNames:h,getOwnPropertySymbols:o,getPrototypeOf:n}=Object,a=globalThis,c=a.trustedTypes,l=c?c.emptyScript:\"\",p=a.reactiveElementPolyfillSupport,d=(t,s)=>t,u={toAttribute(t,s){switch(s){case Boolean:t=t?l:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},f=(t,s)=>!i(t,s),y={attribute:!0,type:String,converter:u,reflect:!1,hasChanged:f};Symbol.metadata??=Symbol(\"metadata\"),a.litPropertyMetadata??=new WeakMap;class b extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=y){if(s.state&&(s.attribute=!1),this._$Ei(),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),r=this.getPropertyDescriptor(t,i,s);void 0!==r&&e(this.prototype,t,r)}}static getPropertyDescriptor(t,s,i){const{get:e,set:h}=r(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t}};return{get(){return e?.call(this)},set(s){const r=e?.call(this);h.call(this,s),this.requestUpdate(t,r,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??y}static _$Ei(){if(this.hasOwnProperty(d(\"elementProperties\")))return;const t=n(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(d(\"finalized\")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(d(\"properties\"))){const t=this.properties,s=[...h(t),...o(t)];for(const i of s)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(t(s))}else void 0!==s&&i.push(t(s));return i}static _$Eu(t,s){const i=s.attribute;return!1===i?void 0:\"string\"==typeof i?i:\"string\"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return s(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach((t=>t.hostConnected?.()))}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()))}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$EC(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:u).toAttribute(s,i.type);this._$Em=t,null==r?this.removeAttribute(e):this.setAttribute(e,r),this._$Em=null}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),r=\"function\"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u;this._$Em=e,this[e]=r.fromAttribute(s,t.type),this._$Em=null}}requestUpdate(t,s,i){if(void 0!==t){if(i??=this.constructor.getPropertyOptions(t),!(i.hasChanged??f)(this[t],s))return;this.P(t,s,i)}!1===this.isUpdatePending&&(this._$ES=this._$ET())}P(t,s,i){this._$AL.has(t)||this._$AL.set(t,s),!0===i.reflect&&this._$Em!==t&&(this._$Ej??=new Set).add(t)}async _$ET(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t)!0!==i.wrapped||this._$AL.has(s)||void 0===this[s]||this.P(s,this[s],i)}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach((t=>t.hostUpdate?.())),this.update(s)):this._$EU()}catch(s){throw t=!1,this._$EU(),s}t&&this._$AE(s)}willUpdate(t){}_$AE(t){this._$EO?.forEach((t=>t.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Ej&&=this._$Ej.forEach((t=>this._$EC(t,this[t]))),this._$EU()}updated(t){}firstUpdated(t){}}b.elementStyles=[],b.shadowRootOptions={mode:\"open\"},b[d(\"elementProperties\")]=new Map,b[d(\"finalized\")]=new Map,p?.({ReactiveElement:b}),(a.reactiveElementVersions??=[]).push(\"2.0.4\");export{b as ReactiveElement,u as defaultConverter,f as notEqual};\n//# sourceMappingURL=reactive-element.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,i=t.trustedTypes,s=i?i.createPolicy(\"lit-html\",{createHTML:t=>t}):void 0,e=\"$lit$\",h=`lit$${Math.random().toFixed(9).slice(2)}$`,o=\"?\"+h,n=`<${o}>`,r=document,l=()=>r.createComment(\"\"),c=t=>null===t||\"object\"!=typeof t&&\"function\"!=typeof t,a=Array.isArray,u=t=>a(t)||\"function\"==typeof t?.[Symbol.iterator],d=\"[ \\t\\n\\f\\r]\",f=/<(?:(!--|\\/[^a-zA-Z])|(\\/?[a-zA-Z][^>\\s]*)|(\\/?$))/g,v=/-->/g,_=/>/g,m=RegExp(`>|${d}(?:([^\\\\s\"'>=/]+)(${d}*=${d}*(?:[^ \\t\\n\\f\\r\"'\\`<>=]|(\"|')|))|$)`,\"g\"),p=/'/g,g=/\"/g,$=/^(?:script|style|textarea|title)$/i,y=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),x=y(1),b=y(2),w=y(3),T=Symbol.for(\"lit-noChange\"),E=Symbol.for(\"lit-nothing\"),A=new WeakMap,C=r.createTreeWalker(r,129);function P(t,i){if(!a(t)||!t.hasOwnProperty(\"raw\"))throw Error(\"invalid template strings array\");return void 0!==s?s.createHTML(i):i}const V=(t,i)=>{const s=t.length-1,o=[];let r,l=2===i?\"\":3===i?\"\":\"\")),o]};class N{constructor({strings:t,_$litType$:s},n){let r;this.parts=[];let c=0,a=0;const u=t.length-1,d=this.parts,[f,v]=V(t,s);if(this.el=N.createElement(f,n),C.currentNode=this.el.content,2===s||3===s){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=C.nextNode())&&d.length0){r.textContent=i?i.emptyScript:\"\";for(let i=0;i2||\"\"!==s[0]||\"\"!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=E}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=S(this,t,i,0),o=!c(t)||t!==this._$AH&&t!==T,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new R(i.insertBefore(l(),t),t,void 0,s??{})}return h._$AI(t),h};export{Z as _$LH,x as html,w as mathml,T as noChange,E as nothing,B as render,b as svg};\n//# sourceMappingURL=lit-html.js.map\n","import{ReactiveElement as t}from\"@lit/reactive-element\";export*from\"@lit/reactive-element\";import{render as e,noChange as s}from\"lit-html\";export*from\"lit-html\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */class r extends t{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const s=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=e(s,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return s}}r._$litElement$=!0,r[\"finalized\"]=!0,globalThis.litElementHydrateSupport?.({LitElement:r});const i=globalThis.litElementPolyfillSupport;i?.({LitElement:r});const o={_$AK:(t,e,s)=>{t._$AK(e,s)},_$AL:t=>t._$AL};(globalThis.litElementVersions??=[]).push(\"4.1.1\");export{r as LitElement,o as _$LE};\n//# sourceMappingURL=lit-element.js.map\n","import { LitElement, html, css } from 'lit';\n\nexport default class CzCombobox extends LitElement {\n\tstatic styles = [\n\t\tcss`\n\t\t\t:host {\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t\tslot {\n\t\t\t\tbox-sizing: border-box;\n\t\t\t}\n\t\t`\n\t];\n\n\tstatic properties = {\n\t\tautocomplete: {},\n\t};\n\n\tget select() {\n\t\treturn this._select ??= this.querySelector('select');\n\t}\n\n\t/**\n\t * bake your own combobox \n\t */\n\tbakeComponent() {\n\n\t\treturn false;\n\t}\n\n\tupdated(changedProperties) {\n\t\tif (changedProperties?.has('autocomplete')) {\n\t\t\tthis.bakeComponent();\n\t\t}\n\t}\n\n\trender() {\n\t\treturn html``;\n\t}\n}\n\ncustomElements.define('cz-combobox', CzCombobox);\n","import { getStorage } from \"./keyvaluestorage.js\";\n\nconst _paq = window?._paq || [];\nconst piwikPrefix = \"piwik_\";\nconst piwikSession = getStorage('session');\n\nlet pdl = {\n push: function (val) {\n if (val) {\n (window?.PiwikdataLayer || []).push?.(val);\n }\n }\n};\n\n\nlet lastEvent;\n\nfunction sameEvent(event) {\n let result = false;\n if (event && lastEvent) {\n result = event.event === lastEvent.event && event.event_category === lastEvent.event_category && event.event_action === lastEvent.event_action && event.event_name === lastEvent.event_name;\n } \n lastEvent = event;\n return result;\n}\n\nfunction findStoredPiwikKeys() {\n return Object.keys(sessionStorage)?.filter(key => key.startsWith(piwikPrefix) && key.length > piwikPrefix.length);\n}\n\nfunction storePiwikdimension(key, value) {\n if (!key || typeof key !== 'string' || typeof value !== 'string') return;\n piwikSession.storeKeyValue(`${piwikPrefix}${key}`, value);\n}\n\nexport function putDimensionInDatalayer(key, value) {\n if (key && typeof key === 'string') {\n pdl.push({[`${key}`]: `${value}`});\n } \n}\n\nexport function putCusDimInDatalayer(key, value) {\n if (key && typeof key === 'number' && value) {\n (window?._paq || _paq).push([\"setCustomDimensionValue\", key, `${value}`]);\n } \n}\n\nexport async function processStoredPiwikdimensions() {\n const piwikKeys = findStoredPiwikKeys();\n piwikKeys.forEach((pk) => {\n const val = piwikSession.getStoredValue(pk);\n putDimensionInDatalayer(pk.substring(piwikPrefix.length), val);\n })\n}\n\nexport function getStoredPiwikdimension(key) {\n if (!key) return;\n return piwikSession.getStoredValue(`${piwikPrefix}${key}`);\n}\n\nexport async function addEventToDatalayer(event) {\n if (!!event?.event && !sameEvent(event)) {\n pdl.push(event);\n }\n}\n\nexport async function addDimensionToDatalayer(key, value) {\n storePiwikdimension(key, value);\n putDimensionInDatalayer(key, value);\n}\n\nexport async function createHash(text) {\n if (typeof text !== 'string') return;\n\n const msgUint8 = new TextEncoder().encode(text); // encode as (utf-8) Uint8Array\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", msgUint8); // hash the message\n const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array\n // return bytes as hex string\n return hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}","/**\n * Wait function, useful if you want to show a loading spinner for example\n * just add `await wait(ms)` where you want to wait\n *\n * @param {number} ms the milliseconds you want to wait for\n */\nexport function wait(ms) {return new Promise(function(r) { setTimeout(r, ms)})};\n","import { wait } from './wait.js'\n// using reduce to pipe functions together\n// expects an array of generator functions\nconst pipeGenerators = fns => x => {\n\tif (fns && fns.length > 0) {\n\t\treturn fns.reduce((v, fn) => fn(v), x);\n\t} else {\n\t\treturn x;\n\t}\n};\n\n// using reduce to pipe functions together by wrapping them with async generator functions\n// expects an array of functions\nconst pipe = fns => x => {\n\tif (fns && fns.length > 0) {\n\t\treturn fns.reduce((v, fn) => {\n\t\t\treturn (async function* (input) {\n\t\t\t\tfor await (const i of input) {\n\t\t\t\t\tyield fn(i);\n\t\t\t\t}\n\t\t\t})(v);\n\t\t}, x);\n\t} else {\n\t\treturn x;\n\t}\n};\n\n/**\n * async generator will produce the entries in the queue one by one and wait for new entries\n * if onlyLast === true the async generator will produce only the final entry in the queue\n * will skip entries if new entries come in within the given ms (defaults to 500)\n *\n * @param {boolean} onlyLast\tif true only produce last entry, produce new entry if added within (ms)milliseconds \n * \t\t\t\t\t\t\t\t\tdefaults to false\n * @param {Array}\tqueue\t\tarray to hold the actions that will be produced\n * @param {Object}\tref\t\t\treference object to hold the callback function used to resolve a promise\n * @param {number}\tms\t\t\tnumber of milliseconds to wait for new entries before producing them\n * \t\t\t\t\t\t\t\t\tdefaults to 500\n * @param {number}\tpause\t\tnumber of milliseconds to pause before checking for new entries to produce\n * \t\t\t\t\t\t\t\t\tdefaults to 0\n */\nasync function* produce({ onlyLast = false, queue, ref, ms = 500, pause = 0 } = {}) {\n\tfor (;;) {\n\t\twhile (queue.length) {\n\t\t\tif (onlyLast) {\n\t\t\t\tif (queue.length > 1) {\n\t\t\t\t\tqueue.shift();\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (ms > 0) {\n\t\t\t\t\tawait wait(ms);\n\t\t\t\t}\n\t\t\t\tif (queue.length > 1) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tyield queue.shift(); //yield the first entry in the queue.\n\t\t\tif (pause > 0) {\n\t\t\t\tawait wait(pause);\n\t\t\t}\n\t\t}\n\t\tawait new Promise(i => (ref.callback = i));\n\t\tref.callback = null;\n\t}\n}\n\n/**\n * async function to consume the entries produced and sending them down the pipeline\n *\n * @param {*}\t\t\tproducer\titerable or generator function that produces actions to be consumed\n * @param {function}\tfinalFn\t\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {Array}\t\tfns\t\t\tArray of functions to let each action pass through before being handled by the finalFn\n * @param {boolean}\t\tgen\t\t\tif true the functions are generator functions defaults to false\n */\nasync function consume(producer, finalFn = () => {}, fns, gen = false) {\n\tlet pipeline = gen ? pipeGenerators(fns) : pipe(fns);\n\tfor await (const i of pipeline(producer)) {\n\t\tfinalFn(i); // anything added to the queue eventually ends up here.\n\t}\n}\n\n/**\n * get a producer object that will allow iteration to produce the entries in the queue one by one and wait for new entries\n * if onlyLast === true the asynciterator will produce only the final entry in the queue\n * will skip entries if new entries come in within the given ms (defaults to 500)\n *\n * @param {boolean}\tonlyLast\tif true only produce last entry, produce new entry if added within (ms)milliseconds \n * \t\t\t\t\t\t\t\t\tdefaults to false\n * @param {number}\tms\t\t\tnumber of milliseconds to wait for new entries before producing them\n * \t\t\t\t\t\t\t\t\tdefaults to 500\n * @param {number}\tpause\t\tnumber of milliseconds to pause before checking for new entries to produce\n * \t\t\t\t\t\t\t\t\tdefaults to 0\n * @returns {*} iterable object\n */\nfunction getProducer({onlyLast = false, ms = 500, pause = 0} = {}) {\n\treturn {\n\t\tcallback: null,\n\t\tqueue: [],\n\t\t[Symbol.asyncIterator]: async function* () {\n\t\t\tfor (;;) {\n\t\t\t\twhile (this.queue.length) {\n\t\t\t\t\tif (onlyLast) {\n\t\t\t\t\t\tif (this.queue.length > 1) {\n\t\t\t\t\t\t\tthis.queue = [this.queue.pop()];\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (ms > 0) {\n\t\t\t\t\t\t\tawait wait(ms);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.queue.length > 1) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tyield this.queue.shift();\n\t\t\t\t\tif (pause > 0) {\n\t\t\t\t\t\tawait wait(pause);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait new Promise(i => (this.callback = i));\n\t\t\t\tthis.callback = null;\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * get a producer object that will allow iteration to produce the entries in the queue one by one and wait for new entries\n * if onlyFirst === true the asynciterator will produce only the first entry in the queue\n * will skip new entries when they come in within the given ms (defaults to 200)\n *\n * @param {boolean}\tonlyFirst\tif true only produce first entry, skip new entry if added within (ms)milliseconds \n * \t\t\t\t\t\t\t\t\tdefaults to false\n * @param {number}\tms\t\t\tnumber of milliseconds to wait for new entries before producing them\n * \t\t\t\t\t\t\t\t\tdefaults to 200\n * @returns {*} iterable object\n */\nfunction getReducer({onlyFirst = false, now = false, ms = 200}) {\n\treturn {\n\t\tcallback: null,\n\t\tqueue: [],\n\t\t[Symbol.asyncIterator]: async function* () {\n\t\t\tfor (;;) {\n\t\t\t\twhile (this.queue.length) {\n\t\t\t\t\tif (onlyFirst && !now) {\n\t\t\t\t\t\tif (ms > 0) {\n\t\t\t\t\t\t\tawait wait(ms);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.queue.length > 1) {\n\t\t\t\t\t\t\tthis.queue = [this.queue.shift()];\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tyield this.queue.shift();\n\t\t\t\t\tif (onlyFirst && now) {\n\t\t\t\t\t\tif (ms > 0) {\n\t\t\t\t\t\t\tawait wait(ms);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.queue.length > 1) {\n\t\t\t\t\t\t\tthis.queue = [this.queue.shift()];\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tawait new Promise(i => (this.callback = i));\n\t\t\t\tthis.callback = null;\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Process all actions in a queue\n * Use it to process al the actions in a queue\n * pass regular functions as parameters\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tpause\tnumber of milliseconds to pause before checking for new entries to produce\n * @param {Array}\t\tfns \tArray of functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\t\t\tAn object you can push the actions you need processed to\n */ \nfunction processQueue(finalFn, pause, ...fns) {\n\tconst ref = {\n\t\tcallback: null\n\t};\t\n\tconst queue = [];\n\n\tconst producer = produce({\n\t\tqueue,\n\t\tref,\n\t\tpause\n\t});\t\n\n\tconsume(producer, finalFn, fns);\n\n\treturn {\n\t\tpush(action) {\n\t\t\tif (ref.callback) {\n\t\t\t\tref.callback();\n\t\t\t}\t\n\t\t\tqueue.push(action);\n\t\t}\t\n\t};\t\n}\t\n\n/**\n * Process first action in a queue added within a .2 second timeframe\n * Use it to process events where maybe some extra event get fired in a queue\n * pass regular functions as parameters\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tms\t\tnumber of milliseconds to wait for new entries before producing them\n * @param {Array}\t\tfns \tArray of functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\tAn object you can push the actions you need processed to\n */\nfunction processFirst(finalFn, ms, ...fns) {\n\tconst gen = getReducer({onlyFirst: true, ms});\n\tconsume(gen, finalFn, fns);\n\treturn {\n\t\tpush(val) {\n\t\t\tif (gen.callback) {\n\t\t\t\tgen.callback();\n\t\t\t}\n\t\t\tgen.queue.push(val);\n\t\t}\n\t};\n}\n\n/**\n * Process first action in a queue immediately and wait for a .2 second timeframe before processing the first event added to the queue\n * Use it to process events where you need to throttle events fired in a queue\n * pass regular functions as parameters\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tms\t\tnumber of milliseconds to wait for new entries before producing them\n * @param {Array}\t\tfns \tArray of functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\tAn object you can push the actions you need processed to\n */\nfunction processFirstNow(finalFn, ms, ...fns) {\n\tconst gen = getReducer({onlyFirst: true, now: true, ms});\n\tconsume(gen, finalFn, fns);\n\treturn {\n\t\tpush(val) {\n\t\t\tif (gen.callback) {\n\t\t\t\tgen.callback();\n\t\t\t}\n\t\t\tgen.queue.push(val);\n\t\t}\n\t};\n}\n\n/**\n * Process last action in a queue added within a .5 second timeframe\n * Use it to process events where maybe somebody changes their mind the actions in a queue\n * pass regular functions as parameters\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tms\t\tnumber of milliseconds to wait for new entries before producing them\n * @param {Array}\t\tfns \tArray of functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\tAn object you can push the actions you need processed to\n */\nfunction processEvent(finalFn, ms, ...fns) {\n\tconst por = getProducer({onlyLast: true, ms});\n\tconsume(por, finalFn, fns);\n\treturn {\n\t\tpush(val) {\n\t\t\tif (por.callback) {\n\t\t\t\tpor.callback();\n\t\t\t}\n\t\t\tpor.queue.push(val);\n\t\t}\n\t};\n}\n\n/**\n * Process all actions in a queue\n * Use it to process al the actions in a queue\n * pass generator functions as parameters apart from the finalFn\n * generator functions will give you more control but are harder to write\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tpause\tnumber of milliseconds to pause before checking for new entries to produce\n * @param {Array}\t\tfns \tArray of generator functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\tAn object you can push the actions you need processed to\n */\nfunction processQueueAsync(finalFn, pause, ...fns) {\n\tconst producer = getProducer({pause});\n\tconsume(producer, finalFn, fns, true);\n\treturn {\n\t\tpush(action) {\n\t\t\tif (producer.callback) {\n\t\t\t\tproducer.callback();\n\t\t\t}\n\t\t\tproducer.queue.push(action);\n\t\t}\n\t};\n}\n\n/**\n * Process last action in a queue added within a .5second timeframe\n * Use it to process events where maybe somebody changes their mindal the actions in a queue\n * pass generator functions as parameters apart from the finalFn\n * generator functions will give you more control but are harder to write\n *\n * @param {function}\tfinalFn\tFunction to execute for every action in the queue, will be called at the end of the pipeline\n * @param {number}\t\tms\t\tnumber of milliseconds to wait for new entries before producing them\n * @param {Array}\t\tfns \tArray of generator functions to let each action pass through before being handled by the finalFn\n * @returns {*}\t\t\tAn object you can push the actions you need processed to\n */\nfunction processEventAsync(finalFn, ms, ...fns) {\n\tconst gener = getProducer({onlyLast: true, ms});\n\tconsume(gener, finalFn, fns, true);\n\treturn {\n\t\tpush(action) {\n\t\t\tif (gener.callback) {\n\t\t\t\tgener.callback();\n\t\t\t}\n\t\t\tgener.queue.push(action);\n\t\t}\n\t};\n}\n\nfunction debounce(fn, ms) {\n\tif (!fn || typeof fn !== 'function') {\n\t\treturn;\n\t}\n\tconst eventQueue = processEvent(fn, ms);\n\treturn function(args) {\n\t\teventQueue.push(args);\n\t}\n}\n\nfunction throttle(fn, ms) {\n\tif (!fn || typeof fn !== 'function') {\n\t\treturn;\n\t}\n\tconst eventQueue = processFirstNow(fn, ms);\n\treturn function(args) {\n\t\teventQueue.push(args);\n\t}\n}\n\nexport {\n\tdebounce,\n\tthrottle,\n\tprocessQueue,\n\tprocessEvent,\n\tprocessFirst,\n\tprocessFirstNow,\n\tprocessQueueAsync,\n\tprocessEventAsync\n};","const prefix = \"shared-header__\";\n\n/**\n * Central store for classNames\n */\nexport default {\n layout: {\n logo: `${prefix}logo`,\n menuButtonMobile: `${prefix}btn-mobile--menu`,\n navContainer: `${prefix}nav`,\n navContainerWrapper: `${prefix}nav-wrapper`,\n rootElement: \"shared-header\",\n topBar: `${prefix}top-bar`,\n },\n modifiers: {\n active: \"is-active\",\n hidden: \"is-hidden\",\n submenu: \"submenu-is-open\",\n },\n navDomain: {\n nav: `${prefix}nav-domain`,\n },\n navPrimary: {\n container: `${prefix}nav__list`,\n listItem: `${prefix}nav__item`,\n mainItem: `${prefix}nav__link`,\n subNav: `${prefix}nav__sub-nav`,\n subNavGroup: `${prefix}nav__sub-nav__group-wrapper`,\n },\n overlay: `${prefix}overlay`,\n search: {\n dialog: `${prefix}search-dialog`,\n autoComplete: `${prefix}search-auto-complete`,\n buttonClear: `${prefix}search-btn-clear`,\n buttonSubmit: `${prefix}search-btn-submit`,\n buttonToggleSearchMobile: `${prefix}btn-mobile--search`,\n form: `${prefix}search`,\n formWrapperMobile: `${prefix}search-wrapper`,\n list: `${prefix}list`,\n listLabel: `${prefix}list-label`,\n },\n};\n","import ClassNames from \"./classNames.js\";\n\n/**\n * Central store for selecting dom elements\n */\n\n/**\n * Basic layout\n */\n\n// Optional root element wrapper for platform specific configuration\n// See example: ./front-end/src/index-local-dev.hbs\nconst $configWrapper = document.getElementById(\"shared-header-config-wrapper\");\n\n// HTML document body\nconst $htmlBody = document.querySelector(`body`);\n\nconst $logo = document.querySelector(`.${ClassNames.layout.logo}`);\n\n// Mobile menu button\nconst $menuButtonMobile = document.querySelector(\n `.${ClassNames.layout.menuButtonMobile}`\n);\n\n// Nav container\nconst $navContainer = document.querySelector(\n `.${ClassNames.layout.navContainer}`\n);\n\n// Nav container wrapper\nconst $navContainerWrapper = document.querySelector(\n `.${ClassNames.layout.navContainerWrapper}`\n);\n\n// Black opacity backdrop\nconst $overlay = document.querySelector(`.${ClassNames.overlay}`);\n\n// Root Element\n// Please note; an addtional wrapper is optional per platform to set up platform specific configuration\n// See example: ./front-end/src/index-local-dev.hbs\nconst $rootElement = document.querySelector(\n `.${ClassNames.layout.rootElement}`\n);\n\n/**\n * Nav primary\n */\n\n// Nav primary container\nconst $navPrimaryContainer = document.querySelector(\n `.${ClassNames.navPrimary.container}`\n);\n\n// Nav primary links\nconst $navPrimaryLinks = Array.prototype.slice.call(\n document\n .querySelector(`.${ClassNames.layout.navContainer}`)\n ?.querySelectorAll(\"a\") || []\n);\n\n// Nav primary main nav items (level 1 items)\nconst $navPrimaryMainItems = Array.prototype.slice.call(\n document.querySelectorAll(`.${ClassNames.navPrimary.mainItem}`) || []\n);\n\n// Nav primary buttons controlling a submenu\nconst $navPrimarySubmenuButtons = Array.prototype.slice.call(\n document\n .querySelector(`.${ClassNames.layout.navContainer}`)\n ?.querySelectorAll(`button.${ClassNames.navPrimary.mainItem}`) || []\n);\n\n// Nav primary subnavigation group of links\nconst $navPrimarySubNavGroups = Array.prototype.slice.call(\n document.querySelectorAll(`.${ClassNames.navPrimary.subNavGroup}`) || []\n);\n\n// Nav primary sub navigations\nconst $navPrimarySubNavs = Array.prototype.slice.call(\n document.querySelectorAll(`.${ClassNames.navPrimary.subNav}`) || []\n);\n\n/**\n * Nav domain\n */\n\n// Nav domain container\nconst $navDomain = document.querySelector(`.${ClassNames.navDomain.nav}`);\n\n// Nav domain links\nconst $navDomainLinks = $navDomain\n ? Array.prototype.slice.call($navDomain.querySelectorAll(\"a\") || [])\n : [];\n\n/**\n * Search\n */\n\n// Search mobile toggle button\nconst $searchButtonToggleSearchMobile = document.querySelector(\n `.${ClassNames.search.buttonToggleSearchMobile}`\n);\n\n// Search form wrapper mobile\nconst $searchFormWrapperMobile = document.querySelector(\n `.${ClassNames.search.formWrapperMobile}`\n);\n\n// Search form mobile\nconst $searchFormMobile = document\n .querySelector(`.${ClassNames.search.dialog}`)\n ?.querySelector(`.${ClassNames.search.form}`);\n\n// Search form wrapper desktop\nconst $searchFormDesktop = $navContainerWrapper?.querySelector(\n `.${ClassNames.search.form}`\n);\n\n// Search form input mobile\nconst $searchInputMobile = $searchFormMobile\n ? $searchFormMobile.querySelector(\"input\")\n : null;\n\n// Search form input desktop\nconst $searchInputDesktop = $searchFormDesktop\n ? $searchFormDesktop.querySelector(\"input\")\n : null;\n\n// Search button clear mobile\nconst $searchBtnClearMobile = $searchFormMobile\n ? $searchFormMobile.querySelector(`.${ClassNames.search.buttonClear}`)\n : null;\n\n// Search button clear desktop\nconst $searchBtnClearDesktop = $searchFormDesktop\n ? $searchFormDesktop.querySelector(`.${ClassNames.search.buttonClear}`)\n : null;\n\n// Search button submit mobile\nconst $searchSubmitMobile = $searchFormMobile\n ? $searchFormMobile.querySelector(`.${ClassNames.search.buttonSubmit}`)\n : null;\n\n// Search button submit desktop\nconst $searchSubmitDesktop = $searchFormDesktop\n ? $searchFormDesktop.querySelector(`.${ClassNames.search.buttonSubmit}`)\n : null;\n\n// Search button auto complete mobile\nconst $searchAutoCompleteMobile = $searchFormMobile\n ? $searchFormMobile.querySelector(`.${ClassNames.search.autoComplete}`)\n : null;\n\n// Search button auto complete desktop\nconst $searchAutoCompleteDesktop = $searchFormDesktop\n ? $searchFormDesktop.querySelector(`.${ClassNames.search.autoComplete}`)\n : null;\n\nexport default {\n $configWrapper,\n $htmlBody,\n $logo,\n $menuButtonMobile,\n $navContainer,\n $navContainerWrapper,\n $overlay,\n $rootElement,\n $navPrimaryContainer,\n $navPrimaryLinks,\n $navPrimaryMainItems,\n $navPrimarySubmenuButtons,\n $navPrimarySubNavGroups,\n $navPrimarySubNavs,\n $navDomain,\n $navDomainLinks,\n $searchButtonToggleSearchMobile,\n $searchFormWrapperMobile,\n $searchFormMobile,\n $searchFormDesktop,\n $searchInputMobile,\n $searchInputDesktop,\n $searchBtnClearMobile,\n $searchBtnClearDesktop,\n $searchSubmitMobile,\n $searchSubmitDesktop,\n $searchAutoCompleteMobile,\n $searchAutoCompleteDesktop,\n};\n","/**\n * Translates a contextual correct action to a classList method\n *\n * Most presentational changes are handeled by simple class changes. Terms like\n * \"add\" and \"remove\" don't always make sense when the presentational result of\n * a method is e.g. showing or hiding it.\n * \n * action = \"close\" | \"open\" | \"toggle\";\n * result = \"add\" | \"remove\" | \"toggle\";\n *\n * @param action The action to interpret\n */\nexport function interpretAction(action) {\n if (action === \"close\") return \"remove\";\n if (action === \"open\") return \"add\";\n return action;\n}","/**\n * Handles all functionality related to account navigation\n *\n * A11Y requirements: {@link https://w3c.github.io/aria-practices/examples/menu-button/menu-button-links.html}\n */\n\nimport ClassNames from \"./classNames.js\";\nimport DomElements from \"./domElements.js\";\nconst {\n $navPrimarySubNavs: $subNavs,\n $navPrimaryContainer,\n $menuButtonMobile,\n $navContainerWrapper\n} = DomElements;\n\nimport { interpretAction } from \"../../@helpers/js/interpretAction.js\";\n\n/**\n * Check if mobile menu open\n *\n * @returns 'true' if open, 'false' if hidden\n */\nconst isMobileMenuOpen = () => !!$menuButtonMobile?.classList?.contains(\n `${ClassNames.layout.menuButtonMobile}--${ClassNames.modifiers.active}`\n);\n\n// Currently active\nlet activeSubmenuId = \"\";\n\nconst updateActiveSubmenuId = (newValue) => activeSubmenuId = newValue\nconst getActiveSubmenuId = () => activeSubmenuId\n\n/**\n * Close all submenus\n */\nfunction closeAllSubmenus() {\n const subNavList = Array.prototype.slice.call($subNavs, 0);\n subNavList.forEach(($submenu) => {\n const { submenuId } = $submenu.dataset;\n submenuId && toggle(submenuId, \"close\");\n });\n activeSubmenuId = \"\";\n}\n\n/**\n * Show, hide or toggle a submenu\n *\n * Also calculates the submenu position for tablet and up\n * (unable to do with just CSS)\n *\n * @param id Submenu id\n * @param action Type of action\n */\nconst toggle = (id, action) => {\n const subNavList = Array.prototype.slice.call($subNavs, 0);\n subNavList.forEach(($submenu) => {\n if ($submenu.dataset.submenuId === id) {\n // Toggle submenu\n $submenu.classList[interpretAction(action)](\n `${ClassNames.navPrimary.subNav}--${ClassNames.modifiers.active}`\n );\n\n // Set active submenu state on trigger\n $submenu.parentElement\n .querySelector(`.${ClassNames.navPrimary.mainItem}`)\n .classList[interpretAction(action)](\n `${ClassNames.navPrimary.mainItem}--${ClassNames.modifiers.submenu}`\n );\n\n $submenu.parentElement.classList[interpretAction(action)](\n `${ClassNames.navPrimary.listItem}--${ClassNames.modifiers.submenu}`\n );\n\n // Set active submenu state on container\n // (Required to handle different active states in CSS)\n if (window.innerWidth >= 768) {\n $navPrimaryContainer.classList[interpretAction(action)](\n `${ClassNames.navPrimary.container}--${ClassNames.modifiers.submenu}`\n );\n } else {\n $navPrimaryContainer.classList.remove(\n `${ClassNames.navPrimary.container}--${ClassNames.modifiers.submenu}`\n );\n }\n\n // Handle `aria-expanded`\n const trigger = document.querySelector(`[data-submenu-id=\"${id}\"]`);\n\n if (trigger) {\n trigger.setAttribute(\n \"aria-expanded\",\n `${!(trigger.getAttribute(\"aria-expanded\") === \"true\")}`\n );\n }\n\n // Set submenu position (by rules of design)\n const menuWidth =\n $navContainerWrapper.clientWidth -\n parseFloat(getComputedStyle($navContainerWrapper).paddingLeft) -\n parseFloat(getComputedStyle($navContainerWrapper).paddingRight);\n // Number of pixels the submenu is too far overlapping to the right\n const overlap =\n $submenu.clientWidth -\n 2 * (window.innerWidth >= 1024 ? 32 : 24) -\n (menuWidth - $submenu.parentElement.offsetLeft);\n\n // Correct position for screens equal or larger the 1024 (M up)\n if (window.innerWidth >= 1024) {\n if (overlap < $submenu.parentElement.offsetLeft) {\n $submenu.style.marginLeft = `-${overlap}px`;\n } else {\n $submenu.style.marginLeft = `-${$submenu.parentElement.offsetLeft}px`;\n }\n }\n\n // Correct position for breakpoint 768 - 1024 (M)\n if (window.innerWidth >= 768 && window.innerWidth < 1024) {\n if ($submenu.dataset.columns <= 2) {\n $submenu.style.marginLeft = `-${overlap}px`;\n } else {\n const spaceLeft =\n $navContainerWrapper.offsetLeft + $submenu.parentElement.offsetLeft;\n $submenu.style.marginLeft = `-${spaceLeft}px`;\n }\n }\n\n // Reset corrected position for screens smaller then 768 (S down)\n if (window.innerWidth < 768) $submenu.style.marginLeft = \"\";\n }\n });\n};\n\n/**\n * Check if any submenu is open\n *\n * @returns If open\n */\nconst isAnySubmenuOpen = () => !!activeSubmenuId;\n\nexport default {\n isMobileMenuOpen,\n updateActiveSubmenuId,\n getActiveSubmenuId,\n closeAllSubmenus,\n toggle,\n isAnySubmenuOpen,\n};\n","import { lockScroll } from \"../../@helpers/js/scrollLocker.js\";\n\nimport ClassNames from \"./classNames.js\";\nimport DomElements from \"./domElements.js\";\nconst { $overlay } = DomElements;\nimport Shared from \"./shared.js\";\nconst {\n isMobileMenuOpen,\n closeAllSubmenus,\n isAnySubmenuOpen,\n} = Shared;\nimport { interpretAction } from \"../../@helpers/js/interpretAction.js\";\n\n/**\n * Handle initial setup\n */\nfunction initOverlay() {\n $overlay?.addEventListener(\"click\", () => {\n if (isAnySubmenuOpen()) closeAllSubmenus();\n toggle(\"close\");\n toggleScrollLock(false);\n });\n}\n\n/**\n * Reevaluate if overflow should be opened or closed\n */\nfunction reevaluateOverlay() {\n if (!isOpen()) {\n if (isAnySubmenuOpen() || isMobileMenuOpen()) {\n toggle(\"open\");\n toggleScrollLock(true);\n }\n } else {\n if (\n (!isAnySubmenuOpen() &&\n window.innerWidth >= 768) ||\n (!isMobileMenuOpen() && window.innerWidth < 768)\n ) {\n toggle(\"close\");\n toggleScrollLock(false);\n }\n }\n}\n\n/**\n * Check if open\n *\n * @returns If open\n */\nconst isOpen = () => !!$overlay?.classList?.contains(\n `${ClassNames.overlay}--${ClassNames.modifiers.active}`\n);\n\n/**\n * Toggle visibility\n */\nconst toggle = (action) => {\n $overlay.classList[interpretAction(action)](\n `${ClassNames.overlay}--${ClassNames.modifiers.active}`\n );\n};\n\n/**\n * Only lock scrollbar if there is no visible scrollbar (mobile).\n * Locking can cause content shift otherwise\n */\nfunction toggleScrollLock(lock) {\n const scrollbarWidth =\n window.innerWidth - document.documentElement.offsetWidth;\n if (scrollbarWidth && lock) return;\n\n lockScroll(lock, \"instant\");\n}\n\nexport default {\n initOverlay,\n reevaluateOverlay,\n};\n","/**\n * Lock- or unlock scrolling.\n */\nexport function lockScroll(lock, behavior = \"auto\") {\n\tif (globalThis?.window) {\n\t\tlet scrollY;\n\t\tif (lock) {\n\t\t\tscrollY = window.scrollY ?? 0;\n\t\t\tdocument.body.style.minHeight = \"100%\";\n\t\t\tdocument.body.style.position = \"fixed\";\n\t\t\tdocument.body.style.top = scrollY ? `-${scrollY}px` : \"0px\";\n\t\t\tdocument.body.style.width = \"100%\";\n\t\t}\n\t\telse {\n\t\t\tscrollY = parseInt(document.body.style.top) * -1 || 0;\n\t\t\tdocument.body.style.position = \"\";\n\t\t\tdocument.body.style.top = \"\";\n\t\t\tdocument.body.style.width = \"\";\n\t\t\tdocument.body.style.minHeight = \"\";\n\t\t\tbehavior = [\"auto\", \"instant\", \"smooth\"].includes(behavior) ? behavior : \"auto\";\n\t\t\tif (scrollY > 0) {\n\t\t\t\twindow.scrollTo({left: 0, top: scrollY, behavior});\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * Handles all functionality related to the primary navigation container\n */\n\nimport ClassNames from \"./classNames.js\";\nimport DomElements from \"./domElements.js\";\nconst { $menuButtonMobile, $navContainerWrapper } = DomElements;\nimport Overlay from \"./handleOverlay.js\";\nconst { reevaluateOverlay } = Overlay;\nimport { interpretAction } from \"../../@helpers/js/interpretAction.js\";\n\n/**\n * On click menu button (small vp)\n */\nconst initMenuButton = () => {\n $menuButtonMobile?.addEventListener(\"click\", () => {\n if (!isOpen()) {\n toggleNavigation(\"open\");\n } else toggleNavigation(\"close\");\n reevaluateOverlay();\n });\n};\n\n/**\n * Check if open\n *\n * @returns 'true' if open, 'false' if hidden\n */\nconst isOpen = () => !!$navContainerWrapper?.classList?.contains(\n `${ClassNames.layout.navContainerWrapper}--${ClassNames.modifiers.active}`\n);\n\n/**\n * Toggle visibility\n *\n * @param action Type of action to handle\n */\nfunction toggleNavigation(action) {\n $menuButtonMobile.classList[interpretAction(action)](\n `${ClassNames.layout.menuButtonMobile}--${ClassNames.modifiers.active}`\n );\n $menuButtonMobile.setAttribute(\n \"aria-expanded\",\n `${!($menuButtonMobile.getAttribute(\"aria-expanded\") === \"true\")}`\n );\n\n $navContainerWrapper.classList[interpretAction(action)](\n `${ClassNames.layout.navContainerWrapper}--${ClassNames.modifiers.active}`\n );\n}\n\nexport default {\n initMenuButton,\n isOpen,\n toggleNavigation,\n};\n","/**\n * Handles all functionality related to domain navigation\n *\n * A11Y requirements: {@link https://www.w3.org/TR/wai-aria-practices/examples/disclosure/disclosure-navigation.html}\n */\n\nimport DomElements from \"./domElements.js\";\nconst { $navDomainLinks: $links } = DomElements;\n\n/**\n * Initialize nav domain functionality\n */\nexport default function initNavDomain() {\n initKeyboardSupport();\n}\n\n/**\n * Keyboard support (A11Y)\n */\nconst initKeyboardSupport = () => {\n if ($links?.length) {\n $links.forEach(($link, i) => {\n $link.addEventListener(\"keyup\", (event) => {\n switch (event.code) {\n case \"ArrowDown\":\n case \"ArrowRight\":\n i + 1 in $links && $links[i + 1].focus();\n break;\n case \"ArrowUp\":\n case \"ArrowLeft\":\n i - 1 in $links && $links[i - 1].focus();\n break;\n case \"Home\":\n $links[0].focus();\n break;\n case \"End\":\n $links[$links.length - 1].focus();\n break;\n }\n });\n });\n }\n};\n","import { debounce } from \"../../@helpers/js/queue-processing.js\";\n\nimport ClassNames from \"./classNames.js\";\nimport DomElements from \"./domElements.js\";\nimport Shared from \"./shared.js\";\nconst {\n closeAllSubmenus,\n isAnySubmenuOpen,\n} = Shared;\nimport Overlay from \"./handleOverlay.js\";\nconst { reevaluateOverlay } = Overlay;\nimport { interpretAction } from \"../../@helpers/js/interpretAction.js\";\n\nconst $autoCompleteDesktop = DomElements.$searchAutoCompleteDesktop;\nconst $autoCompleteMobile = DomElements.$searchAutoCompleteMobile;\nconst $btnClearDesktop = DomElements.$searchBtnClearDesktop;\nconst $btnClearMobile = DomElements.$searchBtnClearMobile;\nconst $buttonToggleSearchMobile = DomElements.$searchButtonToggleSearchMobile;\nconst $formDesktop = DomElements.$searchFormDesktop;\nconst $formMobile = DomElements.$searchFormMobile;\nconst $formWrapperMobile = DomElements.$searchFormWrapperMobile;\nconst $inputDesktop = DomElements.$searchInputDesktop;\nconst $inputMobile = DomElements.$searchInputMobile;\nconst $submitDesktop = DomElements.$searchSubmitDesktop;\nconst $submitMobile =DomElements.$searchSubmitMobile;\nconst $nav = DomElements.$navAccount;\n\n/**\n * IMPORTANT\n * We were unable to support a single search form for both desktop and mobile\n * The design is to different\n * So all required functionality needs to be applied to both mobile and desktop\n */\n\n// Array for auto complete results\nlet autoCompleteResponse = [];\nlet selectedSearchResultIndex = -1;\nlet searchInitialized = false;\nconst site = Array.from(document.documentElement.classList).reduce((prev, current) => {\n if (['cz', 'just', 'zorgkantoor', 'pzp', 'czdirect', 'pzpdirect'].includes(current)) {\n return current;\n }\n return prev;\n}, null);\n\n/**\n * Handle initial setup\n */\nfunction initSearch() {\n // prevent double execution\n if (searchInitialized) {\n return;\n }\n searchInitialized = true;\n\n if ($formMobile || $formDesktop) {\n handleInputFocus();\n appendUserInputToFormAction();\n setSubmitDisabledIfInputIsToSmallDesktop();\n handleSubmitForms();\n handleInputValidation();\n setupAutoComplete();\n handleClearButton();\n }\n}\n\n/**\n * If search on mobile is open\n */\nexport const searchMobileisOpen = () => !!$formWrapperMobile?.classList?.contains(\n `${ClassNames.search.formWrapperMobile}--${ClassNames.modifiers.active}`\n);\n\n/**\n * Toggle display search mobile\n */\nexport const clickToggleSearchMobile = () => {\n $buttonToggleSearchMobile.dispatchEvent(new Event(\"click\"));\n}\n\n/**\n * Toggle display search mobile\n */\nexport const toggleSearchMobile = (action) => {\n const interpretedAction = interpretAction(action);\n\n // Handle classes\n $formWrapperMobile.classList[interpretedAction](\n `${ClassNames.search.formWrapperMobile}--${ClassNames.modifiers.active}`\n );\n\n $buttonToggleSearchMobile.classList[interpretedAction](\n `${ClassNames.search.buttonToggleSearchMobile}--${ClassNames.modifiers.active}`\n );\n\n DomElements.$logo.classList[interpretedAction](\n `${ClassNames.layout.logo}--${ClassNames.modifiers.hidden}`\n );\n\n if ($nav) {\n $navAccountBtnMobile.classList[interpretedAction](\n `${ClassNames.navAccount.btnMobile}--${ClassNames.modifiers.hidden}`\n );\n }\n\n // If open focus directly on input\n if (searchMobileisOpen()) $inputMobile.focus();\n};\n\n/**\n * Keep both desktop and mobile input in sync\n */\nconst appendUserInputToFormAction = () => {\n $inputMobile?.addEventListener(\"keyup\", () => {\n setSearchFormAction($inputMobile);\n if ($inputDesktop) {\n $inputDesktop.value = $inputMobile.value;\n }\n });\n\n $inputDesktop?.addEventListener(\"keyup\", () => {\n setSearchFormAction($inputDesktop);\n if ($inputMobile) {\n $inputMobile.value = $inputDesktop.value;\n }\n });\n};\n\n/**\n * Set the action based on user value\n */\nconst setSearchFormAction = ($input) => {\n const action = `${\n ($formMobile?.action || $formDesktop?.action)?.split(\"?\")[0]\n }?query=${$input.value\n .trim()\n .replace(/ {2,}/g, \" \") // Remove multiple spaces\n .replace(/\\s/g, \"+\") // Replace spaces for '+' character\n .replace(/[^+a-zA-Z0-9]/g, \"\")}`; // Remove all special characters except alfabetical, numeric and '+' characters\n\n if ($formDesktop) $formDesktop.action = action;\n if ($formMobile) $formMobile.action = action;\n};\n\n/**\n * Evaluate if submit button should be dis- or enabled\n */\nconst evaluateSubmitDisabled = () => {\n if ($inputMobile?.value?.length > 0 && $submitMobile) $submitMobile.disabled = false;\n else if ($submitMobile) $submitMobile.disabled = true;\n\n if ($inputDesktop?.value?.length > 0 && $submitDesktop) $submitDesktop.disabled = false;\n else if ($submitDesktop) $submitDesktop.disabled = true;\n};\n\n/**\n * Clear auto complete results and reset selected result index\n */\nconst clearAutoCompleteResults = () => {\n // Clear auto complete containers\n if ($autoCompleteMobile) $autoCompleteMobile.innerHTML = \"\";\n if ($autoCompleteDesktop) $autoCompleteDesktop.innerHTML = \"\";\n\n // Reset accessiblity field\n $inputDesktop?.setAttribute(\"aria-expanded\", \"false\");\n $inputMobile?.setAttribute(\"aria-expanded\", \"false\");\n\n // reset selected search index\n selectedSearchResultIndex = -1;\n\n // reset autocomplete results\n autoCompleteResponse = [];\n};\n\n/**\n * Handle API response in UI\n */\nconst handleAutoComplete = async () => {\n const value = $inputMobile?.value || $inputDesktop?.value;\n if (!value) return;\n const response = await requestAutoComplete(value);\n\n // Clear all previous results\n clearAutoCompleteResults();\n\n // Store new response\n autoCompleteResponse = response;\n\n if (autoCompleteResponse?.length) {\n\n\n // List label\n const label = document.createElement(\"label\");\n label.id = ClassNames.search.listLabel;\n label.innerHTML = ($formDesktop?.dataset?.suggestionsLabel || $formMobile?.dataset?.suggestionsLabel) ?? \"Suggesties\";\n\n const ol = document.createElement(\"ol\");\n ol.id = ClassNames.search.list;\n ol.setAttribute(\"role\", \"listbox\");\n autoCompleteResponse.forEach((value, index) => {\n // Create a link, set `href` and set the name\n const a = document.createElement(\"a\");\n a.setAttribute(\n \"href\",\n `${($formMobile || $formDesktop)?.getAttribute(\"action\")?.split(\"?\")[0]\n }?query=${value.replace(\" \", \"+\")}`\n );\n a.innerHTML = value;\n // Create a `li` node\n const li = document.createElement(\"li\");\n li.id = `option-${index}`;\n li.setAttribute(\"role\", \"option\");\n // Append the link to `li`\n li.append(a);\n // Append the `li' to the `ol` container element\n ol.append(li);\n });\n // Append to mobile wrapper\n if ($autoCompleteMobile) {\n $autoCompleteMobile.append(label);\n ol.id = $inputMobile.getAttribute(\"aria-controls\") ?? ClassNames.search.list;\n $autoCompleteMobile.append(ol);\n $inputMobile.setAttribute(\"aria-expanded\", \"true\");\n }\n // Append a clone to the desktop wrapper\n if ($autoCompleteDesktop) {\n $autoCompleteDesktop.append(label.cloneNode(true));\n const olClone = ol.cloneNode(true);\n olClone.id = $inputDesktop.getAttribute(\"aria-controls\") ?? ClassNames.search.list;\n $autoCompleteDesktop.append(olClone);\n $inputDesktop.setAttribute(\"aria-expanded\", \"true\");\n }\n // Hightlight user value\n highlightUserValue();\n }\n};\n\n/**\n * Handle all functionality for the clear button\n */\nconst handleClearButton = () => {\n function toggleClearBtn($input, $btn) {\n if (!$input || !$btn) return;\n if ($input.value === \"\") {\n $btn.classList.add(\n `${ClassNames.search.buttonClear}--${ClassNames.modifiers.hidden}`\n );\n $btn.tabIndex = -1;\n } else {\n $btn.classList.remove(\n `${ClassNames.search.buttonClear}--${ClassNames.modifiers.hidden}`\n );\n $btn.tabIndex = 0;\n }\n }\n\n function onClick(e, $input, $btn) {\n e.preventDefault();\n if (!$input || !$btn) return;\n $input.value = \"\";\n $input.focus();\n clearAutoCompleteResults();\n toggleClearBtn($input, $btn);\n evaluateSubmitDisabled();\n }\n\n $btnClearDesktop?.addEventListener(\"click\", (e) => {\n onClick(e, $inputDesktop, $btnClearDesktop);\n onClick(e, $inputMobile, $btnClearMobile);\n });\n\n $inputDesktop?.addEventListener(\"keyup\", () => {\n toggleClearBtn($inputDesktop, $btnClearDesktop);\n toggleClearBtn($inputMobile, $btnClearMobile);\n });\n\n $btnClearMobile?.addEventListener(\"click\", (e) => {\n onClick(e, $inputMobile, $btnClearMobile);\n onClick(e, $inputDesktop, $btnClearDesktop);\n });\n\n $inputMobile?.addEventListener(\"keyup\", () => {\n toggleClearBtn($inputMobile, $btnClearMobile);\n toggleClearBtn($inputDesktop, $btnClearDesktop);\n });\n};\n\n/**\n * Handle UI changes for mobile and desktop input focus\n */\nconst handleInputFocus = () => {\n // Mobile\n\n // Show auto complete container on focus in\n $formMobile?.addEventListener(\"focusin\", () => {\n $autoCompleteMobile.classList.remove(\n `${ClassNames.search.autoComplete}--${ClassNames.modifiers.hidden}`\n );\n\n // Add focus state\n $inputMobile.parentElement.classList.add(\"is-in-focus\");\n $formMobile.classList.add(\"a11y-focus\");\n\n // Add accessiblity field when there are search results\n if (autoCompleteResponse?.length) {\n $inputMobile.setAttribute(\"aria-expanded\", \"true\");\n }\n\n reevaluateOverlay();\n });\n\n // Hide auto complete container on focus out\n $formMobile?.addEventListener(\"focusout\", () => {\n $autoCompleteMobile.classList.add(\n `${ClassNames.search.autoComplete}--${ClassNames.modifiers.hidden}`\n );\n\n // Reset state to non-focus\n $inputMobile.parentElement.classList.remove(\"is-in-focus\");\n $formMobile.classList.remove(\"a11y-focus\");\n\n // Reset accessiblity field\n $inputMobile.setAttribute(\"aria-expanded\", \"false\");\n });\n\n // Desktop\n\n $formDesktop?.addEventListener(\n \"focusin\",\n () => {\n // Set width\n if ($inputDesktop.clientWidth < 300) {\n $inputDesktop.parentElement.style.width = \"300px\";\n }\n\n // Add focus state\n $inputDesktop.parentElement.classList.add(\"is-in-focus\");\n $formDesktop.classList.add(\"a11y-focus\");\n\n // show icon for clearing value input\n if ($inputDesktop?.value !== \"\") {\n $btnClearDesktop.classList.remove(\"hidden\");\n }\n\n // Reenable submit button if input (and if disabled)\n if ($inputDesktop?.value !== \"\") {\n $submitDesktop.disabled = false;\n }\n\n // Show auto complete container\n $autoCompleteDesktop.classList.remove(\n `${ClassNames.search.autoComplete}--${ClassNames.modifiers.hidden}`\n );\n\n // Add accessiblity field when there are search results\n if (autoCompleteResponse?.length) {\n $inputDesktop.setAttribute(\"aria-expanded\", \"true\");\n }\n\n // Clean up related interface\n isAnySubmenuOpen() && closeAllSubmenus();\n reevaluateOverlay();\n },\n true\n );\n\n $formDesktop?.addEventListener(\n \"blur\",\n () => {\n // Reset width to CSS default\n $inputDesktop.parentElement.style.width = \"\";\n\n // Reset state to non-focus\n $inputDesktop.parentElement.classList.remove(\"is-in-focus\");\n $formDesktop.classList.remove(\"a11y-focus\");\n\n // Reset auto complete container to CSS default\n $autoCompleteDesktop.classList.add(\n `${ClassNames.search.autoComplete}--${ClassNames.modifiers.hidden}`\n );\n\n // Reset accessiblity field\n $inputDesktop.setAttribute(\"aria-expanded\", \"false\");\n\n // Disable submit button if field too narrow\n setTimeout(() => setSubmitDisabledIfInputIsToSmallDesktop(), 150);\n },\n true\n );\n};\n\n/**\n * Setup event listeners to validate input\n */\nconst handleInputValidation = () => {\n // For mobile\n $inputMobile?.addEventListener(\"keyup\", () => evaluateSubmitDisabled());\n\n // For desktop\n $inputDesktop?.addEventListener(\"keyup\", () => evaluateSubmitDisabled());\n};\n\n/**\n * Submit the forms\n */\nconst handleSubmitForms = () => {\n $formMobile?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n window.location.href = $formMobile.action;\n });\n\n $formDesktop?.addEventListener(\"submit\", (e) => {\n e.preventDefault();\n window.location.href = $formDesktop.action;\n });\n};\n\n/**\n * Highlights user value in suggested search values from API\n */\nconst highlightUserValue = () => {\n function highlight($links) {\n $links.forEach(($link) => {\n // Since both input values are kept in sync we can just take one of them\n const userValue = $inputMobile.value.toLowerCase();\n $link.innerHTML = $link.innerHTML\n .replace(/<\\/?[^>]+(>|$)/g, \"\")\n .replace(new RegExp(userValue, \"ig\"), `$&`);\n });\n }\n\n const $mobileLinks = $autoCompleteMobile?.querySelectorAll(\"a\");\n const $desktopLinks = $autoCompleteDesktop?.querySelectorAll(\"a\");\n\n if ($mobileLinks?.length) highlight($mobileLinks);\n if ($desktopLinks?.length) highlight($desktopLinks);\n};\n\n/**\n * Request API for auto complete suggestions\n */\nconst requestAutoComplete = async (query) => {\n return fetch(`${ $inputMobile?.dataset?.api || $inputDesktop?.dataset?.api}?site=${site}&query=${query}`)\n .then((response) => response.json())\n .catch(() => []);\n};\n\n/**\n * Disable submit button if search field is narrower than 72px\n * This is to avoid accidental clicks on button\n * Button is re-enabled on focus in handleInputFocus\n */\nconst setSubmitDisabledIfInputIsToSmallDesktop = () => {\n if ($inputDesktop?.clientWidth < 72 && $submitDesktop) $submitDesktop.disabled = true;\n};\n\n/**\n * Initialize an eventlistener for showing autosuggestions below the searchinput box.\n * @param inputElement Searchbox with user input to find suggestions\n */\nconst initSearchSuggestionListener = (inputElement) => {\n function ignoreSearchingForKeys(event) {\n return [\"ArrowDown\", \"ArrowUp\"].indexOf(event.code) === -1;\n }\n\n function meetsMinimumLength(inputElement) {\n return inputElement.value?.length >= 1;\n }\n\n inputElement.addEventListener(\n \"keyup\",\n debounce(async (event) => {\n if (meetsMinimumLength(inputElement) && ignoreSearchingForKeys(event)) {\n try {\n await handleAutoComplete();\n highlightUserValue();\n } catch (error) {\n // ignore\n }\n } else if (!meetsMinimumLength(inputElement)) {\n clearAutoCompleteResults();\n }\n }, 500)\n );\n};\n\n/**\n * Initialize an eventlistener\n * @param inputElement Searchbox with user input to find suggestions\n * @param autoCompleteList Suggestionlist based on the seach inputbox\n */\nconst initSearchNavigationSupportListener = (\n inputElement,\n autoCompleteList\n) => {\n if (!inputElement || !autoCompleteList) return;\n\n let selectedNode = null;\n\n const determineNextValidIndex = (eventCode, nodes) => {\n let currentIndex = selectedSearchResultIndex;\n let nextIndex = -1;\n switch (eventCode) {\n case \"ArrowDown\":\n nextIndex = ++currentIndex > nodes.length - 1 ? 0 : currentIndex;\n break;\n case \"ArrowUp\":\n nextIndex = --currentIndex < 0 ? nodes.length - 1 : currentIndex;\n break;\n default:\n nextIndex = -1;\n }\n\n return nextIndex;\n };\n\n const handleKeyUpNavigationListener = (event) => {\n const nodes = Array.prototype.slice.call(\n autoCompleteList.querySelectorAll(\"a\"),\n 0\n );\n\n selectedNode?.classList.remove(\"highlight\");\n\n const nextIndex = determineNextValidIndex(event.code, nodes);\n\n if (nextIndex === -1) {\n selectedNode = null;\n return;\n }\n\n if (nextIndex in nodes) {\n selectedSearchResultIndex = nextIndex;\n selectedNode = nodes[nextIndex];\n selectedNode.classList.add(\"highlight\");\n selectedNode.scrollIntoView({ block: \"nearest\" });\n\n inputElement.setAttribute(\"aria-activedescendant\", `option-${nextIndex}`);\n inputElement.value = selectedNode.innerText;\n setSearchFormAction(inputElement);\n }\n };\n\n //Add eventlistener\n inputElement.addEventListener(\"keyup\", handleKeyUpNavigationListener);\n};\n\n/**\n * Set up event listeners for both inputs triggering API requests and\n * highlighting auto complete values when input meets length requirement.\n */\nconst setupAutoComplete = () => {\n if ($inputMobile) {\n initSearchSuggestionListener($inputMobile);\n initSearchNavigationSupportListener($inputMobile, $autoCompleteMobile);\n }\n\n if ($inputDesktop) {\n initSearchSuggestionListener($inputDesktop);\n initSearchNavigationSupportListener($inputDesktop, $autoCompleteDesktop);\n }\n};\n\nexport default initSearch;\n","// https://w3c.github.io/aria-practices/examples/menubar/menubar-navigation.html\nimport ClassNames from \"./classNames.js\";\nimport DomElements from \"./domElements.js\";\nconst {\n $navContainerWrapper,\n $navPrimaryMainItems: $mainItems,\n $navPrimarySubNavs: $subNavs,\n $navPrimarySubNavGroups: $subNavGroups,\n} = DomElements;\nimport Shared from \"./shared.js\";\nconst {\n getActiveSubmenuId,\n updateActiveSubmenuId,\n closeAllSubmenus,\n toggle,\n isAnySubmenuOpen,\n} = Shared;\nimport Overlay from \"./handleOverlay.js\";\nconst { reevaluateOverlay } = Overlay;\n\n/**\n * Calculates width of each $subnav based on navigation container width and\n * number of child nav groups\n */\nconst calcSubNavsWidth = () => {\n const subNavList = Array.prototype.slice.call($subNavs, 0);\n subNavList.forEach(($subNav) => {\n const navGroupsCount = parseInt($subNav.dataset.columns);\n\n // Gutter sizes for >= 1440\n let gutterInner = 32;\n let gutterOuter = 32;\n\n if (window.innerWidth < 1440) {\n gutterInner = 24;\n }\n\n if (window.innerWidth < 1024) {\n gutterInner = 16;\n gutterOuter = 24;\n }\n\n // Calculate menu width without padding\n const computedStyle = getComputedStyle($navContainerWrapper);\n const menuWidth =\n $navContainerWrapper.clientWidth -\n parseFloat(computedStyle.paddingLeft) -\n parseFloat(computedStyle.paddingRight);\n\n // Calculate width of each subnav for screens equal or larger the 1024 (M up)\n if (window.innerWidth >= 1024) {\n const columnWidth = (menuWidth - gutterInner * 3) / 4;\n const width =\n columnWidth * navGroupsCount +\n (navGroupsCount - 1) * gutterInner +\n gutterOuter * 2;\n $subNav.style.width = `${width}px`;\n }\n\n // Set width of each subnav for breakpoint 768 - 1024 (M)\n // (As determined by design)\n if (window.innerWidth >= 768 && window.innerWidth < 1024) {\n $subNav.style.width = `${window.innerWidth}px`; // 100%\n if (navGroupsCount === 2) $subNav.style.width = \"572px\"; // Fixed number\n if (navGroupsCount === 1) $subNav.style.width = \"302px\"; // Fixed number\n }\n\n // Reset calculated width of each subnav for screens smaller then 768 (S down)\n if (window.innerWidth < 768) $subNav.style.width = \"\";\n });\n};\n\n/**\n * Handle initial setup\n */\nfunction initSubmenus() {\n handleActiveState();\n initKeyboardSupport();\n\n const mainItemList = Array.prototype.slice.call($mainItems, 0);\n mainItemList.forEach(($menuItem) => {\n $menuItem.addEventListener(\"click\", (event) => {\n const { submenuId: requestedSubmenuId } = $menuItem.dataset;\n\n // If no related submenu\n if (!requestedSubmenuId) return;\n\n // Prevent default behaviour links\n event.preventDefault();\n\n // Close open submenu\n if (getActiveSubmenuId()) toggle(getActiveSubmenuId(), \"close\");\n\n // If requested- same as active submenu\n if (getActiveSubmenuId() && getActiveSubmenuId() === requestedSubmenuId) {\n updateActiveSubmenuId(\"\");\n } else {\n updateActiveSubmenuId(requestedSubmenuId);\n toggle(requestedSubmenuId, \"open\");\n }\n reevaluateOverlay();\n });\n });\n\n // Set data attribute for each submenu with number of columns (for CSS)\n $subNavs.forEach(($submenu) => {\n const columns = $submenu.querySelectorAll(\n `.${ClassNames.navPrimary.subNavGroup}`\n ).length;\n $submenu.dataset.columns = columns.toString();\n });\n\n calcSubNavsWidth();\n}\n\n/**\n * Keyboard support (A11Y)\n */\nconst initKeyboardSupport = () => {\n // For main items\n const mainItemList = Array.prototype.slice.call($mainItems, 0);\n mainItemList.forEach(($item, i) => {\n $item.addEventListener(\"keyup\", (event) => {\n switch (event.code) {\n case \"ArrowDown\":\n case \"ArrowRight\":\n i + 1 in $mainItems && $mainItems[i + 1].focus();\n break;\n case \"ArrowUp\":\n case \"ArrowLeft\":\n i - 1 in $mainItems && $mainItems[i - 1].focus();\n break;\n case \"Home\":\n $mainItems[0].focus();\n break;\n case \"End\":\n $mainItems[$mainItems.length - 1].focus();\n break;\n }\n });\n });\n\n // For sub nav items\n const subNavGroupList = Array.prototype.slice.call($subNavGroups, 0);\n subNavGroupList.forEach(($subNavGroup) => {\n const $links = $subNavGroup.querySelectorAll(\"a\");\n const linkList = Array.prototype.slice.call($links, 0);\n linkList.forEach(($link, i) => {\n $link.addEventListener(\"keyup\", (event) => {\n switch (event.code) {\n case \"ArrowDown\":\n case \"ArrowRight\":\n i + 1 in $links && $links[i + 1].focus();\n break;\n case \"ArrowUp\":\n case \"ArrowLeft\":\n i - 1 in $links && $links[i - 1].focus();\n break;\n case \"Home\":\n $links[0].focus();\n break;\n case \"End\":\n $links[$links.length - 1].focus();\n break;\n case \"Escape\":\n closeAllSubmenus();\n reevaluateOverlay();\n $link.parentNode?.parentNode?.parentNode?.parentNode?.parentNode\n ?.querySelector(\"button\")\n ?.focus();\n break;\n }\n });\n });\n });\n};\n\n/**\n * Apply a visual active state based on pathname matching (window href and link href)\n *\n * (The API always provides an absolute path)\n */\nconst handleActiveState = () => {\n function addActiveClass($node) {\n $node.classList.add(\"shared-header__nav__link--is-active\");\n }\n\n const mainItemList = Array.prototype.slice.call($mainItems, 0);\n mainItemList.forEach(($menuItem) => {\n let menuItemLink = document.createElement(\"a\");\n\n if ($menuItem.nodeName === \"A\") menuItemLink.href = $menuItem.href;\n if ($menuItem.nodeName === \"BUTTON\")\n menuItemLink.href = $menuItem.dataset.href;\n\n if (menuItemLink) {\n const currentLocation = window.location;\n const isHomeLink = $menuItem.dataset.isHomeItem;\n const isPathPartOfCurrentLocation =\n currentLocation.pathname.toLowerCase().indexOf(menuItemLink.pathname.toLowerCase()) !== -1;\n\n if (currentLocation.hostname.toLowerCase() !== menuItemLink.hostname.toLowerCase()) {\n // External site link, do nothing\n return;\n }\n\n if (isHomeLink) {\n if (menuItemLink.pathname.toLowerCase() === currentLocation.pathname.toLowerCase()) {\n addActiveClass($menuItem);\n }\n } else {\n if (isPathPartOfCurrentLocation) {\n addActiveClass($menuItem);\n openSubMenuAndScroll($menuItem, currentLocation.pathname);\n }\n }\n }\n });\n};\n\n/**\n * Open menu on mobile devices and scroll to clicked link\n */\nfunction openSubMenuAndScroll($menuItem, pathname) {\n if (window.innerWidth < 768) {\n const { submenuId: requestedSubmenuId } = $menuItem.dataset;\n if (!requestedSubmenuId) return;\n updateActiveSubmenuId(requestedSubmenuId);\n // open the submenu\n toggle(requestedSubmenuId, \"open\");\n\n // scroll to the clicked link\n const subNavList = Array.prototype.slice.call($subNavs, 0);\n subNavList.forEach(($submenu) => {\n if ($submenu.dataset.submenuId === requestedSubmenuId) {\n const $links = $submenu.querySelectorAll(\"a\");\n const linkList = Array.prototype.slice.call($links, 0);\n linkList.forEach(($link) => {\n if (pathname.toLowerCase() === $link.pathname.toLowerCase()) {\n $link.scrollIntoView(false);\n }\n });\n }\n });\n }\n}\n\nexport default {\n calcSubNavsWidth,\n closeAllSubmenus,\n initSubmenus,\n isAnySubmenuOpen,\n};\n","import { debounce } from \"../../@helpers/js/queue-processing.js\";\n\n/**\n * Set the 'actual' viewport height based on the current window size.\n */\nconst viewportHeight = () => {\n document.documentElement.style.setProperty(\n \"--viewport-height\",\n `${window.innerHeight}px`\n );\n};\n\n/**\n * Set height and recall on resize.\n */\nexport default function initViewportHeight() {\n window.addEventListener(\"resize\", debounce(viewportHeight, 250));\n viewportHeight();\n}\n","import { debounce } from \"../../@helpers/js/queue-processing.js\";\n\nimport initViewportHeight from \"./handleViewportHeights.js\";\nimport NavContainer from \"./handleNavContainer.js\";\nconst { initMenuButton, toggleNavigation } = NavContainer;\nimport Shared from \"./shared.js\";\nconst {\n isMobileMenuOpen,\n isAnySubmenuOpen,\n closeAllSubmenus,\n} = Shared;\nimport initNavDomain from \"./handleNavDomain.js\";\nimport Overlay from \"./handleOverlay.js\";\nconst { initOverlay, reevaluateOverlay } = Overlay;\nimport {searchMobileisOpen, clickToggleSearchMobile} from \"./handleSearch.js\";\nimport Submenus from \"./handleSubmenus.js\";\nconst { initSubmenus, calcSubNavsWidth } = Submenus;\n\nclass Navigation {\n constructor(element) {\n this._element = element;\n\n this.init();\n }\n\n init() {\n let cachedWidth = window.innerWidth;\n initViewportHeight();\n initMenuButton();\n initNavDomain();\n initOverlay();\n initSubmenus();\n\n window.addEventListener(\n \"resize\",\n debounce(() => {\n // catch unexpected resize events (IOS/Android scroll)\n if (cachedWidth === window.innerWidth) {\n return;\n }\n cachedWidth = window.innerWidth;\n\n if (isAnySubmenuOpen()) {\n closeAllSubmenus();\n }\n\n if (searchMobileisOpen()) {\n clickToggleSearchMobile();\n }\n\n if (isMobileMenuOpen()) {\n toggleNavigation(\"close\");\n }\n\n reevaluateOverlay();\n calcSubNavsWidth();\n }, 250)\n );\n }\n}\n\nexport default Navigation;\n","import { LitElement, css, html } from \"lit\";\n\nexport class CzLoader extends LitElement {\n\tstatic styles = css`\n\t\t@layer component {\n\t\t\t:host {\n\t\t\t\t--_cz-loader-color: var(--cz-loader-color, currentcolor);\n\t\t\t\t--_cz-loader-width: var(--cz-loader-width, 50px);\n\t\t\t\t--_cz-loader-height: var(--cz-loader-height, 50px);\n\n\t\t\t\tdisplay: block;\n\n\t\t\t\tmax-width: var(--_cz-loader-width);\n\t\t\t\tmax-height: var(--_cz-loader-height);\n\t\t\t\tstroke: var(--_cz-loader-color);\n\t\t\t}\n\t\t}\n\t`;\n\n\tstatic properties = {\n\t\ttext: {type: String},\n\t};\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.text = 'loading...';\n\t}\n\n\trender() {\n\t\treturn html``;\n\t}\n}\n\nif (!customElements.get('cz-loader')) {\n\tcustomElements.define('cz-loader', CzLoader);\n}","import { LitElement, css, html } from \"lit\";\n\nexport class CzIcon extends LitElement {\n\tstatic styles = css`\n\t\t@layer component {\n\t\t\t:host {\n\t\t\t\t--_cz-icon-color: var(--cz-icon-color, currentcolor);\n\t\t\t\t--_cz-icon-width: var(--cz-icon-width, 50px);\n\t\t\t\t--_cz-icon-height: var(--cz-icon-height, 50px);\n\t\t\t\tdisplay: block;\n\t\t\t\twidth: var(--_cz-icon-width);\n\t\t\t\theight: var(--_cz-icon-height);\n\t\t\t\tmax-width: var(--_cz-icon-width);\n\t\t\t\tmax-height: var(--_cz-icon-height);\n\t\t\t}\n\t\t\t\n\t\t\t:host(cz-icon[type=stroke]) ::slotted(svg) {\n\t\t\t\tstroke: var(--_cz-icon-color);\n\t\t\t\tfill: transparent;\n\t\t\t}\n\t\t\t\n\t\t\t::slotted(svg) {\n\t\t\t\tfill: var(--_cz-icon-color);\n\t\t\t\twidth: 100%;\n\t\t\t\theight: 100%;\n\t\t\t}\n\t\t}\n\t`;\n\n\tstatic properties = {\n\t\ttype: {type: String},\n\t\tname: {type: String}\n\t};\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.type = 'fill';\n\t\tthis.name = 'chevron';\n\t}\n\n\trender() {\n\t\treturn html``;\n\t}\n}\n\nif (!customElements.get('cz-icon')) {\n\tcustomElements.define('cz-icon', CzIcon);\n}","import { LitElement, css, html } from 'lit';\nimport { CzLoader } from '../cz-loader/cz-loader.js';\nimport { CzIcon } from '../cz-icon/cz-icon.js';\n\n/**\n * Represents a custom content loader component.\n * should be used as a basis for loading content based on a url\n * will show the cz-loader component until the content is loaded\n * @extends LitElement\n */\nexport class CzContentloader extends LitElement {\n\tstatic styles = css`\n\t\t@layer component {\n\t\t\t:host {\n\t\t\t\tdisplay: grid;\n\t\t\t}\n\t\t\t:host(:empty){\n\t\t\t\taspect-ratio: 1/.5;\n\t\t\t}\n\t\t\tcz-icon {\n\t\t\t\tmargin: auto;\n\t\t\t}\n\t\t}\n\t`;\n\n\t#url = false;\n\n\t/**\n\t * override this method in the class that extends this contentloader\n\t * @param {url} url \n\t * @returns promise\n\t */\n\tcallBackend = async (url) => {\n\t\tlet result;\n\t\tresult = `
This is what would get loaded if you don't override the async callBackend method
`;\n\t\treturn result;\n\t}\n\t\n\trender() {\n\t\treturn html``;\n\t}\n\n\n\t/**\n\t * Don't forget to call loadContent method from this function if you override it\n\t *\n\t * @param {*} changedProperties\n\t */\n\tupdated(changedProperties) {\n\t\tif (changedProperties) {\n\t\t\tthis.innerHTML = '';\n\t\t\tthis.loadContent()\n\t\t\t\t.then((f) => console.log(f))\n\t\t\t\t.catch((e) => console.log(e));\n\t\t}\n\t}\n\n\tasync loadContent() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (this.#url) {\n\t\t\t\t\tthis.callBackend(this.#url).then(result => {\n\t\t\t\t\t\tthis.innerHTML = result;\n\t\t\t\t\t\treturn resolve('succes!');\n\t\t\t\t\t}).catch(() => reject(new Error('Error loading content!')));\n\t\t\t\t}\n\t\t\t}, 10);\n\t\t});\n\t}\n\t\n\tconstructor() {\n\t\tsuper();\n\t\tthis.#url = this.getAttribute('url');\n\t}\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}export{i as Directive,t as PartType,e as directive};\n//# sourceMappingURL=directive.js.map\n","import{nothing as t,noChange as i}from\"../lit-html.js\";import{Directive as r,PartType as s,directive as n}from\"../directive.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */class e extends r{constructor(i){if(super(i),this.it=t,i.type!==s.CHILD)throw Error(this.constructor.directiveName+\"() can only be used in child bindings\")}render(r){if(r===t||null==r)return this._t=void 0,this.it=r;if(r===i)return r;if(\"string\"!=typeof r)throw Error(this.constructor.directiveName+\"() called with a non-string value\");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}e.directiveName=\"unsafeHTML\",e.resultType=1;const o=n(e);export{e as UnsafeHTMLDirective,o as unsafeHTML};\n//# sourceMappingURL=unsafe-html.js.map\n","import Focusable from \"./focusable.js\";\n\nconst _TAB_KEY = 'Tab';\nconst _ESCAPE_KEY = 'Escape';\n\nexport function trapFocus(element) {\n\tif (!element) return;\n\n\tconst focusable = Focusable(element);\n\n\tconst evHandlers = {\n\t\tkeepFocus: (e) => keepFocus(e),\n\t\tkeyPress: (e) => onKeypress(e)\n\t}\n\n\tconst getFocusableChildren = () => {\n\t\tconst excludedSlots = element?.getExcludedSlots?.() || [];\n\t\tconst focusableBefore = element?.getFocusableBefore?.() || [];\n\t\tconst focusableAfter = element?.getFocusableAfter?.() || [];\n\t\treturn ([...focusableBefore, ...focusable.keyboardOnly, ...focusableAfter]).filter((child) => !!(\n\t\t\t!excludedSlots?.includes(child.getAttribute('slot')) &&\n\t\t\t(child.offsetWidth ||\n\t\t\t\tchild.offsetHeight ||\n\t\t\t\tchild.getClientRects().length)\n\t\t));\n\t}\n\n\tconst setFocusToFirstItem = () => {\n\t\tconst focusableChildren = getFocusableChildren();\n\t\tconst focused = element.querySelector('[autofocus]') || focusableChildren[0];\n\n\t\tif (focused) {\n\t\t\tfocused.focus();\n\t\t}\n\t}\n\n\tconst onKeypress = (event) => {\n\t\t// If the dialog is shown and the ESCAPE key is being pressed, prevent any\n\t\t// further effects from the ESCAPE key and hide the dialog, unless its role\n\t\t// is 'alertdialog', which should be modal\n\t\tif (event.key === _ESCAPE_KEY && ((event.target.matches('input[type=\"search\"]') && event.target.value) || (!event.target.matches('[role=\"switch\"]') && event.target.value) || (!event.target.matches('[role=\"combobox\"]') && event.target.value))) {\n\t\t\tevent.preventDefault();\n\t\t}\n\n\t\t// If the dialog is shown and the TAB key is being pressed, make sure the\n\t\t// focus stays trapped within the dialog element\n\t\tif (event.key === _TAB_KEY) {\n\t\t\ttrapTabKey(event);\n\t\t}\n\t}\n\n\tconst trapTabKey = (event) => {\n\t\tconst focusableChildren = getFocusableChildren();\n\t\tlet activeElement = document.activeElement\n\t\tif (activeElement === element) {\n\t\t\tactiveElement = focusableChildren[0];\n\t\t}\n\t\tconst focusedItemIndex = focusableChildren.indexOf(activeElement);\n\n\t\tif (focusableChildren.length === 1) {\n\t\t\tfocusableChildren[0].focus();\n\t\t\tevent.preventDefault();\n\t\t} else {\n\n\t\t\t// If the SHIFT key is being pressed while tabbing (moving backwards) and\n\t\t\t// the currently focused item is the first one, move the focus to the last\n\t\t\t// focusable item from the dialog element\n\t\t\tif (event.shiftKey && focusedItemIndex === 0) {\n\t\t\t\tfocusableChildren[focusableChildren.length - 1].focus();\n\t\t\t\tevent.preventDefault();\n\t\t\t\t// If the SHIFT key is not being pressed (moving forwards) and the currently\n\t\t\t\t// focused item is the last one, move the focus to the first focusable item\n\t\t\t\t// from the dialog element\n\t\t\t} else if (!event.shiftKey && focusedItemIndex === focusableChildren.length - 1) {\n\t\t\t\tfocusableChildren[0].focus();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t}\n\n\tconst keepFocus = (event) => {\n\t\t// If the dialog is shown and the focus is not within the dialog element,\n\t\t// move it back to its first focusable child\n\t\tif (!element.contains(event.target)) {\n\t\t\tsetFocusToFirstItem();\n\t\t}\n\t}\n\n\treturn {\n\t\tsetFocusToFirstItem,\n\t\tevHandlers\n\t};\n}\n","export default function Focusable(element = document) {\n\treturn {\n\t\tget length() {\n\t\t\treturn this.keyboardOnly.length\n\t\t},\n\n\t\tget all() {\n\t\t\treturn [\n\t\t\t\t...element.querySelectorAll(\n\t\t\t\t\t`a[href],\n\t\t\t\t\tarea[href],\n\t\t\t\t\tbutton,\n\t\t\t\t\tinput,\n\t\t\t\t\ttextarea,\n\t\t\t\t\tselect,\n\t\t\t\t\tdetails,\n\t\t\t\t\tiframe,\n\t\t\t\t\tembed,\n\t\t\t\t\tobject,\n\t\t\t\t\tsummary,\n\t\t\t\t\tdialog,\n\t\t\t\t\taudio[controls],\n\t\t\t\t\tvideo[controls],\n\t\t\t\t\t[contenteditable],\n\t\t\t\t\t[tabindex]`\n\t\t\t\t)].filter(el => {\n\t\t\t\t\tif (el.hasAttribute('disabled')) return false;\n\t\t\t\t\tif (el.hasAttribute('hidden')) return false;\n\t\t\t\t\tif (el.hasAttribute('inert')) return false;\n\t\t\t\t\tif (window.getComputedStyle(el).display === 'none') return false;\n\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t},\n\n\t\tget keyboardOnly() {\n\t\t\treturn this.all.filter(el => el.tabIndex > -1);\n\t\t},\n\n\t\tget firstFocusable() {\n\t\t\treturn this.keyboardOnly[0];\n\t\t},\n\n\t\tget lastFocusable() {\n\t\t\treturn this.keyboardOnly[this.length - 1];\n\t\t},\n\t}\n}","import { LitElement, css, html } from \"lit\";\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\nimport { angleLeft, angleRight } from \"@cz/icons/dist/cz/iconSprites.mjs\";\nimport { trapFocus } from '../helpers/trap-focus.js';\n\nexport class CzSidepanel extends LitElement {\n\tstatic styles = css`\n\t\t@layer component {\n\t\t\t:host {\n\t\t\t\t--_cz-sidepanel-backdrop-padding: var(--cz-sidepanel-backdrop-padding, var(--sidepanel-backdrop-padding, 1rem));\n\t\t\t\t--_cz-sidepanel-backdrop-color: var(--cz-sidepanel-backdrop-color, var(--sidepanel-backdrop-color, black));\n\t\t\t\t\n\t\t\t\t--_cz-sidepanel-background-color: var(--cz-sidepanel-background-color, var(--sidepanel-background-color, canvas));\n\t\t\t\t--_cz-sidepanel-text-color: var(--cz-sidepanel-text-color, var(--sidepanel-text-color, canvastext));\n\t\t\t\t--_cz-sidepanel-width: min(max(var(--cz-sidepanel-width), 26rem), calc(100vi - var(--_cz-sidepanel-backdrop-padding, 1rem)));\n\t\t\t\t--_cz-sidepanel-transition-duration: var(--cz-sidepanel-transition-duration, var(--sidepanel-transition-duration, 0.25s));\n\t\t\t\t--_cz-sidepanel-transition-timing: var(--cz-sidepanel-transition-timing, var(--sidepanel-transition-timing, ease-in-out));\n\t\t\t\t--_cz-sidepanel-content-padding-block: var(--cz-sidepanel-content-padding-block, var(--sidepanel-content-padding-block, 0px 2rem));\n\t\t\t\t--_cz-sidepanel-content-padding-inline: var(--cz-sidepanel-content-padding-inline, var(--sidepanel-content-padding-inline, 1rem));\n\n\t\t\t\t--cz-sidepanel-width: var(--sidepanel-width, 26rem);\n\t\t\t\t--close-button-text-color-hover: var(--color-primary-bird, #333333);\n\t\t\t\t--close-button-border-color: var(--color-secondary-lion,#989691);\n\n\t\t\t\t--focus-ring-color: var(--a11y-focus-ring-color, var(--color-tertiary-otter, #0071b2));\n\t\t\t}\n\n\t\t\t.drawer,\n\t\t\t.drawer[open].closing {\n\t\t\t\t--_translate-inline: var(--translate-inline, var(--_cz-sidepanel-width));\n\t\t\t\t--_sidepanel-onleft: var(--sidepanel-onleft, unset);\n\t\t\t\t--_sidepanel-onright: var(--sidepanel-onright, 100vi);\n\t\t\t\t// Remove default dialog styling\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0;\n\t\t\t\tmax-height: unset;\n\t\t\t\tborder: none;\n\t\t\t\tleft: var(--_sidepanel-onright);\n\t\t\t\t\n\t\t\t\theight: 100%;\n\t\t\t\twidth: var(--_cz-sidepanel-width);\n\t\t\t\t\n\t\t\t\ttranslate: var(--_translate-inline) 0px;\n\n\t\t\t\tcolor: inherit;\n\t\t\t\tbox-sizing: border-box;\n\t\t\t\toverflow-y: auto;\n\t\t\t\toverscroll-behavior: contain;\n\t\t\t\tcontainer-type: inline-size;\n\t\t\t\t\n\t\t\t\tbackground-color: var(--_cz-sidepanel-background-color, white);\n\t\t\t\tmax-width: var(--_cz-sidepanel-width, 100%);\n\t\t\t\t\n\t\t\t\t> .inner {\n\t\t\t\t\tposition: relative;\n\t\t\t\t\tinset: 0;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: column;\n\t\t\t\t\twidth: 100cqi;\n\t\t\t\t\tmax-width: 100%;\n\t\t\t\t\tmin-width: fit-content;\n\t\t\t\t\tmin-height: 100%;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.drawer::backdrop,\n\t\t\t.drawer[open].closing::backdrop {\n\t\t\t\topacity: 0;\n\t\t\t\tbackground-color: color-mix( in srgb, var(--_cz-sidepanel-backdrop-color, black) 40%, transparent);\n\t\t\t}\n\n\t\t\tslot[name=close] {\n\t\t\t\tleft: 0;\n\t\t\t}\n\n\t\t\t/* animate */\n\t\t\t@media screen and (prefers-reduced-motion: no-preference) {\n\t\t\t\t.drawer {\n\t\t\t\t\ttransition-property: translate, display, overlay;\n\t\t\t\t\ttransition-duration: var(--_cz-sidepanel-transition-duration);\n\t\t\t\t\ttransition-timing-function: var(--_cz-sidepanel-transition-timing);\n\t\t\t\t\ttransition-behavior: allow-discrete\n\t\t\t\t}\n\t\t\t\t.drawer::backdrop {\n\t\t\t\t\ttransition-property: opacity, display, overlay;\n\t\t\t\t\ttransition-duration: var(--_cz-sidepanel-transition-duration);\n\t\t\t\t\ttransition-timing-function: var(--_cz-sidepanel-transition-timing);\n\t\t\t\t\ttransition-behavior: allow-discrete\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.drawer.open {\n\t\t\t\tdisplay: block;\n\t\t\t}\n\n\t\t\t.drawer[open] {\n\t\t\t\t--sidepanel-onright: auto;\n\t\t\t\ttranslate: 0px 0px;\n\t\t\t\tbox-shadow: color-mix( in srgb, var(--_cz-sidepanel-backdrop-color, black) 20%, transparent) var(--sidepanel-box-shadow-direction, -6px 0px 0px 0px);\n\n\t\t\t\t&::backdrop {\n\t\t\t\t\topacity: 1;\n\t\t\t\t}\t\n\t\t\t}\n\n\t\t\t@starting-style {\n\t\t\t\t.drawer[open]::backdrop {\n\t\t\t\t\topacity: 0;\t\t\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t.content {\n\t\t\t\tpadding-block: var(--_cz-sidepanel-content-padding-block, 0px 2rem);\n\t\t\t\tpadding-inline: var(--_cz-sidepanel-content-padding-inline, 1rem);\n\t\t\t}\n\n\t\t\tslot[name=close] {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\tposition: sticky;\n\t\t\t\ttop: 1rem;\n\t\t\t\tmargin-bottom: 1rem;\n\t\t\t\twidth: min-content;\n\t\t\t\tz-index: 10;\n\t\t\t}\n\n\t\t\t.closeButton {\n\t\t\t\talign-items: center;\n\t\t\t\tappearance: none;\n\t\t\t\tbackground-color: color-mix(in srgb, rgb(0 0 0) 0%, white);\n\t\t\t\tborder-radius: var(--close-button-border-radius, 0 6px 6px 0);\n\t\t\t\tborder: 1px solid;\n\t\t\t\tborder-color: var(--close-button-border-color);\n\t\t\t\talign-self: baseline;\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\tcursor: pointer;\n\t\t\t\tfont-weight: bold;\n\t\t\t\tjustify-content: flex-start;\n\t\t\t\toverflow: hidden;\n\t\t\t\ttransition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,border-color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,color 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;\n\t\t\t\tvertical-align: top;\n\t\t\t\tcolumn-gap: 6px;\n\t\t\t\tfont-size: 18px;\n\t\t\t\tline-height: 22px;\n\t\t\t\tbox-shadow: none;\n\t\t\t\tborder-width: var(--close-button-border-width, 1px 1px 1px 0);\n\t\t\t\talign-self: baseline;\n\t\t\t\tpadding: 13px 20px 13px 1rem;\n\n\t\t\t\t&:hover {\n\t\t\t\t\tcolor: var(--close-button-text-color-hover);\n\t\t\t\t\tbackground-color: color-mix(in srgb, rgb(0 0 0) 4%, white);\n\t\t\t\t}\n\n\t\t\t\t&:focus-visible {\n\t\t\t\t\toutline-color: var(--focus-ring-color);\n\t\t\t\t\t@supports (background-color: color-mix(in srgb, white, black)){\n\t\t\t\t\t\toutline-color: color-mix(in srgb, var(--focus-ring-color) 86%, transparent);\n\t\t\t\t\t}\n\n\t\t\t\t\toutline-style: solid;\n\t\t\t\t\toutline-width: 3px;\n\n\t\t\t\t\toutline-offset: 2px;\n\t\t\t\t\t@media screen and (prefers-reduced-motion: no-preference) {\n\t\t\t\t\t\ttransition: outline-offset .125s linear;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t&:focus,\n\t\t\t\t&:active {\n\t\t\t\t\tcolor: var(--close-button-text-color-hover); \n\t\t\t\t\tbackground-color: color-mix(in srgb, rgb(0 0 0) 12%, white);\n\t\t\t\t}\n\n\t\t\t\t& > span {\n\t\t\t\t\ttext-wrap: nowrap;\n\t\t\t\t}\n\n\t\t\t\t& > svg {\n\t\t\t\t\tfill: currentcolor;\n\t\t\t\t\twidth: 20px;\n\t\t\t\t\theight: 20px;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t@layer variant {\n\t\t\t:host([wide]) {\n\t\t\t\t--cz-sidepanel-width: 100vi;\n\t\t\t}\t\n\n\t\t\t:host([left]) {\n\t\t\t\t--translate-inline: calc(var(--_cz-sidepanel-width) * -1);\n\t\t\t\t--sidepanel-onleft: 100vi;\n\t\t\t\t--_sidepanel-onright: initial;\n\t\t\t\t--sidepanel-box-shadow-direction: 6px 0px 0px 0px;\n\t\t\t\t--close-button-border-width: 1px 0 1px 1px;\n\t\t\t\t--close-button-border-radius: 6px 0 0 6px;\n\t\t\t}\n\n\t\t\t:host([left]) slot[name=close] {\n\t\t\t\tright: 0;\n\t\t\t\talign-self: flex-end;\n\t\t\t}\n\n\t\t\t:host([left]) .drawer[open] {\n\t\t\t\t--sidepanel-onleft: auto;\n\t\t\t}\n\n\t\t\t:host([left]) .drawer.open {\n\t\t\t\t--sidepanel-onright: auto;\n\t\t\t\tleft: calc(50% - 50vi);\n\t\t\t}\n\n\t\t\t:host([left]) .drawer {\n\t\t\t\tright: var(--_sidepanel-onleft);\n\t\t\t}\n\t\t}\n\t`;\n\n\tstatic properties = {\n\t\tcloseText: { type: String },\n\t\topen: { type: Boolean, reflect: true }\n\t};\n\n\tget dialog() {\n\t\treturn this._dialog ??= this.renderRoot?.querySelector('dialog');\n\t}\n\n\tclickInsideDialog(node) {\n\t\tlet result = false;\n\t\tconst slotted = this.dialog?.querySelector('slot:not([name])')?.assignedNodes({ flatten: true });\n\t\t// if the node is not visible, or is slotted, or is inside a slotted node, it is considered to be inside the dialog\n\t\tresult = !node.checkVisibility() || slotted.includes(node) || slotted.some((n) => n.contains(node));\n\n\t\tif (!result) {\n\t\t\tresult = node.closest('.inner') === this.dialog?.firstElementChild;\n\t\t}\n\t\treturn result;\n\t}\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.closeText = 'terug';\n\t\tthis.open = false;\n\t\tthis.focusTrap = trapFocus(this);\n\t}\n\n\tgetExcludedSlots() {\n\t\treturn ['trigger'];\n\t}\n\n\tgetFocusableBefore() {\n\t\tconst result = [];\n\t\tconst closebtn = this.dialog?.querySelector('.closeButton');\n\t\tif (closebtn) result.push(closebtn);\n\t\treturn result;\n\t}\n\n\tcreateRenderRoot() {\n\t\tconst root = super.createRenderRoot();\n\t\troot.addEventListener(\n\t\t\t'click',\n\t\t\t(e) => {\n\t\t\t\tif (!this.open && !this.dialog?.open) {\n\t\t\t\t\tthis.openSidepanel();\n\t\t\t\t} else if (this.open && this.dialog?.open && !this.clickInsideDialog(e.target)) {\n\t\t\t\t\tthis.closeSidepanel();\n\t\t\t\t}\n\t\t\t});\n\t\treturn root;\n\t}\n\n\tupdated(changedProperties) {\n\t\tsuper.updated?.(changedProperties);\n\t\tif (this.open && !this.dialog?.open) {\n\t\t\tthis.openSidepanel();\n\t\t}\n\t}\n\n\tevHandler = {\n\t\tbackbuttonPress: (e) => this.onBackbuttonPress(e)\n\t}\n\n\tonBackbuttonPress(event) {\n\t\tif (event && event.state == 'backPressed' && this.open) {\n\t\t\tconst shouldStayOpen = this.hasAttribute('stayOpenOnBack') && this.getAttribute('stayOpenOnBack').toLowerCase() === 'true';\n\n\t\t\tif (!shouldStayOpen) {\n\t\t\t\tthis.closeSidepanel();\n\t\t\t}\n\t\t}\n\t}\n\n\topenSidepanel() {\n\t\tthis.open = true;\n\t\tsetTimeout(() => {\n\t\t\tthis.dialog?.showModal();\n\n\t\t\t// Set the focus to the first focusable child of the dialog element\n\t\t\tthis.focusTrap.setFocusToFirstItem();\n\n\t\t\t// Bind a focus event listener to the body element to make sure the focus\n\t\t\t// stays trapped inside the dialog while open, and start listening for some\n\t\t\t// specific key presses (TAB and ESC)\n\t\t\tdocument.body.addEventListener('focus', this.focusTrap.evHandlers.keepFocus, true);\n\t\t\tdocument.addEventListener('keydown', this.focusTrap.evHandlers.keyPress);\n\n\t\t\tif (window.history.state === 'showOverlay') {\n\t\t\t\twindow.removeEventListener('popstate', this.evHandler.backbuttonPress);\n\t\t\t} else {\n\t\t\t\tif (window.history.state === 'backPressed') {\n\t\t\t\t\twindow.removeEventListener('popstate', this.evHandler.backbuttonPress);\n\t\t\t\t} else {\n\t\t\t\t\tthis._oldState = window.history.state;\n\t\t\t\t\twindow.history.replaceState('backPressed', null, null);\n\t\t\t\t}\n\t\t\t\twindow.history.pushState('showOverlay', null, null);\n\t\t\t}\n\t\t\twindow.addEventListener('popstate', this.evHandler.backbuttonPress);\n\t\t}, 20);\n\t}\n\n\tcloseSidepanel() {\n\t\tthis.dialog?.classList.add('closing');\n\t\tsetTimeout(() => {\n\t\t\t// check if not already closed like by esc key\n\t\t\tif (this.dialog?.open) {\n\t\t\t\tthis.dialog?.close();\n\t\t\t} else {\n\t\t\t\tthis.dialog?.classList.remove('closing');\n\t\t\t\tthis.open = false;\n\t\t\t}\n\t\t\t// Remove the focus event listener to the body element and stop listening\n\t\t\t// for specific key presses\n\t\t\tdocument.body.removeEventListener('focus', this.focusTrap.evHandlers.keepFocus, true);\n\t\t\tdocument.removeEventListener('keydown', this.focusTrap.evHandlers.keyPress);\n\t\t\twindow.removeEventListener('popstate', this.evHandler.backbuttonPress);\n\n\t\t\tif (window.history.state === 'backPressed' && !!this._oldState && this._oldState !== 'backPressed') {\n\t\t\t\twindow.history.replaceState(this._oldState, null, null);\n\t\t\t}\n\t\t}, 300);\n\t}\n\n\thandleCancel(event) {\n\t\tevent.preventDefault();\n\t\tthis.closeSidepanel();\n\t}\n\n\trender() {\n\t\treturn html`\n\t\t\n\t\t\n\t\t`;\n\t}\n}\nif (!customElements.get('cz-sidepanel')) {\n\tcustomElements.define('cz-sidepanel', CzSidepanel);\n}\n\nCSS.registerProperty?.({\n\tname: '--cz-sidepanel-width',\n\tsyntax: '',\n\tinherits: true,\n\tinitialValue: '30%',\n});","export const angleDown = ``;\nexport const angleLeft = ``;\nexport const angleRight = ``;\nexport const angleUp = ``;\nexport const arrowDown = ``;\nexport const arrowLeft = ``;\nexport const arrowRight = ``;\nexport const arrowUp = ``;\nexport const bars = ``;\nexport const book = ``;\nexport const briefcaseMedical = ``;\nexport const building = ``;\nexport const bullit = ``;\nexport const busCustom = ``;\nexport const calculator = ``;\nexport const calendar = ``;\nexport const car = ``;\nexport const chartPie = ``;\nexport const checkCircle = ``;\nexport const check = ``;\nexport const checkboxSelected = ``;\nexport const checkboxUnselected = ``;\nexport const chevron = ``;\nexport const children = ``;\nexport const clinicMedical = ``;\nexport const clipboardMedical = ``;\nexport const clockCustom = ``;\nexport const close = ``;\nexport const coins = ``;\nexport const comments = ``;\nexport const crossout = ``;\nexport const download = ``;\nexport const dumbellsCustom = ``;\nexport const earthAmericas = ``;\nexport const envelope = ``;\nexport const exclamationCircle = ``;\nexport const exclamationTriangle = ``;\nexport const externalLink = ``;\nexport const eyeSlash = ``;\nexport const eye = ``;\nexport const facebook = ``;\nexport const fileContract = ``;\nexport const fileDownload = ``;\nexport const fileExcel = ``;\nexport const fileInvoiceEuro = ``;\nexport const filePdf = ``;\nexport const fileWord = ``;\nexport const file = ``;\nexport const footCustom = ``;\nexport const handHoldingHeart = ``;\nexport const handshake = ``;\nexport const headSideHeart = ``;\nexport const home = ``;\nexport const hospital = ``;\nexport const infoCircle = ``;\nexport const instagram = ``;\nexport const linkedinIn = ``;\nexport const loader = ``;\nexport const lock = ``;\nexport const mapMarker = ``;\nexport const messageSmile = ``;\nexport const minus = ``;\nexport const mobile = ``;\nexport const pen = ``;\nexport const pencil = ``;\nexport const peopleGroup = ``;\nexport const people = ``;\nexport const percent = ``;\nexport const percent100 = ``;\nexport const percent70 = ``;\nexport const percent75 = ``;\nexport const percent85 = ``;\nexport const personBreastfeeding = ``;\nexport const phone = ``;\nexport const pills = ``;\nexport const plus = ``;\nexport const questionCircle = ``;\nexport const quoteLeft = ``;\nexport const quoteRight = ``;\nexport const radiobuttonSelected = ``;\nexport const radiobuttonUnselected = ``;\nexport const search = ``;\nexport const shoppingCart = ``;\nexport const skinCustom = ``;\nexport const sortDown = ``;\nexport const sortUp = ``;\nexport const speakEarCustom = ``;\nexport const stopwatch = ``;\nexport const thumbsDown = ``;\nexport const thumbsUp = ``;\nexport const timesCircle = ``;\nexport const times = ``;\nexport const tooth = ``;\nexport const transgender = ``;\nexport const trillium = ``;\nexport const twitter = ``;\nexport const unlock = ``;\nexport const userCheck = ``;\nexport const userCircle = ``;\nexport const userDoctorHairLong = ``;\nexport const userEdit = ``;\nexport const userPlus = ``;\nexport const userTimes = ``;\nexport const user = ``;\nexport const vergoedingenZoekenCustom = ``;\nexport const whatsapp = ``;\nexport const wheelchairMove = ``;\nexport const x = ``;\nexport const youtube = ``;","/**\n * Module to show suggestions on typing. a simple, autocomplete module for modern browsers\n * @author Serge Huijben\n *\n * MIT license\n */\nimport { registerTriggers, triggerNotify } from \"../../@helpers/js/observer.js\";\n\nclass SearchSuggestions {\n constructor(\n element,\n {\n autosuggestUrl = \"\",\n method = \"GET\",\n key = \"key\",\n autosuggestKey = \"q\",\n subtitleprefix = \"Nr:\",\n autofocus = false,\n sort = false,\n filter = false,\n minChars = 3,\n maxItems = 15,\n autoFirst = false,\n } = {}\n ) {\n this._options = {\n autosuggestUrl,\n method,\n key,\n autosuggestKey,\n subtitleprefix,\n autofocus,\n sort,\n filter,\n minChars,\n maxItems,\n autoFirst,\n };\n this._element = element;\n this.input = this._element.querySelector(\"input.c-search-suggestions__input\");\n this.submitButton = this._element.querySelector(\"[data-search-suggestions-button]\"); // use this attribute only if you want autosuggest on button click\n this.notFoundTemplate = this._element.querySelector(\"[data-search-suggestions-404]\");\n this.overMaxFoundTemplate = this._element.querySelector(\"[data-search-suggestions-over-max]\");\n\n if (this.input) {\n this._init();\n }\n }\n\n // Setup\n _init() {\n this.input.setAttribute(\"autocomplete\", \"off\");\n this.input.setAttribute(\"aria-autocomplete\", \"list\");\n this.input.value = getQueryString(this._options.key);\n\n this.index = -1;\n\n this.filter = (text, input, filter) => filter ? new RegExp(regExpEscape(input.trim()), \"i\").test(text) : true;\n\n this.sort = (a, b, value) => {\n if (value && isNaN(value)) {\n const val = regExpEscape(value);\n let aio = a.naam.toLowerCase().indexOf(val.toLowerCase());\n let bio = b.naam.toLowerCase().indexOf(val.toLowerCase());\n\n if (aio < 0) {\n let areg = new RegExp(val.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\"), \"g\");\n aio = areg.test(a.normalizedName) ? areg.lastIndex - val.length + 99\n : a.length + 199;\n }\n if (bio < 0) {\n let breg = new RegExp(val.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\"), \"g\");\n bio = breg.test(b.normalizedName) ? breg.lastIndex - val.length + 99 : b.length + 199;\n }\n return aio - bio;\n } else if (value) {\n let anio = a.relatienummer.length - a.relatienummer.indexOf(value) + a.relatienummer.replace(/^0+/, \"\").indexOf(value);\n let bnio = b.relatienummer.length - b.relatienummer.indexOf(value) + b.relatienummer.replace(/^0+/, \"\").indexOf(value);\n return anio - bnio;\n }\n return 0;\n };\n\n this._createElements();\n\n this._bindEvents();\n\n this.list = [];\n\n registerTriggers([\n \"searchsuggestions-highlight\",\n \"searchsuggestions-close\",\n \"searchsuggestions-open\",\n \"searchsuggestions-select\",\n \"searchsuggestions-selectcomplete\",\n ]);\n\n if (this.input.value && this._options.autofocus === true)\n window.setTimeout(() => this.input.focus(), 100);\n }\n\n // Create necessary elements\n _createElements() {\n this.container = document.createElement(\"div\");\n this.container.className = \"suggestions\";\n this.input.parentNode.insertBefore(this.container, this.input);\n this.container.appendChild(this.input);\n\n this.innerContainer = document.createElement(\"div\");\n this.innerContainer.className = \"c-search-suggestions__list\";\n this.innerContainer.setAttribute(\"hidden\", \"hidden\");\n this.container.appendChild(this.innerContainer);\n\n this.innerContainer.innerHTML = \"\";\n\n this.ul = document.createElement(\"ul\");\n this.innerContainer.appendChild(this.ul);\n\n this.notFound = document.createElement(\"div\");\n this.notFound.className = \"c-search-suggestions__list-404\";\n this.innerContainer.appendChild(this.notFound);\n\n this.status = document.createElement(\"span\");\n this.status.className = \"t-visuallyhidden\";\n this.status.setAttribute(\"role\", \"status\");\n this.status.setAttribute(\"aria-live\", \"assertive\");\n this.status.setAttribute(\"aria-atomic\", \"true\");\n this.status.setAttribute(\"aria-relevant\", \"additions\");\n this.container.appendChild(this.status);\n }\n\n // Bind events\n _bindEvents() {\n if (this.input) {\n [\"click\", \"touchend\", \"focus\"].forEach((event) => {\n this.input.addEventListener(event, () => {\n if (this.timeoutID && typeof this.timeoutID === \"number\") {\n window.clearTimeout(this.timeoutID);\n }\n this.timeoutID = window.setTimeout(() => {\n if (this.inputValueBackup && this.input.value && this.input.value === this.inputValueBackup &&\n ((this.notFoundBackup && this.notFoundBackup.length > 0) || (this.ulBackup && this.ulBackup.length > 0))\n ) {\n this.ul.innerHTML = this.ulBackup;\n this.notFound.innerHTML = this.notFoundBackup;\n this.open();\n } else if (!this.input.value || this.input.value.length < this._options.minChars) {\n this.close({ reason: \"clear\" });\n } else if (this.inputValueBackup && this.input.value && this.input.value.toLowerCase().startsWith(this.inputValueBackup.toLowerCase())) {\n this._element.classList.add(\"loading\");\n this.showSuggestions(this.input.value, true);\n } else {\n this._element.classList.add(\"loading\");\n this.evaluate();\n }\n }, 200);\n });\n });\n // Act on keypress and paste action for the following keys:\n // < > ' \" $ { } [ ] / keys\n const forbiddenChars = /[<>{}[\\]$\"'/]/g;\n this.input.addEventListener(\"input\", () => {\n this.input.value = this.input.value.replace(forbiddenChars, \"\");\n if (this.inputValueBackup && this.input.value && this.input.value.toLowerCase().startsWith(this.inputValueBackup.toLowerCase())) {\n return this.showSuggestions(this.input.value, true);\n }\n return this.wrapEvaluation();\n });\n this.input.addEventListener(\"blur\", () => this.close({ reason: \"blur\" }));\n this.input.addEventListener(\"keydown\", (evt) => {\n const c = evt.keyCode;\n\n // If the dropdown `ul` is in view, then act on keydown for the following keys:\n // Enter / Esc / Up / Down\n if (this.opened) {\n if (c === 13) {\n // Enter\n if (this.selected) {\n evt.preventDefault();\n this.select();\n } else {\n if (this.submitButton) {\n this.submitButton.click();\n } else {\n this.close({\n reason: \"non-select\",\n });\n triggerNotify(\"searchsuggestions-selectcomplete\");\n }\n }\n } else if (c === 27) {\n // Esc\n this.close({\n reason: \"esc\",\n });\n } else if (c === 38 || c === 40) {\n // Down/Up arrow\n evt.preventDefault();\n let count = this.ul.children.length;\n if (count <= 0) {\n let linkToSearch = this.notFound.querySelector(\".c-link\");\n if (linkToSearch) {\n let toggle =\n linkToSearch.getAttribute(\"aria-selected\") &&\n linkToSearch.getAttribute(\"aria-selected\") === \"true\";\n linkToSearch.setAttribute(\"aria-selected\", !toggle);\n }\n } else {\n this[c === 38 ? \"previous\" : \"next\"](count);\n }\n }\n } else {\n if (c === 13) {\n // Enter\n if (this.submitButton) {\n this.submitButton.click();\n } else {\n triggerNotify(\"searchsuggestions-selectcomplete\");\n }\n }\n }\n });\n }\n\n if (this.submitButton) {\n this.submitButton.addEventListener(\"click\", (evt) => {\n evt.preventDefault();\n this._element.classList.add(\"loading\");\n this.evaluate(true);\n });\n }\n\n if (this.input && this.input.form) {\n this.input.form.addEventListener(\"submit\", () =>\n this.close({ reason: \"submit\" })\n );\n }\n\n if (this.ul) {\n this.ul.addEventListener(\"mousedown\", (evt) => {\n let li = evt.target;\n\n if (li !== this) {\n while (li && !/li/i.test(li.nodeName)) {\n li = li.parentNode;\n }\n\n if (li && evt.button === 0) {\n // Only select on left click\n evt.preventDefault();\n this.select(li, evt.target);\n }\n }\n });\n }\n }\n\n set list(list) {\n if (typeof list === \"string\" && list.indexOf(\",\") > -1) {\n this._list = list.split(/\\s*,\\s*/);\n } else {\n // Element or CSS selector\n this._list = list;\n }\n\n if (document.activeElement === this.input) {\n this.wrapEvaluation();\n }\n }\n\n get list() {\n return this._list;\n }\n\n get selected() {\n return this.index > -1;\n }\n\n get opened() {\n return !this.innerContainer.hasAttribute(\"hidden\");\n }\n\n close(o) {\n if (!this.opened) {\n return;\n }\n const ms = o && o.reason && o.reason === \"clear\" ? 10 : 200;\n window.setTimeout(() => {\n this.innerContainer.setAttribute(\"hidden\", \"\");\n this.notFound.innerHTML = \"\";\n this.ul.innerHTML = \"\";\n }, ms);\n this.index = -1;\n\n triggerNotify(\"searchsuggestions-close\", o || {});\n }\n\n open() {\n this.innerContainer.removeAttribute(\"hidden\");\n\n if (this._options.autoFirst && this.index === -1) {\n this.goto(0);\n }\n\n triggerNotify(\"searchsuggestions-open\");\n }\n\n next(count) {\n this.goto(this.index < count - 1 ? this.index + 1 : -1);\n }\n\n previous(count) {\n this.goto(this.selected ? this.index - 1 : count - 1);\n }\n\n // Should not be used, highlights specific item without any checks!\n goto(i) {\n const lis = this.ul.children;\n\n if (this.selected) {\n lis[this.index].setAttribute(\"aria-selected\", \"false\");\n }\n\n this.index = i;\n\n if (i > -1 && lis.length > 0) {\n lis[i].setAttribute(\"aria-selected\", \"true\");\n this.status.textContent = lis[i].textContent;\n\n triggerNotify(\n \"searchsuggestions-highlight\",\n this.suggestions[this.index]\n );\n }\n }\n\n select(selected, origin) {\n if (selected) {\n this.index = siblingIndex(selected);\n } else {\n selected = this.ul.children[this.index];\n }\n\n if (selected) {\n const suggestion = this.suggestions[this.index];\n this.input.value = suggestion.relatienummer;\n this.inputValueBackup = this.input.value;\n this.close({\n reason: \"select\",\n });\n triggerNotify(\"searchsuggestions-selectcomplete\", suggestion);\n }\n }\n\n wrapEvaluation() {\n if (this.timeoutID && typeof this.timeoutID === \"number\") {\n window.clearTimeout(this.timeoutID);\n }\n this.timeoutID = window.setTimeout(() => {\n this._element.classList.add(\"loading\");\n this.evaluate();\n }, 400);\n }\n\n noSuggestionsFound(value) {\n if (this.notFoundTemplate && this.notFoundTemplate.innerHTML && this.notFoundTemplate.innerHTML.length > 0) {\n this.notFound.innerHTML = this.notFoundTemplate.innerHTML.replace(/\\{0\\}/g, value);\n return true;\n }\n return false;\n }\n\n moreMaxSuggestionsFound(value) {\n if (this.overMaxFoundTemplate && this.overMaxFoundTemplate.innerHTML && this.overMaxFoundTemplate.innerHTML.length > 0) {\n this.notFound.innerHTML = this.overMaxFoundTemplate.innerHTML.replace(/\\{0\\}/g, this._options.maxItems).replace(/\\{1\\}/g, value);\n return true;\n }\n return false;\n }\n\n async evaluate(skipLengthCheck) {\n const value = this.input.value;\n const controller = window.AbortController ? new AbortController() : {};\n const signal = controller.signal || {};\n \n let fetchPromise;\n if ((skipLengthCheck && value.length > 1) || value.length >= this._options.minChars) {\n if (this._options.autosuggestUrl) {\n this.inputValueBackup = \"\";\n this.notFound.innerHTML = \"\";\n this.ul.innerHTML = \"\";\n if (fetchPromise && controller.abort) {\n controller.abort();\n }\n let suggestURL = \"\";\n let searchData = {};\n let key = this._options.key ? this._options.key : \"key\";\n if (this._options.method === \"POST\") {\n suggestURL = this._options.autosuggestUrl;\n\n // Create data object\n searchData = {\n maxResults: this._options.maxResults,\n };\n // Add key value pair to data object\n searchData[key] = value;\n } else {\n suggestURL = `${this._options.autosuggestUrl}&${this._options.autosuggestKey}=${value}`;\n }\n try {\n fetchPromise = fetch(suggestURL, {\n signal,\n method: this._options.method || \"GET\",\n headers: {\n \"Content-Type\": \"application/json; charset=utf-8\",\n },\n body: this._options.method === \"POST\" ? JSON.stringify(searchData) : undefined,\n });\n let response = await fetchPromise;\n let result = await response.json();\n\n if (result && result.isSucces && result.data) {\n this._list = result.data.collectiviteiten;\n this.showSuggestions(value);\n } else {\n this._element.classList.remove(\"loading\");\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: \"nomatches\",\n });\n }\n }\n } catch (error) {\n this._element.classList.remove(\"loading\");\n console.error(error);\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: \"error\",\n });\n }\n } finally {\n fetchPromise = undefined;\n if (this.input.value && this.input.value.length >= 2) {\n this.inputValueBackup = `${this.input.value}`;\n this.notFoundBackup = `${this.notFound.innerHTML}`;\n this.ulBackup = `${this.ul.innerHTML}`;\n }\n }\n } else {\n this._element.classList.remove(\"loading\");\n this.close({\n reason: \"no autosuggest url\",\n });\n }\n } else {\n this._element.classList.remove(\"loading\");\n this.close({\n reason: \"to little characters\",\n });\n }\n }\n\n showSuggestions(value, filter) {\n if (this._list.length > 0) {\n this.index = -1;\n // Populate list with options that match\n const collSuggestions = this._list\n .map((item) => new collectiviteit(item))\n .filter((item) => {\n return this.filter(isNaN(value) ? item.normalizedName : item.relatienummer, value.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\"), filter);\n })\n .sort((a, b) => this._options.sort ? a.normalizedName < b.normalizedName ? -1 : a.normalizedName > b.normalizedName ? 1 : 0 : 0)\n .sort((a, b) => {\n return this._options.sort ? this.sort(a, b, value.trim()) : 0;\n });\n this.suggestions = collSuggestions.slice(0, this._options.maxItems);\n\n let html = this.suggestions.reduce((sentence, suggestion) => `${sentence}${item(`${markText(suggestion.naam, value)}${this._options.subtitleprefix} ${markText(suggestion.relatienummer, value)}`)}`, \"\");\n\n this.ul.innerHTML = html;\n\n if (this.ul.children.length === 0) {\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: \"nomatches\",\n });\n }\n } else if (collSuggestions.length > this._options.maxItems) {\n this.moreMaxSuggestionsFound(value);\n this.open();\n } else {\n this.notFound.innerHTML = '';\n this.open();\n }\n } else {\n if (this.noSuggestionsFound(value)) {\n this.open();\n } else {\n this.close({\n reason: \"nomatches\",\n });\n }\n }\n this._element.classList.remove(\"loading\");\n }\n}\n\n// Private\nfunction collectiviteit(data) {\n const o = { ...data };\n\n o.length = o.naam?.length ?? 0;\n\n o.normalizedName = o.length > 0 ? `${o.naam.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\")}` : \"\";\n\n o.toString = () => `${o.naam}`;\n\n return o;\n}\n\n// Helpers\nfunction markText(text, input) {\n return !input || input === \"\" ? text : text.replace(new RegExp(regExpEscape(input.trim()), \"gi\"), \"$&\");\n}\n\nfunction item(html) {\n return `
${html}
`;\n}\n\nfunction getQueryString(name, raw = false) {\n if (!name || typeof name !== \"string\") {\n return \"\";\n }\n let params =\n location.search &&\n location.search.length > 0 &&\n location.search.indexOf(name) > -1\n ? location.search.substring(1).split(\"&\")\n : location.hash &&\n location.hash.length > 0 &&\n location.hash.indexOf(name) > -1\n ? location.hash.substring(1).split(\"&\")\n : [];\n\n for (let i = 0; i < params.length; i++) {\n params[i] = params[i].replace(/\\+/g, \" \");\n }\n\n for (let param of params) {\n const p = param.split(\"=\");\n if (p[0]?.toLowerCase() === name.toLowerCase())\n return raw ? p[1] : decodeURIComponent(p[1]);\n }\n return \"\";\n}\n\nfunction regExpEscape(s) {\n return s.replace(/[-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\");\n}\n\nfunction siblingIndex(el) {\n /* eslint-disable no-cond-assign */\n let i = 0;\n while (el.previousElementSibling) {\n el = el.previousElementSibling;\n i++;\n }\n return i;\n}\n\nexport default SearchSuggestions; // as Searchsuggestions\n","import { addEventToDatalayer } from '../../@helpers/js/datalayer.js';\nimport { wait } from '../../@helpers/js/wait.js';\n\nclass CompareInsuranceTable {\n\n\tconstructor(element, {\n\t\ttoggleclass = 'c-toggle-detail-on',\n\t\thighlightclass = 'c-table-row-highlight',\n\t\tsearchPlaceholder = 'Begin hier met typen',\n\t\tsearchText = 'Geen passend resultaat gevonden',\n\t} = {}) {\n\n\t\tthis._element = element;\n\t\tthis._options = {\n\t\t\ttoggleclass,\n\t\t\thighlightclass,\n\t\t\tsearchPlaceholder,\n\t\t\tsearchText\n\t\t};\n\n\t\tthis.init();\n\t}\n\n\tinit() {\n\t\tthis._tableBody = this._element.querySelector('table tbody');\n\t\tthis._revealerColl = this._element.querySelector('.c-revealer-collection');\n\t\tthis._selectBox = this._element.querySelector('.c-insurance-compare__select .c-insurance-compare__combobox__list');\n\t\tthis._selectOptions = this._selectBox ? [...this._selectBox.querySelectorAll('li[role=option]')] : [];\n\t\tthis._noneleft = this._element.querySelector('[data-insurance-compare-none]');\n\t\tthis._tablerows = this._tableBody ? [...this._tableBody.querySelectorAll('tbody tr')].map((row) => {\n\t\t\treturn {\n\t\t\t\trow,\n\t\t\t\tname: row.dataset?.tablerow,\n\t\t\t\ttoggleBtn: row.querySelector('th button[data-module=ToggleButton]'),\n\t\t\t\trem: row.querySelector('button[data-insurance-compare-hider]')\n\t\t\t};\n\t\t}) : [];\n\t\tthis._revealerrows = this._revealerColl ? [...this._revealerColl.querySelectorAll('[data-revealerrow]')].map((row) => {\n\t\t\treturn {\n\t\t\t\trow,\n\t\t\t\tname: row.dataset?.revealerrow,\n\t\t\t\ttoggleBtn: row.querySelector('button[data-module=ToggleButton]'),\n\t\t\t\trem: row.nextElementSibling,\n\t\t\t\trev: row.querySelector('[data-revealer-title]'),\n\t\t\t};\n\t\t}) : [];\n\t\t\n\t\tif (this._tablerows?.length > 0 && this._revealerrows?.length > 0) {\n\t\t\tthis._comboBox = this._element.querySelector('input[role=\"combobox\"]');\n\t\t\tthis._selectConfirm = this._element.querySelector('button[data-confirm-selection]');\n\n\t\t\t// add click listener\n\t\t\tif (this._selectConfirm) {\n\t\t\t\tthis._selectConfirm.addEventListener('click', () => {\n\t\t\t\t\t// get selected value from slimselect\n\t\t\t\t\tlet selected = this._selectOptions.length >= 1 && this._comboBox?.value ? this._selectOptions?.find(o => o.innerText === this._comboBox.value) : '';\n\t\t\t\t\tif (selected) {\n\t\t\t\t\t\tif (selected.innerText) {\n\t\t\t\t\t\t\tlet options;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toptions = JSON.parse(this._selectConfirm.dataset.confirmDatalayerClick);\n\t\t\t\t\t\t\t\toptions.event = 'event';\n\t\t\t\t\t\t\t\toptions.label = selected.innerText;\n\t\t\t\t\t\t\t\tsetTimeout( () => addEventToDatalayer(options), 100);\n\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\tconsole.error(error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t// get correct row by value\n\t\t\t\t\t\tconst trow = this._tablerows.find((r) => r.name === selected.id)\n\t\t\t\t\t\t// get correct revealerrow by value\n\t\t\t\t\t\tconst rrow = this._revealerrows.find((r) => r.name === selected.id)\n\t\t\t\t\t\tif (trow && rrow) {\n\t\t\t\t\t\t\t// move row to bottom and remove t-hidden class\n\t\t\t\t\t\t\tthis._tableBody.appendChild(trow.row);\n\t\t\t\t\t\t\ttrow.row.classList.remove('t-hidden');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// move revealerrow to bottom and remove t-hidden class\n\t\t\t\t\t\t\tthis._revealerColl.appendChild(rrow.row);\n\t\t\t\t\t\t\tthis._revealerColl.appendChild(rrow.rem);\n\t\t\t\t\t\t\trrow.row.classList.remove('t-hidden');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// remove option from TimoSelect\n\t\t\t\t\t\t\tselected.className = 't-hidden';\n\t\t\t\t\t\t\tselected.setAttribute('disabled',true);\n\t\t\t\t\t\t\tthis._comboBox.value = '';\n\t\t\t\t\t\t\tthis._noneleft.classList.add('t-hidden');\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t// remove highlightclass\n\t\t\t\t\t\t\twait(150).then(() => {\n\t\t\t\t\t\t\t\ttrow.row.classList.remove(this._options.highlightclass);\n\t\t\t\t\t\t\t\trrow.row.classList.remove(this._options.highlightclass);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\twait(1000).then(() => {\n\t\t\t\t\t\t\t\trrow.row.classList.remove('t-background-color-transition');\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// listen to remove button clicks\n\t\t\tthis._tablerows.forEach((trow) => {\n\t\t\t\t\n\t\t\t\t// setup interaction on remove button click\n\t\t\t\tif (trow.rem) {\n\t\t\t\t\ttrow.rem.addEventListener('click', () => {\n\t\t\t\t\t\ttrow.row.classList.add(this._options.highlightclass);\n\t\t\t\t\t\twait(200).then(() => {\n\t\t\t\t\t\t\tthis.removeRow(trow);\n\t\t\t\t\t\t\tthis.addToSelector(trow.name);\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// also hide the mobile version\n\t\t\t\t\t\tconst rrow = this._revealerrows.find((r) => r.name === trow.name)\n\t\t\t\t\t\tthis.removeRow(rrow);\n\t\t\t\t\t\t\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\t// listen to remove button clicks\n\t\t\tthis._revealerrows.forEach((rrow) => {\n\n\t\t\t\t// setup interaction on remove button click\n\t\t\t\tif (rrow.rem && rrow.rem.classList?.contains('c-insurance-compare__removal__wrapper')) {\n\t\t\t\t\trrow.rem?.firstElementChild.addEventListener('click', () => {\n\t\t\t\t\t\trrow.row.classList.add('t-background-color-transition');\n\t\t\t\t\t\trrow.row.classList.add(this._options.highlightclass);\n\t\t\t\t\t\twait(200).then(() => {\n\t\t\t\t\t\t\tthis.removeRow(rrow);\n\t\t\t\t\t\t\tthis.addToSelector(rrow.name);\n\t\t\t\t\t\t});\n\t\t\t\t\t\t// also hide the desktop version\n\t\t\t\t\t\tconst trow = this._tablerows.find((r) => r.name === rrow.name)\n\t\t\t\t\t\tthis.removeRow(trow);\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t}\n\t}\n\t\n\taddToSelector(selected) {\n\t\tconst chosenOption = this._selectOptions?.find(o => o.id === selected);\n\t\tchosenOption.className = '';\n\t\tchosenOption.removeAttribute('disabled');\n\t\tlet options = this._selectOptions;\n\t\tif (options?.some(o => !o.hasAttribute('disabled'))) {\n\t\t\tthis._comboBox.disabled = false;\n\t\t\tthis._selectConfirm.disabled = false;\n\t\t}\n\t\tif (options?.every(o => !o.hasAttribute('disabled'))) {\n\t\t\tthis._noneleft.classList.remove('t-hidden');\n\t\t}\n\t}\n\n\t// hide the row on the revealer on remove\n\tremoveRow(r) {\n\t\tif (!r || !r.row) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// close detail toggle\n\t\tif (r.toggleBtn && r.toggleBtn.getAttribute('aria-checked') == 'true') {\n\t\t\tr.toggleBtn.click();\n\t\t}\n\t\t// also close revealer if open\n\t\tif (r.rev && r.rev.getAttribute('aria-expanded') == 'true') {\n\t\t\tr.rev.click();\n\t\t}\n\t\t\n\t\tr.row.classList.add('t-hidden');\n\t\tr.row.classList.add(this._options.highlightclass);\n\t\tif (r.rev) {\n\t\t\tr.row.classList.add('t-background-color-transition');\n\t\t}\n\t}\n}\n\nexport default CompareInsuranceTable;","import { css } from 'lit';\nimport { CzContentloader } from '@cz/webcomponents';\n\nexport default class CzAvtableloader extends CzContentloader {\n\n\tstatic styles = [\n\t\tCzContentloader.styles,\n\t\tcss`\n\t\t\t@layer component {\n\t\t\t\t:host(:empty) {\n\t\t\t\t\taspect-ratio: 1/.325;\n\t\t\t\t}\n\t\t\t}\n\t\t`\n\t];\n\n\tstatic properties = {\n\t\tbrand: {},\n\t\tyear: {},\n\t\tlanguage: {},\n\t\tcategory: {},\n\t\tcollectivity: {}\n\t};\n\n\t#meldingOphalenGegevens = 'Geen gegevens gevonden';\n\t#meldingAVNietGevonden = 'Geen aanvullende verzekering gevonden';\n\t#avTitle = 'Aanvullende verzekering';\n\t#tvTitle = 'Tandarts verzekering';\n\t#vergoedingTitle = 'Vergoeding';\n\n\tupdated(changedProperties) {\n\t\tif (changedProperties?.has('brand') ||\n\t\t\tchangedProperties?.has('year') ||\n\t\t\tchangedProperties?.has('language') ||\n\t\t\tchangedProperties?.has('category') ||\n\t\t\tchangedProperties?.has('collectivity')) {\n\t\t\tthis.innerHTML = '';\n\t\t\tthis.loadContent();\n\t\t}\n\t}\n\n\tcallBackend = async (url) => {\n\t\ttry {\n\t\t\tconst requestUrl = `${url}?site=${this.brand?.toLowerCase()}&language=${this.language}&year=${this.year?.toLowerCase()}&categoryId=${this.category?.toLowerCase()}&collectivity=${this.collectivity?.toLowerCase()}`;\n\t\t\tconst controller = window.AbortController ? new AbortController() : {};\n\t\t\tconst signal = controller.signal || {};\n\t\t\tconst fetchPromise = fetch(requestUrl, {\n\t\t\t\tsignal,\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders: {\n\t\t\t\t \"Content-Type\": \"application/json; charset=utf-8\",\n\t\t\t\t},\n\t\t\t\tcredentials: \"same-origin\",\n\t\t\t });\n\t\t\tconst response = await fetchPromise;\n\t\t\tif (!response.ok) {\n\t\t\t\treturn this.#errorNotification(this.#meldingAVNietGevonden);\n\t\t\t}\n\t\t\tlet result = await response.json();\n\t\t\treturn this.#bakeHtmlFromJsonResult(result);\n\t\t} catch (error) {\n\t\t\treturn this.#errorNotification(this.#meldingOphalenGegevens);\n\t\t}\n\t}\n\n\t#errorNotification(message) {\n\t\treturn `
\n\t\t\t\t\t${message}\n\t\t\t\t
`;\n\t}\n\n\t#bakeHtmlFromJsonResult(result) {\n let returnValue = '';\n if (result) {\n if (result.aanvullend && result.aanvullend.length > 0) {\n returnValue += this.#bakeTable(result.aanvullend, `