{"version":3,"file":"components-roi-calculator.js","mappings":"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","sources":["webpack://silverstripe-base/./themes/app/src/components/roi-calculator.js","webpack://silverstripe-base/./themes/app/src/scripts/common/scroll-to.js","webpack://silverstripe-base/./node_modules/slide-element/dist/index.es.js","webpack://silverstripe-base/./themes/app/src/scripts/common/slide.js","webpack://silverstripe-base/./node_modules/jump.js/dist/jump.module.js","webpack://silverstripe-base/./node_modules/imask/esm/masked/number.js"],"sourcesContent":["import { slideDown } from \"@common/slide\";\nimport { scrollToIfNeeded } from \"@common/scroll-to\";\nimport IMask from \"imask/esm/imask\";\nimport \"imask/esm/masked/number\";\nimport \"imask/esm/masked/pattern\";\n\nconst form = document.querySelector(\".roi-form\");\nconst results = document.querySelector(\".roi-results\");\nconst calculatorData = JSON.parse(form.dataset.json);\n\nconst headline = document.querySelector(\".roi-headline\");\nconst totalBaseInput = form.querySelector('input[name=\"total_base\"]');\nconst percentMissPaymentRange = form.querySelector('input[name=\"percent_miss_payment_range\"]');\nconst percentMissPaymentInput = form.querySelector('input[name=\"percent_miss_payment\"]');\nconst latePaymentDaysRange = form.querySelector('input[name=\"late_payment_days_range\"]');\nconst latePaymentDaysInput = form.querySelector('input[name=\"late_payment_days\"]');\nconst percentMonthlyChurnRange = form.querySelector('input[name=\"percent_monthly_churn_range\"]');\nconst percentMonthlyChurnInput = form.querySelector('input[name=\"percent_monthly_churn\"]');\nconst amountOwedInput = form.querySelector('input[name=\"amount_owed\"]');\n\nIMask(totalBaseInput, {\n mask: Number,\n scale: 0,\n signed: false,\n thousandsSeparator: \",\",\n max: Number.MAX_SAFE_INTEGER,\n});\n\nconst rangeInputFields = [\n {\n input: percentMissPaymentInput,\n range: percentMissPaymentRange,\n },\n {\n input: latePaymentDaysInput,\n range: latePaymentDaysRange,\n },\n {\n input: percentMonthlyChurnInput,\n range: percentMonthlyChurnRange,\n },\n];\n\nrangeInputFields.forEach((fields) => {\n const mask = IMask(fields.input, {\n mask: Number,\n scale: 0,\n min: parseInt(fields.range.getAttribute(\"min\")),\n max: parseInt(fields.range.getAttribute(\"max\")),\n });\n\n fields.range.addEventListener(\"input\", () => {\n fields.input.value = fields.range.value;\n mask.updateValue();\n fields.input.classList.remove(\"has-error\");\n });\n\n mask.on(\"complete\", () => {\n const value = mask.value || 0;\n fields.range.value = value;\n });\n});\n\nIMask(amountOwedInput, {\n mask: Number,\n scale: 2,\n signed: false,\n thousandsSeparator: \",\",\n padFractionalZeros: true,\n radix: \".\",\n mapToRadix: [\".\"],\n normalizeZeros: true,\n min: 0,\n max: Number.MAX_SAFE_INTEGER,\n prepare: function (str) {\n return str.replace(/[^0-9.]/g, \"\");\n },\n overwrite: true,\n});\n\nconst wait = async (duration = 500) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve();\n }, duration);\n });\n};\n\nconst normalizeNumber = (input) => {\n return parseFloat(input.replaceAll(\",\", \"\"));\n};\n\nconst toCurrency = (number) => {\n const formatter = new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n });\n\n return formatter.format(number);\n};\n\nform.addEventListener(\"submit\", async (e) => {\n e.preventDefault();\n\n let isValid = true;\n\n form.querySelectorAll(\"input[required]\").forEach((field) => {\n if (!field.checkValidity()) {\n field.classList.add(\"has-error\");\n isValid = false;\n\n field.addEventListener(\"input\", () => field.classList.remove(\"has-error\"), { once: true });\n } else {\n field.classList.remove(\"has-error\");\n }\n });\n\n if (!isValid) {\n scrollToIfNeeded(form, 32);\n\n return;\n }\n\n const submitBtn = form.querySelector('[type=\"submit\"]');\n\n const data = new FormData(form);\n\n const totalBase = normalizeNumber(data.get(\"total_base\"));\n const percentMonthlyChurn = normalizeNumber(data.get(\"percent_monthly_churn\"));\n const amountOwed = normalizeNumber(data.get(\"amount_owed\"));\n const reduceBadDebtLowPercentage = parseFloat(calculatorData.reduce_bad_debt_low_percentage) / 100;\n const reduceBadDebtHighPercentage = parseFloat(calculatorData.reduce_bad_debt_high_percentage) / 100;\n\n const totalMonthlyChurn = totalBase * (percentMonthlyChurn / 100);\n const annualBadDebtExposure = amountOwed * totalMonthlyChurn * 12;\n const lowAnnualRevenueReturn =\n totalMonthlyChurn * amountOwed * (1 / (percentMonthlyChurn / 100)) * reduceBadDebtLowPercentage * 12;\n const highAnnualRevenueReturn =\n totalMonthlyChurn * amountOwed * (1 / (percentMonthlyChurn / 100)) * reduceBadDebtHighPercentage * 12;\n\n form.querySelector(\".annual-bad-debt-amount\").textContent = toCurrency(annualBadDebtExposure);\n form.querySelector(\".low-annual-revenue-amount\").textContent = toCurrency(lowAnnualRevenueReturn);\n form.querySelector(\".high-annual-revenue-amount\").textContent = toCurrency(highAnnualRevenueReturn);\n\n submitBtn.disabled = true;\n submitBtn.classList.add(\"is-loading\");\n\n await wait();\n\n if (!form.classList.contains(\"has-results\")) {\n await slideDown(results);\n }\n\n scrollToIfNeeded(results, 32);\n\n headline.textContent = headline.dataset.resultsLabel;\n form.classList.add(\"has-results\");\n submitBtn.disabled = false;\n submitBtn.classList.remove(\"is-loading\");\n submitBtn.querySelector(\"span\").textContent = \"Update Calculation\";\n\n if (window.dataLayer) {\n window.dataLayer.push({\n event: \"form_submit\",\n form_type: \"ROI Calculator Form\",\n });\n }\n});\n","import jump from \"jump.js\";\n\nconst getPageOffset = () => {\n let offset = 0;\n\n const siteHeader = document.querySelector(\".site-header\");\n\n if (siteHeader) {\n const siteHeaderHeight = getComputedStyle(document.documentElement).getPropertyValue(\"--site-header-height\");\n\n offset += parseInt(siteHeaderHeight);\n }\n\n return offset;\n};\n\nconst scrollTo = (target, additionalOffset = 0) => {\n const pageOffset = getPageOffset() * -1;\n\n if (target.dataset.scrollOffset) {\n additionalOffset = parseInt(target.dataset.scrollOffset);\n }\n\n let offset = pageOffset - additionalOffset;\n\n return new Promise((resolve) => {\n jump(target, {\n duration: 600,\n offset,\n callback: () => {\n resolve();\n },\n });\n });\n};\n\nexport const scrollToIfNeeded = (target, additionalOffset = 0) => {\n const rect = target.getBoundingClientRect();\n const viewportHeight = window.innerHeight || document.documentElement.clientHeight;\n const isInViewport = rect.top >= 0 && rect.bottom <= viewportHeight;\n const is50PercentFromTop = rect.top <= viewportHeight / 2;\n\n if (!isInViewport || !is50PercentFromTop) {\n return scrollTo(target, additionalOffset);\n }\n};\n\nexport default scrollTo;\n","const afterNextRepaint = (callback) => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n callback(resolve);\n });\n });\n });\n};\nlet defaultOptions = {\n easing: \"ease\",\n duration: 250,\n fill: \"backwards\",\n display: \"block\",\n overflow: \"hidden\"\n};\nlet nonAnimatableOptions = [\"overflow\", \"display\"];\nlet SlideController = (element, options) => {\n let mergedOptions = Object.assign({}, defaultOptions, options);\n let openDisplayValue = mergedOptions.display;\n let closedDisplayValue = \"none\";\n let setDisplay = (value) => element.style.display = value;\n let getHeight = () => element.clientHeight + \"px\";\n let getComputed = () => window.getComputedStyle(element);\n let setOverflow = (set) => element.style.overflow = set ? mergedOptions.overflow : \"\";\n let getAnimations = () => element.getAnimations();\n let createAnimation = (willOpen, lowerBound) => {\n var _a;\n nonAnimatableOptions.forEach((property) => delete mergedOptions[property]);\n let currentHeight = getHeight();\n let frames = [currentHeight, lowerBound].map((height) => ({\n height,\n paddingTop: \"0px\",\n paddingBottom: \"0px\"\n }));\n let { paddingTop, paddingBottom } = getComputed();\n frames[0].paddingTop = paddingTop;\n frames[0].paddingBottom = paddingBottom;\n if (willOpen) {\n frames[0].height = currentHeight;\n frames.reverse();\n }\n if ((_a = window.matchMedia(\"(prefers-reduced-motion: reduce)\")) == null ? void 0 : _a.matches) {\n mergedOptions.duration = 0;\n }\n let animation = element.animate(frames, mergedOptions);\n animation.id = (+willOpen).toString();\n return animation;\n };\n let triggerAnimation = async (willOpen) => {\n let finishedAnimations = getAnimations().map((a) => a.finish());\n await afterNextRepaint(async (resolve) => {\n let currentHeight = willOpen ? getHeight() : \"0px\";\n if (willOpen)\n setDisplay(openDisplayValue);\n setOverflow(true);\n await createAnimation(willOpen, currentHeight).finished;\n setOverflow(false);\n if (!willOpen)\n setDisplay(closedDisplayValue);\n resolve();\n });\n return finishedAnimations.length ? null : willOpen;\n };\n let up2 = async () => triggerAnimation(false);\n let down2 = async () => triggerAnimation(true);\n let toggle2 = async () => {\n var _a;\n let existingAnimationId = (_a = getAnimations()[0]) == null ? void 0 : _a.id;\n let condition = existingAnimationId ? existingAnimationId === \"1\" : element.offsetHeight;\n return (condition ? up2 : down2)();\n };\n return {\n up: up2,\n down: down2,\n toggle: toggle2\n };\n};\nlet down = (element, options = {}) => SlideController(element, options).down();\nlet up = (element, options = {}) => SlideController(element, options).up();\nlet toggle = (element, options = {}) => SlideController(element, options).toggle();\nexport {\n down,\n toggle,\n up\n};\n","import { up, down, toggle } from \"slide-element\";\n\nexport const slideUp = (element, duration = 400, display = \"block\", easing = \"ease-out\") => {\n element.classList.add(\"is-sliding\");\n\n const slide = up(element, {\n duration,\n display,\n easing,\n });\n\n slide.then(() => {\n element.classList.remove(\"is-sliding\");\n });\n\n return slide;\n};\n\nexport const slideDown = (element, duration = 400, display = \"block\", easing = \"ease-out\") => {\n element.classList.add(\"is-sliding\");\n\n const slide = down(element, {\n duration,\n display,\n easing,\n });\n\n slide.then(() => {\n element.classList.remove(\"is-sliding\");\n });\n\n return slide;\n};\n\nexport const slideToggle = (element, duration = 400, display = \"block\", easing = \"ease-out\") => {\n element.classList.add(\"is-sliding\");\n\n const slide = toggle(element, {\n duration,\n display,\n easing,\n });\n\n slide.then(() => {\n element.classList.remove(\"is-sliding\");\n });\n\n return slide;\n};\n","// Robert Penner's easeInOutQuad\n\n// find the rest of his easing functions here: http://robertpenner.com/easing/\n// find them exported for ES6 consumption here: https://github.com/jaxgeller/ez.js\n\nvar easeInOutQuad = function easeInOutQuad(t, b, c, d) {\n t /= d / 2;\n if (t < 1) return c / 2 * t * t + b;\n t--;\n return -c / 2 * (t * (t - 2) - 1) + b;\n};\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n return typeof obj;\n} : function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n};\n\nvar jumper = function jumper() {\n // private variable cache\n // no variables are created during a jump, preventing memory leaks\n\n var element = void 0; // element to scroll to (node)\n\n var start = void 0; // where scroll starts (px)\n var stop = void 0; // where scroll stops (px)\n\n var offset = void 0; // adjustment from the stop position (px)\n var easing = void 0; // easing function (function)\n var a11y = void 0; // accessibility support flag (boolean)\n\n var distance = void 0; // distance of scroll (px)\n var duration = void 0; // scroll duration (ms)\n\n var timeStart = void 0; // time scroll started (ms)\n var timeElapsed = void 0; // time spent scrolling thus far (ms)\n\n var next = void 0; // next scroll position (px)\n\n var callback = void 0; // to call when done scrolling (function)\n\n // scroll position helper\n\n function location() {\n return window.scrollY || window.pageYOffset;\n }\n\n // element offset helper\n\n function top(element) {\n return element.getBoundingClientRect().top + start;\n }\n\n // rAF loop helper\n\n function loop(timeCurrent) {\n // store time scroll started, if not started already\n if (!timeStart) {\n timeStart = timeCurrent;\n }\n\n // determine time spent scrolling so far\n timeElapsed = timeCurrent - timeStart;\n\n // calculate next scroll position\n next = easing(timeElapsed, start, distance, duration);\n\n // scroll to it\n window.scrollTo(0, next);\n\n // check progress\n timeElapsed < duration ? window.requestAnimationFrame(loop) // continue scroll loop\n : done(); // scrolling is done\n }\n\n // scroll finished helper\n\n function done() {\n // account for rAF time rounding inaccuracies\n window.scrollTo(0, start + distance);\n\n // if scrolling to an element, and accessibility is enabled\n if (element && a11y) {\n // add tabindex indicating programmatic focus\n element.setAttribute('tabindex', '-1');\n\n // focus the element\n element.focus();\n }\n\n // if it exists, fire the callback\n if (typeof callback === 'function') {\n callback();\n }\n\n // reset time for next jump\n timeStart = false;\n }\n\n // API\n\n function jump(target) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n // resolve options, or use defaults\n duration = options.duration || 1000;\n offset = options.offset || 0;\n callback = options.callback; // \"undefined\" is a suitable default, and won't be called\n easing = options.easing || easeInOutQuad;\n a11y = options.a11y || false;\n\n // cache starting position\n start = location();\n\n // resolve target\n switch (typeof target === 'undefined' ? 'undefined' : _typeof(target)) {\n // scroll from current position\n case 'number':\n element = undefined; // no element to scroll to\n a11y = false; // make sure accessibility is off\n stop = start + target;\n break;\n\n // scroll to element (node)\n // bounding rect is relative to the viewport\n case 'object':\n element = target;\n stop = top(element);\n break;\n\n // scroll to element (selector)\n // bounding rect is relative to the viewport\n case 'string':\n element = document.querySelector(target);\n stop = top(element);\n break;\n }\n\n // resolve scroll distance, accounting for offset\n distance = stop - start + offset;\n\n // resolve duration\n switch (_typeof(options.duration)) {\n // number in ms\n case 'number':\n duration = options.duration;\n break;\n\n // function passed the distance of the scroll\n case 'function':\n duration = options.duration(distance);\n break;\n }\n\n // start the loop\n window.requestAnimationFrame(loop);\n }\n\n // expose only the jump method\n return jump;\n};\n\n// export singleton\n\nvar singleton = jumper();\n\nexport default singleton;\n","import { escapeRegExp, DIRECTION } from '../core/utils.js';\nimport ChangeDetails from '../core/change-details.js';\nimport Masked from './base.js';\nimport IMask from '../core/holder.js';\nimport '../core/continuous-tail-details.js';\n\nvar _MaskedNumber;\n/** Number mask */\nclass MaskedNumber extends Masked {\n /** Single char */\n\n /** Single char */\n\n /** Array of single chars */\n\n /** */\n\n /** */\n\n /** Digits after point */\n\n /** Flag to remove leading and trailing zeros in the end of editing */\n\n /** Flag to pad trailing zeros after point in the end of editing */\n\n /** Enable characters overwriting */\n\n /** */\n\n /** */\n\n /** */\n\n /** Format typed value to string */\n\n /** Parse string to get typed value */\n\n constructor(opts) {\n super({\n ...MaskedNumber.DEFAULTS,\n ...opts\n });\n }\n updateOptions(opts) {\n super.updateOptions(opts);\n }\n _update(opts) {\n super._update(opts);\n this._updateRegExps();\n }\n _updateRegExps() {\n const start = '^' + (this.allowNegative ? '[+|\\\\-]?' : '');\n const mid = '\\\\d*';\n const end = (this.scale ? \"(\" + escapeRegExp(this.radix) + \"\\\\d{0,\" + this.scale + \"})?\" : '') + '$';\n this._numberRegExp = new RegExp(start + mid + end);\n this._mapToRadixRegExp = new RegExp(\"[\" + this.mapToRadix.map(escapeRegExp).join('') + \"]\", 'g');\n this._thousandsSeparatorRegExp = new RegExp(escapeRegExp(this.thousandsSeparator), 'g');\n }\n _removeThousandsSeparators(value) {\n return value.replace(this._thousandsSeparatorRegExp, '');\n }\n _insertThousandsSeparators(value) {\n // https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript\n const parts = value.split(this.radix);\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, this.thousandsSeparator);\n return parts.join(this.radix);\n }\n doPrepareChar(ch, flags) {\n if (flags === void 0) {\n flags = {};\n }\n const [prepCh, details] = super.doPrepareChar(this._removeThousandsSeparators(this.scale && this.mapToRadix.length && (\n /*\n radix should be mapped when\n 1) input is done from keyboard = flags.input && flags.raw\n 2) unmasked value is set = !flags.input && !flags.raw\n and should not be mapped when\n 1) value is set = flags.input && !flags.raw\n 2) raw value is set = !flags.input && flags.raw\n */\n flags.input && flags.raw || !flags.input && !flags.raw) ? ch.replace(this._mapToRadixRegExp, this.radix) : ch), flags);\n if (ch && !prepCh) details.skip = true;\n if (prepCh && !this.allowPositive && !this.value && prepCh !== '-') details.aggregate(this._appendChar('-'));\n return [prepCh, details];\n }\n _separatorsCount(to, extendOnSeparators) {\n if (extendOnSeparators === void 0) {\n extendOnSeparators = false;\n }\n let count = 0;\n for (let pos = 0; pos < to; ++pos) {\n if (this._value.indexOf(this.thousandsSeparator, pos) === pos) {\n ++count;\n if (extendOnSeparators) to += this.thousandsSeparator.length;\n }\n }\n return count;\n }\n _separatorsCountFromSlice(slice) {\n if (slice === void 0) {\n slice = this._value;\n }\n return this._separatorsCount(this._removeThousandsSeparators(slice).length, true);\n }\n extractInput(fromPos, toPos, flags) {\n if (fromPos === void 0) {\n fromPos = 0;\n }\n if (toPos === void 0) {\n toPos = this.displayValue.length;\n }\n [fromPos, toPos] = this._adjustRangeWithSeparators(fromPos, toPos);\n return this._removeThousandsSeparators(super.extractInput(fromPos, toPos, flags));\n }\n _appendCharRaw(ch, flags) {\n if (flags === void 0) {\n flags = {};\n }\n const prevBeforeTailValue = flags.tail && flags._beforeTailState ? flags._beforeTailState._value : this._value;\n const prevBeforeTailSeparatorsCount = this._separatorsCountFromSlice(prevBeforeTailValue);\n this._value = this._removeThousandsSeparators(this.value);\n const oldValue = this._value;\n this._value += ch;\n const num = this.number;\n let accepted = !isNaN(num);\n let skip = false;\n if (accepted) {\n let fixedNum;\n if (this.min != null && this.min < 0 && this.number < this.min) fixedNum = this.min;\n if (this.max != null && this.max > 0 && this.number > this.max) fixedNum = this.max;\n if (fixedNum != null) {\n if (this.autofix) {\n this._value = this.format(fixedNum, this).replace(MaskedNumber.UNMASKED_RADIX, this.radix);\n skip || (skip = oldValue === this._value && !flags.tail); // if not changed on tail it's still ok to proceed\n } else {\n accepted = false;\n }\n }\n accepted && (accepted = Boolean(this._value.match(this._numberRegExp)));\n }\n let appendDetails;\n if (!accepted) {\n this._value = oldValue;\n appendDetails = new ChangeDetails();\n } else {\n appendDetails = new ChangeDetails({\n inserted: this._value.slice(oldValue.length),\n rawInserted: skip ? '' : ch,\n skip\n });\n }\n this._value = this._insertThousandsSeparators(this._value);\n const beforeTailValue = flags.tail && flags._beforeTailState ? flags._beforeTailState._value : this._value;\n const beforeTailSeparatorsCount = this._separatorsCountFromSlice(beforeTailValue);\n appendDetails.tailShift += (beforeTailSeparatorsCount - prevBeforeTailSeparatorsCount) * this.thousandsSeparator.length;\n return appendDetails;\n }\n _findSeparatorAround(pos) {\n if (this.thousandsSeparator) {\n const searchFrom = pos - this.thousandsSeparator.length + 1;\n const separatorPos = this.value.indexOf(this.thousandsSeparator, searchFrom);\n if (separatorPos <= pos) return separatorPos;\n }\n return -1;\n }\n _adjustRangeWithSeparators(from, to) {\n const separatorAroundFromPos = this._findSeparatorAround(from);\n if (separatorAroundFromPos >= 0) from = separatorAroundFromPos;\n const separatorAroundToPos = this._findSeparatorAround(to);\n if (separatorAroundToPos >= 0) to = separatorAroundToPos + this.thousandsSeparator.length;\n return [from, to];\n }\n remove(fromPos, toPos) {\n if (fromPos === void 0) {\n fromPos = 0;\n }\n if (toPos === void 0) {\n toPos = this.displayValue.length;\n }\n [fromPos, toPos] = this._adjustRangeWithSeparators(fromPos, toPos);\n const valueBeforePos = this.value.slice(0, fromPos);\n const valueAfterPos = this.value.slice(toPos);\n const prevBeforeTailSeparatorsCount = this._separatorsCount(valueBeforePos.length);\n this._value = this._insertThousandsSeparators(this._removeThousandsSeparators(valueBeforePos + valueAfterPos));\n const beforeTailSeparatorsCount = this._separatorsCountFromSlice(valueBeforePos);\n return new ChangeDetails({\n tailShift: (beforeTailSeparatorsCount - prevBeforeTailSeparatorsCount) * this.thousandsSeparator.length\n });\n }\n nearestInputPos(cursorPos, direction) {\n if (!this.thousandsSeparator) return cursorPos;\n switch (direction) {\n case DIRECTION.NONE:\n case DIRECTION.LEFT:\n case DIRECTION.FORCE_LEFT:\n {\n const separatorAtLeftPos = this._findSeparatorAround(cursorPos - 1);\n if (separatorAtLeftPos >= 0) {\n const separatorAtLeftEndPos = separatorAtLeftPos + this.thousandsSeparator.length;\n if (cursorPos < separatorAtLeftEndPos || this.value.length <= separatorAtLeftEndPos || direction === DIRECTION.FORCE_LEFT) {\n return separatorAtLeftPos;\n }\n }\n break;\n }\n case DIRECTION.RIGHT:\n case DIRECTION.FORCE_RIGHT:\n {\n const separatorAtRightPos = this._findSeparatorAround(cursorPos);\n if (separatorAtRightPos >= 0) {\n return separatorAtRightPos + this.thousandsSeparator.length;\n }\n }\n }\n return cursorPos;\n }\n doCommit() {\n if (this.value) {\n const number = this.number;\n let validnum = number;\n\n // check bounds\n if (this.min != null) validnum = Math.max(validnum, this.min);\n if (this.max != null) validnum = Math.min(validnum, this.max);\n if (validnum !== number) this.unmaskedValue = this.format(validnum, this);\n let formatted = this.value;\n if (this.normalizeZeros) formatted = this._normalizeZeros(formatted);\n if (this.padFractionalZeros && this.scale > 0) formatted = this._padFractionalZeros(formatted);\n this._value = formatted;\n }\n super.doCommit();\n }\n _normalizeZeros(value) {\n const parts = this._removeThousandsSeparators(value).split(this.radix);\n\n // remove leading zeros\n parts[0] = parts[0].replace(/^(\\D*)(0*)(\\d*)/, (match, sign, zeros, num) => sign + num);\n // add leading zero\n if (value.length && !/\\d$/.test(parts[0])) parts[0] = parts[0] + '0';\n if (parts.length > 1) {\n parts[1] = parts[1].replace(/0*$/, ''); // remove trailing zeros\n if (!parts[1].length) parts.length = 1; // remove fractional\n }\n return this._insertThousandsSeparators(parts.join(this.radix));\n }\n _padFractionalZeros(value) {\n if (!value) return value;\n const parts = value.split(this.radix);\n if (parts.length < 2) parts.push('');\n parts[1] = parts[1].padEnd(this.scale, '0');\n return parts.join(this.radix);\n }\n doSkipInvalid(ch, flags, checkTail) {\n if (flags === void 0) {\n flags = {};\n }\n const dropFractional = this.scale === 0 && ch !== this.thousandsSeparator && (ch === this.radix || ch === MaskedNumber.UNMASKED_RADIX || this.mapToRadix.includes(ch));\n return super.doSkipInvalid(ch, flags, checkTail) && !dropFractional;\n }\n get unmaskedValue() {\n return this._removeThousandsSeparators(this._normalizeZeros(this.value)).replace(this.radix, MaskedNumber.UNMASKED_RADIX);\n }\n set unmaskedValue(unmaskedValue) {\n super.unmaskedValue = unmaskedValue;\n }\n get typedValue() {\n return this.parse(this.unmaskedValue, this);\n }\n set typedValue(n) {\n this.rawInputValue = this.format(n, this).replace(MaskedNumber.UNMASKED_RADIX, this.radix);\n }\n\n /** Parsed Number */\n get number() {\n return this.typedValue;\n }\n set number(number) {\n this.typedValue = number;\n }\n get allowNegative() {\n return this.min != null && this.min < 0 || this.max != null && this.max < 0;\n }\n get allowPositive() {\n return this.min != null && this.min > 0 || this.max != null && this.max > 0;\n }\n typedValueEquals(value) {\n // handle 0 -> '' case (typed = 0 even if value = '')\n // for details see https://github.com/uNmAnNeR/imaskjs/issues/134\n return (super.typedValueEquals(value) || MaskedNumber.EMPTY_VALUES.includes(value) && MaskedNumber.EMPTY_VALUES.includes(this.typedValue)) && !(value === 0 && this.value === '');\n }\n}\n_MaskedNumber = MaskedNumber;\nMaskedNumber.UNMASKED_RADIX = '.';\nMaskedNumber.EMPTY_VALUES = [...Masked.EMPTY_VALUES, 0];\nMaskedNumber.DEFAULTS = {\n ...Masked.DEFAULTS,\n mask: Number,\n radix: ',',\n thousandsSeparator: '',\n mapToRadix: [_MaskedNumber.UNMASKED_RADIX],\n min: Number.MIN_SAFE_INTEGER,\n max: Number.MAX_SAFE_INTEGER,\n scale: 2,\n normalizeZeros: true,\n padFractionalZeros: false,\n parse: Number,\n format: n => n.toLocaleString('en-US', {\n useGrouping: false,\n maximumFractionDigits: 20\n })\n};\nIMask.MaskedNumber = MaskedNumber;\n\nexport { MaskedNumber as default };\n"],"names":["form","document","querySelector","results","calculatorData","JSON","parse","dataset","json","headline","totalBaseInput","percentMissPaymentRange","percentMissPaymentInput","latePaymentDaysRange","latePaymentDaysInput","percentMonthlyChurnRange","percentMonthlyChurnInput","amountOwedInput","IMask","mask","Number","scale","signed","thousandsSeparator","max","MAX_SAFE_INTEGER","input","range","forEach","fields","min","parseInt","getAttribute","addEventListener","value","updateValue","classList","remove","on","padFractionalZeros","radix","mapToRadix","normalizeZeros","prepare","str","replace","overwrite","normalizeNumber","parseFloat","replaceAll","toCurrency","number","Intl","NumberFormat","style","currency","format","async","e","preventDefault","isValid","querySelectorAll","field","checkValidity","add","once","scrollToIfNeeded","submitBtn","data","FormData","totalBase","get","percentMonthlyChurn","amountOwed","totalMonthlyChurn","annualBadDebtExposure","lowAnnualRevenueReturn","reduce_bad_debt_low_percentage","highAnnualRevenueReturn","reduce_bad_debt_high_percentage","textContent","disabled","duration","Promise","resolve","setTimeout","wait","contains","slideDown","resultsLabel","window","dataLayer","push","event","form_type","scrollTo","target","additionalOffset","pageOffset","getPageOffset","offset","siteHeaderHeight","getComputedStyle","documentElement","getPropertyValue","scrollOffset","jump","callback","rect","getBoundingClientRect","viewportHeight","innerHeight","clientHeight","isInViewport","top","bottom","is50PercentFromTop","defaultOptions","easing","fill","display","overflow","nonAnimatableOptions","SlideController","element","options","mergedOptions","Object","assign","openDisplayValue","setDisplay","getHeight","setOverflow","set","getAnimations","triggerAnimation","willOpen","finishedAnimations","map","a","finish","currentHeight","lowerBound","_a","property","frames","height","paddingTop","paddingBottom","reverse","matchMedia","matches","animation","animate","id","toString","createAnimation","finished","requestAnimationFrame","length","up2","down2","up","down","toggle","existingAnimationId","offsetHeight","slideUp","slide","then","slideToggle","easeInOutQuad","t","b","c","d","_typeof","Symbol","iterator","obj","constructor","prototype","start","stop","a11y","distance","timeStart","timeElapsed","next","loop","timeCurrent","setAttribute","focus","arguments","undefined","scrollY","pageYOffset","jumper","_MaskedNumber","MaskedNumber","opts","super","DEFAULTS","updateOptions","_update","this","_updateRegExps","allowNegative","end","_numberRegExp","RegExp","_mapToRadixRegExp","join","_thousandsSeparatorRegExp","_removeThousandsSeparators","_insertThousandsSeparators","parts","split","doPrepareChar","ch","flags","prepCh","details","raw","skip","allowPositive","aggregate","_appendChar","_separatorsCount","to","extendOnSeparators","count","pos","_value","indexOf","_separatorsCountFromSlice","slice","extractInput","fromPos","toPos","displayValue","_adjustRangeWithSeparators","_appendCharRaw","prevBeforeTailValue","tail","_beforeTailState","prevBeforeTailSeparatorsCount","oldValue","num","appendDetails","accepted","isNaN","fixedNum","autofix","UNMASKED_RADIX","Boolean","match","inserted","rawInserted","beforeTailValue","beforeTailSeparatorsCount","tailShift","_findSeparatorAround","searchFrom","separatorPos","from","separatorAroundFromPos","separatorAroundToPos","valueBeforePos","valueAfterPos","nearestInputPos","cursorPos","direction","NONE","LEFT","FORCE_LEFT","separatorAtLeftPos","separatorAtLeftEndPos","RIGHT","FORCE_RIGHT","separatorAtRightPos","doCommit","validnum","Math","unmaskedValue","formatted","_normalizeZeros","_padFractionalZeros","sign","zeros","test","padEnd","doSkipInvalid","checkTail","dropFractional","includes","typedValue","n","rawInputValue","typedValueEquals","EMPTY_VALUES","MIN_SAFE_INTEGER","toLocaleString","useGrouping","maximumFractionDigits"],"sourceRoot":""}