UNPKG

js-utl

Version:

A collection of JS utility functions to be used across several applications or libraries.

6,294 lines 244 kB
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define("JSUtl", [], factory);
	else if(typeof exports === 'object')
		exports["JSUtl"] = factory();
	else
		root["JSUtl"] = factory();
})((typeof self !== 'undefined' ? self : this), function() {
return /******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "unshiftArray": () => (/* binding */ unshiftArray),
/* harmony export */   "cloneArray": () => (/* binding */ cloneArray),
/* harmony export */   "arraySliceFromValueToValue": () => (/* binding */ arraySliceFromValueToValue),
/* harmony export */   "areArrayItemsAllCoercibleToNumber": () => (/* binding */ areArrayItemsAllCoercibleToNumber),
/* harmony export */   "arrayOrArrayLike": () => (/* binding */ arrayOrArrayLike),
/* harmony export */   "lastOfArray": () => (/* binding */ lastOfArray),
/* harmony export */   "firstOfArray": () => (/* binding */ firstOfArray),
/* harmony export */   "arrayFindReverse": () => (/* binding */ arrayFindReverse),
/* harmony export */   "arrayMax": () => (/* binding */ arrayMax),
/* harmony export */   "arrayMin": () => (/* binding */ arrayMin),
/* harmony export */   "sortNums": () => (/* binding */ sortNums)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Array-related utility functions.
 */

/**
 * Unshifts an array.
 *
 * @param {Array} arr The array.
 * @param {*} item The item to unshift.
 * @return {undefined}
 */
function unshiftArray(arr, item) {
  let len = arr.length;
  while (len) {
    arr[len] = arr[len - 1];
    len--;
  }
  arr[0] = item;
}

/**
 * Clones an array.
 *
 * @param {Array} arr The array to clone.
 * @return {Array} The cloned array.
 */
function cloneArray(arr) {
  return arr.slice(0);
}

/**
 * Gets a slice of an array from a value up until another.
 *
 * @param {Array} arr The input array.
 * @param {number} from The "from" lower value.
 * @param {number} to The "two" upper value.
 * @return {Array} The slice as a new array.
 */
function arraySliceFromValueToValue(arr, from, to) {
  const ret = [];
  let include = false;
  for (const value of arr) {
    if (!include && value == from) {
      ret.push(value);
      include = true;
    } else if (include && value == to) {
      ret.push(value);
      break;
    } else if (include) {
      ret.push(value);
    }
  }
  return ret;
}

/**
 * Tests whether all the elements of an array are coercible to a number or not.
 *
 * @param {Array} array An array.
 * @return {boolean} True if all the elements are coercible to a number, false otherwise.
 */
function areArrayItemsAllCoercibleToNumber(array) {
  const res = !array.some(isNaN);
  return res;
}

/**
 * Copies an array or converts an array-like object to a new array.
 *
 * @param {*} arg Array or array-like object.
 * @return {Array} An array.
 */
function arrayOrArrayLike(arg) {
  return Array.prototype.slice.call(arg);
}

/**
 * Returns the last element of the given array.
 *
 * @param {Array} array An array.
 * @return {*} The last element of the array or undefined if there isn't one.
 */
function lastOfArray(array) {
  return array[array.length - 1];
}

/**
 * Returns the first element of the given array.
 *
 * @param {Array} array An array.
 * @return {*} The first element of the array or undefined if there isn't one.
 */
function firstOfArray(array) {
  return array[0];
}

/**
 * Like {@link Array.prototype.find}, but in reverse order.
 *
 * @param {Array} array An array.
 * @param {Function} fn Function to use for the test. The function will receive the array element as parameter.
 * @return {*} The first element which satisfies the test in the array by seeking for the element in reverse order
 *             (i.e. the last element of the array for which the test is satisfied).
 *             If no element satisfies the test, "undefined" is returned.
 */
function arrayFindReverse(array, fn) {
  let l = array.length;

  let ret = void 0;
  while (l) {
    l--;
    if (fn(array[l])) {
      ret = array[l];
      break;
    }
  }
  return ret;
}

/**
 * Finds the maximum value of an array of numbers.
 *
 * @param {number[]} array An array of numbers.
 * @return {number|undefined} The maximum value of the array, or "undefined"
 *                            if the given array is empty.
 */
const arrayMax = array =>
  array.length
    ? array.reduce(
        (carry, current) => (current > carry ? current : carry),
        -Infinity
      )
    : void 0;

/**
 * Finds the minimum value of an array of numbers.
 *
 * @param {number[]} array An array of numbers.
 * @return {number|undefined} The minimum value of the array, or "undefined"
 *                            if the given array is empty.
 */
const arrayMin = array =>
  array.length
    ? array.reduce(
        (carry, current) => (current < carry ? current : carry),
        +Infinity
      )
    : void 0;

/**
 * Sorts an array of numbers returning a new array with the sorted
 * numbers (does not mutate the original).
 *
 * @param {number[]} arrayOfNums An array of numbers.
 * @param {boolean} [desc] True for descending order, false for ascending order (default).
 * @return {number[]} A new array with the sorted numbers.
 */
const sortNums = (arrayOfNums, desc = false) =>
  [...arrayOfNums].sort((a, b) =>
    !desc // asc
      ? a - b
      : // desc
        b - a
  );


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "turnNthBitOff": () => (/* binding */ turnNthBitOff),
/* harmony export */   "turnNthBitOn": () => (/* binding */ turnNthBitOn),
/* harmony export */   "toggleNthBit": () => (/* binding */ toggleNthBit),
/* harmony export */   "checkNthBitOn": () => (/* binding */ checkNthBitOn)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Bitwise utility functions.
 */

/**
 * Turns nth bit off.
 *
 * @param {number} num A number.
 * @param {number} nth Nth bit to turn off (starting from 1 for the rightmost bit).
 * @return {number} New number with the nth bit turned off.
 */
const turnNthBitOff = (num, nth) => num & ~(1 << (nth - 1));

/**
 * Turns nth bit on.
 *
 * @param {number} num A number.
 * @param {number} nth Nth bit to turn on (starting from 1 for the rightmost bit).
 * @return {number} New number with the nth bit turned off.
 */
const turnNthBitOn = (num, nth) => num | (1 << (nth - 1));

/**
 * Toggles nth bit.
 *
 * @param {number} num A number.
 * @param {number} nth Nth bit to toggle (starting from 1 for the rightmost bit).
 * @return {number} New number with the nth bit toggled.
 */
const toggleNthBit = (num, nth) => num ^ (1 << (nth - 1));

/**
 * Checks if nth bit is on.
 *
 * @param {number} num A number.
 * @param {number} nth Nth bit to check.
 * @param {number} 0 if the nth bit is off, otherwise a number greater than 0 if the nth bit is on.
 */
const checkNthBitOn = (num, nth) => num & (1 << (nth - 1));


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "delay": () => (/* binding */ delay),
/* harmony export */   "debounce": () => (/* binding */ debounce),
/* harmony export */   "throttle": () => (/* binding */ throttle)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions for callback handling (like debouncing, throttling).
 */



/**
 * Delays execution of a callback and cancels a previously registered callback if it wasn't executed yet.
 */
const delay = (function () {
  let timer = 0;

  /**
   * Inner function.
   *
   * @param {Function} callback The callback to execute.
   * @param {number} ms Milliseconds to wait before executing the callback.
   * @return {undefined}
   */
  return function (callback, ms) {
    clearTimeout(timer);
    timer = setTimeout(function () {
      callback();
    }, ms);
  };
})();

/**
 * Debounces a function.
 *
 * @param {Function} fn A function.
 * @param {number} wait Wait interval in milliseconds.
 * @return {Function} A new function, debounced.
 */
function debounce(fn, wait) {
  let timer = void 0;
  return function (...args) {
    !(0,_core__WEBPACK_IMPORTED_MODULE_0__.isUndefined)(timer) && clearTimeout(timer);
    timer = setTimeout(function () {
      fn(...args);
    }, wait);
  };
}

/**
 * Throttles a function.
 *
 * @see https://www.sitepoint.com/throttle-scroll-events/
 *
 * @param {Function} fn A function.
 * @param {number} wait Wait interval in milliseconds.
 * @return {Function} A new function, throttled.
 */
function throttle(fn, wait) {
  let time = Date.now();
  return function (...args) {
    if (time + wait - Date.now() < 0) {
      fn(...args);
      time = Date.now();
    }
  };
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "getLuminance": () => (/* binding */ getLuminance),
/* harmony export */   "intToRGBHexString": () => (/* binding */ intToRGBHexString),
/* harmony export */   "colorFromString": () => (/* binding */ colorFromString)
/* harmony export */ });
/* harmony import */ var _hash__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./hash */ "./src/modules/hash.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */



/**
 * Color-related utility functions.
 */

/**
 * Gets a color's luminance.
 *
 * @param {number} color Color int value (RGB).
 * @return {number} An int greater than 160 if the color is considered dark and less than or
 *                  equal to 160 if the color is considered light.
 */
function getLuminance(color) {
  const c = parseInt(color, 16);
  const r = (c & 0xff0000) >> 16;
  const g = (c & 0x00ff00) >> 8;
  const b = c & 0x0000ff;
  return 0.299 * r + 0.587 * g + 0.114 * b;
}

/**
 * Converts an integer to an RGB hex (hexadecimal) string.
 *
 * @param {number} i An integer.
 * @return {string} An RGB hex string (uppercase).
 */
function intToRGBHexString(i) {
  const c = (i & 0x00ffffff).toString(16).toUpperCase();
  return "00000".substring(0, 6 - c.length) + c;
}

/**
 * Converts a string to an RGB hex (hexadecimal) string representing a color.
 *
 * @param {string} str The string.
 * @return {string} The color as an RGB hex string (uppercase).
 */
const colorFromString = str => {
  const hash = (0,_hash__WEBPACK_IMPORTED_MODULE_0__.hashString)(str);
  return intToRGBHexString(hash);
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "yieldCombinationsWithoutRepetition": () => (/* binding */ yieldCombinationsWithoutRepetition),
/* harmony export */   "uniqueProgressiveIncrementalCombinations": () => (/* binding */ uniqueProgressiveIncrementalCombinations),
/* harmony export */   "yieldUniqueProgressiveIncrementalCombinations": () => (/* binding */ yieldUniqueProgressiveIncrementalCombinations),
/* harmony export */   "yieldAllSubsequences": () => (/* binding */ yieldAllSubsequences),
/* harmony export */   "yieldUniqueSubsequences": () => (/* binding */ yieldUniqueSubsequences),
/* harmony export */   "yieldPermutations": () => (/* binding */ yieldPermutations)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/* harmony import */ var _array__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./array */ "./src/modules/array.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Combinatorics utility functions.
 */




/**
 * Yields all the combinations of an array without repetitions (binomial coefficient).
 *
 * @generator
 * @param {Array} items An array.
 * @param {number} numberOfItemsPerCombination The number of elements in each combination
 *                                             (this function assumes it to be less than "items.length"
 *                                             and greater than 0).
 * @param {boolean} yieldCopy True if the yielded combination should be a copy (default) or
 *                            the internal array used during the generation of the current combination.
 * @yields {Array} The next combination.
 */
const yieldCombinationsWithoutRepetition = function* (
  items,
  numberOfItemsPerCombination,
  yieldCopy = true
) {
  const l = items.length;
  const prefix = [];

  const recurse = function* recurse(
    items,
    l,
    prefix,
    numberOfItemsPerCombination,
    nextIndex = 0
  ) {
    // Same as:
    // if (nextIndex === numberOfItemsPerCombination) {
    if (prefix.length === numberOfItemsPerCombination) {
      // Base case:
      yield yieldCopy ? (0,_array__WEBPACK_IMPORTED_MODULE_1__.arrayOrArrayLike)(prefix) : prefix;
    } else {
      // Recurrent case:
      for (
        let i = nextIndex;
        i < l &&
        // Remaining needed items
        numberOfItemsPerCombination - prefix.length <=
          // Remaining available items
          l - i;
        i++
      ) {
        prefix.push(items[i]);
        yield* recurse(items, l, prefix, numberOfItemsPerCombination, i + 1);
        prefix.pop();
      }
    }
  };

  yield* recurse(items, l, prefix, numberOfItemsPerCombination);
};

/**
 * Generate unique, progressive and incremental combinations.
 *
 * @param {Array} items An array of items.
 * @return {Array[]} An array of arrays, each representing a unique progressive incremental combination.
 *                   An empty array is returned if the given items array is empty.
 */
const uniqueProgressiveIncrementalCombinations = items => {
  const len = items.length;
  if (len === 0) {
    return [];
  }

  const last = (0,_array__WEBPACK_IMPORTED_MODULE_1__.arrayOrArrayLike)(items); // Shallow copy/clone of the given array.
  if (len === 1) {
    // [1] => [[1]]
    return [last];
  }

  const ret = [];
  // [1], [2], [3], ..., [n]
  items.map(item => ret.push([item]));

  if (len > 2) {
    // There  are at least three items.
    for (
      let numberOfItemsPerCombination = 2;
      numberOfItemsPerCombination < len;
      numberOfItemsPerCombination++
    ) {
      for (const combination of yieldCombinationsWithoutRepetition(
        items,
        numberOfItemsPerCombination
      )) {
        ret.push(combination);
      }
    }
  }

  ret.push(last);
  return ret;
};

/**
 * Yields unique, progressive and incremental combinations.
 *
 * @generator
 * @param {Array} items An array of items.
 * @param {boolean} yieldCopy True if some of the yielded combinations should be a copy (default)
 *                         of the corresponding internal array used during the generation of the current combination
 *                         or that same array should be returned (if "yieldCopy" is "false").
 * @yields {Array} An array, each representing the next unique progressive incremental combination.
 *                 An empty array is yielded if the given items array is empty.
 */
const yieldUniqueProgressiveIncrementalCombinations = function* (
  items,
  yieldCopy = true
) {
  const len = items.length;
  if (len === 0) {
    return;
  }

  const last = yieldCopy ? (0,_array__WEBPACK_IMPORTED_MODULE_1__.arrayOrArrayLike)(items) : items; // Shallow copy/clone of the given array.
  if (len === 1) {
    // [1] => [[1]]
    yield last;
    return;
  }

  // [1], [2], [3], ..., [n]
  yield* (0,_core__WEBPACK_IMPORTED_MODULE_0__.mapYield)(items, item => [item]);

  if (len > 2) {
    // There  are at least three items.
    for (
      let numberOfItemsPerCombination = 2;
      numberOfItemsPerCombination < len;
      numberOfItemsPerCombination++
    ) {
      for (const combination of yieldCombinationsWithoutRepetition(
        items,
        numberOfItemsPerCombination,
        yieldCopy
      )) {
        yield combination;
      }
    }
  }

  yield last;
};

/**
 * Yields all the subsequences of the given array of items.
 *
 * @generator
 * @param {Array} items An array of items to use to yield subsequences.
 * @yields {Array} The next subsequence.
 */
const yieldAllSubsequences = function* (items) {
  const l = items.length;
  for (let i = 0; i <= l; i++) {
    for (const combination of yieldCombinationsWithoutRepetition(items, i)) {
      yield combination;
    }
  }
};

/**
 * Yields only the unique subsequences of the given array of items.
 *
 * @generator
 * @param {Array} items An array of items to use to yield subsequences.
 * @yields {Array} The next unique subsequence.
 */
const yieldUniqueSubsequences = function* (items) {
  const map = new Map();
  yield [];
  for (const subsequence of yieldAllSubsequences(items)) {
    if (!(0,_core__WEBPACK_IMPORTED_MODULE_0__.nestedMapHas)(map, subsequence)) {
      (0,_core__WEBPACK_IMPORTED_MODULE_0__.nestedMapSet)(map, subsequence, true);
      yield subsequence;
    }
  }
};

/**
 * Yields all the permutations of the given array of items.
 *
 * @generator
 * @param {Array} items An array of items to use to yield permutations.
 * @param {boolean} yieldCopy True if the yielded permutation should be a copy (default) or
 *                            the internal array used during the generation of the current permutation.
 * @yields {Array} The next permutation.
 */
const yieldPermutations = function* (items, yieldCopy = true) {
  const currentPermutationPrefix = [];
  const currentPermutationIndicesMap = {};
  const permute = function* () {
    if (currentPermutationPrefix.length === items.length) {
      yield yieldCopy
        ? (0,_array__WEBPACK_IMPORTED_MODULE_1__.arrayOrArrayLike)(currentPermutationPrefix)
        : currentPermutationPrefix;
    } else {
      for (let i = 0; i < items.length; i++) {
        if (currentPermutationIndicesMap[i]) {
          continue;
        }
        currentPermutationPrefix.push(items[i]);
        currentPermutationIndicesMap[i] = true;
        yield* permute();
        delete currentPermutationIndicesMap[i];
        currentPermutationPrefix.pop();
      }
    }
  };
  yield* permute();
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "filterInt": () => (/* binding */ filterInt),
/* harmony export */   "filterFloat": () => (/* binding */ filterFloat)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Constraints and filtering utility functions.
 */

/**
 * Filters the given string so that it only includes digit (0-9)
 * and an optional leading sign ("+", which is removed if present, or "-"),
 * i.e. represents a valid integer parsable with "Number.parseInt()".
 *
 * @param {string} str The input string.
 * @return {string} The valid input string or an empty string if there isn't any digit.
 */
function filterInt(str) {
  let filtered = str.replace(/[^0-9]/g, "");
  filtered = filtered.replace(/^[0]+([1-9])/, "$1");
  filtered = filtered.replace(/^[0]+$/, "0");
  if (str && filtered.length && str[0] === "-") {
    filtered = `-${filtered}`;
  }
  return filtered;
}

/**
 * Filters the given string so that it only includes digits (0-9), a decimal separator ("." character)
 * and an optional leading sign ("+", which is removed if present, or "-"),
 * i.e. represents a valid float parsable with "Number.parseFloat()".
 *
 * @param {string} str The input string.
 * @return {string} The valid float string or an empty string if there isn't any digit or decimal separator.
 *                  If there isn't any digit in the input string and there is a decimal separator ("." character),
 *                  the returned string will be "0.", i.e. a parsable "0." string.
 */
function filterFloat(str) {
  let filtered = str.replace(/[^0-9.]/g, "");
  const regex = /(\..*)\./g;
  const replace = "$1";
  do {
    filtered = filtered.replace(regex, replace);
  } while (filtered != filtered.replace(regex, replace));
  filtered === "." ? (filtered = "0.") : filtered;
  filtered = filtered.replace(/^[0]+([1-9])/, "$1");
  filtered = filtered.replace(/^[0]+($|\.)/, "0$1");
  if (str && filtered.length && str[0] === "-") {
    filtered = `-${filtered}`;
  }
  return filtered;
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "b2d": () => (/* binding */ b2d),
/* harmony export */   "d2b": () => (/* binding */ d2b)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions related to conversion of data from one format to another.
 */

/**
 * Binary to decimal.
 *
 * @param {string} x Binary string.
 * @return {number} Decimal number.
 */
const b2d = x => parseInt(x, 2);

/**
 * Decimal to binary.
 *
 * @param {number} x Decimal number.
 * @return {string} Binary representation.
 */
const d2b = x => x.toString(2);


/***/ }),

/***/ "./src/modules/core/compare.js":
/*!*************************************!*\
  !*** ./src/modules/core/compare.js ***!
  \*************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "is": () => (/* binding */ is),
/* harmony export */   "objectPropEqual": () => (/* binding */ objectPropEqual),
/* harmony export */   "shallowEqual": () => (/* binding */ shallowEqual)
/* harmony export */ });
/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @typechecks
 *
 */

/**
 * @type {Function}
 */
const hasOwnProperty = Object.prototype.hasOwnProperty;

/**
 * Function implementing "Object.is" behaviour.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 *
 * @param {*} x The first value to compare.
 * @param {*} y The second value to compare.
 * @return {boolean} A boolean indicating whether or not the two arguments are the same value.
 */
function is(x, y) {
  // SameValue algorithm
  if (x === y) {
    // Steps 1-5, 7-10
    // Steps 6.b-6.e: +0 != -0
    return x !== 0 || 1 / x === 1 / y;
  } else {
    // Step 6.a: NaN == NaN
    return x !== x && y !== y;
  }
}

/**
 * Checks whether a prop of an object equals in the other object (shallow comparison).
 *
 * @param {Object} objA The first object.
 * @param {Object} objB The second object.
 * @param {string} prop The name of the property.
 * @return {boolean} True if the value of "prop" in "objA" is shallowly equal to the value of "prop" in "objB".
 */
function objectPropEqual(objA, objB, prop) {
  return hasOwnProperty.call(objB, prop) && is(objA[prop], objB[prop]);
}

/**
 * Performs equality by iterating through keys on an object and returning "false"
 * when any key has values which are not strictly equal between the arguments.
 * Returns "true" when the values of all keys are strictly equal.
 *
 * @see https://stackoverflow.com/questions/22266826/how-can-i-do-a-shallow-comparison-of-the-properties-of-two-objects-with-javascri#answer-37636728
 *
 * @param {*} objA First object.
 * @param {*} objB Second object.
 * @return {boolean}
 */
function shallowEqual(objA, objB) {
  if (is(objA, objB)) {
    return true;
  }

  if (
    typeof objA !== "object" ||
    objA === null ||
    typeof objB !== "object" ||
    objB === null
  ) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    const prop = keysA[i];
    if (!objectPropEqual(objA, objB, prop)) {
      return false;
    }
  }

  return true;
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "shallowEqual": () => (/* reexport safe */ _compare__WEBPACK_IMPORTED_MODULE_0__.shallowEqual),
/* harmony export */   "objectPropEqual": () => (/* reexport safe */ _compare__WEBPACK_IMPORTED_MODULE_0__.objectPropEqual),
/* harmony export */   "is": () => (/* reexport safe */ _compare__WEBPACK_IMPORTED_MODULE_0__.is),
/* harmony export */   "config": () => (/* binding */ config),
/* harmony export */   "isObjectEmpty": () => (/* binding */ isObjectEmpty),
/* harmony export */   "isObject": () => (/* binding */ isObject),
/* harmony export */   "isPlainObject": () => (/* binding */ isPlainObject),
/* harmony export */   "isArray": () => (/* binding */ isArray),
/* harmony export */   "isCallable": () => (/* binding */ isCallable),
/* harmony export */   "isEmpty": () => (/* binding */ isEmpty),
/* harmony export */   "isEmptyOr0": () => (/* binding */ isEmptyOr0),
/* harmony export */   "getGlobalObject": () => (/* binding */ getGlobalObject),
/* harmony export */   "uniqueId": () => (/* binding */ uniqueId),
/* harmony export */   "nestedPropertyValue": () => (/* binding */ nestedPropertyValue),
/* harmony export */   "getNestedPropertyValue": () => (/* binding */ getNestedPropertyValue),
/* harmony export */   "hasNestedPropertyValue": () => (/* binding */ hasNestedPropertyValue),
/* harmony export */   "setNestedPropertyValue": () => (/* binding */ setNestedPropertyValue),
/* harmony export */   "nestedMapSet": () => (/* binding */ nestedMapSet),
/* harmony export */   "nestedMapHas": () => (/* binding */ nestedMapHas),
/* harmony export */   "nestedMapGet": () => (/* binding */ nestedMapGet),
/* harmony export */   "nestedTreeMapSet": () => (/* binding */ nestedTreeMapSet),
/* harmony export */   "nestedTreeMapHas": () => (/* binding */ nestedTreeMapHas),
/* harmony export */   "nestedTreeMapGet": () => (/* binding */ nestedTreeMapGet),
/* harmony export */   "mapYield": () => (/* binding */ mapYield),
/* harmony export */   "deepArrayCompare": () => (/* binding */ deepArrayCompare),
/* harmony export */   "deepObjectCompare": () => (/* binding */ deepObjectCompare),
/* harmony export */   "nestedObjectConstructValue": () => (/* binding */ nestedObjectConstructValue),
/* harmony export */   "cloneDeeplyJSON": () => (/* binding */ cloneDeeplyJSON),
/* harmony export */   "isReferenceType": () => (/* binding */ isReferenceType),
/* harmony export */   "isPrimitiveType": () => (/* binding */ isPrimitiveType),
/* harmony export */   "hasCyclicReference": () => (/* binding */ hasCyclicReference),
/* harmony export */   "typeToStr": () => (/* binding */ typeToStr),
/* harmony export */   "cloneObjDeeply": () => (/* binding */ cloneObjDeeply),
/* harmony export */   "deepObjectExtend": () => (/* binding */ deepObjectExtend),
/* harmony export */   "deepObjectCloningExtend": () => (/* binding */ deepObjectCloningExtend),
/* harmony export */   "extend": () => (/* binding */ extend),
/* harmony export */   "extendDecorate": () => (/* binding */ extendDecorate),
/* harmony export */   "shallowExtend": () => (/* binding */ shallowExtend),
/* harmony export */   "includesTypeCoercion": () => (/* binding */ includesTypeCoercion),
/* harmony export */   "isUndefined": () => (/* binding */ isUndefined),
/* harmony export */   "isInt": () => (/* binding */ isInt),
/* harmony export */   "ctypeDigit": () => (/* binding */ ctypeDigit),
/* harmony export */   "isIntegerOrIntegerStr": () => (/* binding */ isIntegerOrIntegerStr),
/* harmony export */   "findIndex": () => (/* binding */ findIndex),
/* harmony export */   "firstPropValue": () => (/* binding */ firstPropValue),
/* harmony export */   "isStrictlyTrue": () => (/* binding */ isStrictlyTrue),
/* harmony export */   "isTruthy": () => (/* binding */ isTruthy),
/* harmony export */   "allTruthy": () => (/* binding */ allTruthy),
/* harmony export */   "allNotUndefined": () => (/* binding */ allNotUndefined),
/* harmony export */   "isJSONString": () => (/* binding */ isJSONString),
/* harmony export */   "noOpFn": () => (/* binding */ noOpFn),
/* harmony export */   "partialShallowEqual": () => (/* binding */ partialShallowEqual),
/* harmony export */   "shallowObjectDiff": () => (/* binding */ shallowObjectDiff),
/* harmony export */   "str": () => (/* binding */ str),
/* harmony export */   "mapObject": () => (/* binding */ mapObject),
/* harmony export */   "mapToObject": () => (/* binding */ mapToObject),
/* harmony export */   "propSelection": () => (/* binding */ propSelection),
/* harmony export */   "prototypeChainProperties": () => (/* binding */ prototypeChainProperties),
/* harmony export */   "prop": () => (/* binding */ prop),
/* harmony export */   "defineProperty": () => (/* binding */ defineProperty),
/* harmony export */   "completeObjectAssign": () => (/* binding */ completeObjectAssign)
/* harmony export */ });
/* harmony import */ var _compare__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./compare */ "./src/modules/core/compare.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */




/**
 * Core utility functions.
 */

/**
 * Optional configuration with useful properties.
 *
 * @type {Object}
 */
const config = {
  uniqueIdPrefix: "",
  elementUniqueIdPrefix: "",
  checkNetworkURI: null,
};

/**
 * Tests if an object is empty.
 *
 * @param {Object} obj The object to test.
 * @return {boolean} "true" if the given object is empty (does not have own properties), "false" otherwise.
 */
function isObjectEmpty(obj) {
  for (const prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
}

/**
 * @type {string}
 */
const objPrototypeToString = Object.prototype.toString.call({});

/**
 * Tests if a variable is an object.
 *
 * @param {*} obj The variable to test.
 * @return {boolean} "true" if "obj" is indeed an object, "false" otherwise.
 */
const isObject = function (obj) {
  return objPrototypeToString === Object.prototype.toString.call(obj);
};

/**
 * Tests if a variable is a plain object (i.e. "{}", an object literal).
 *
 * @param {*} obj The variable to test.
 * @return {boolean} "true" if "obj" is a plain object, "false" otherwise.
 */
const isPlainObject = obj => {
  return (
    obj !== null &&
    typeof obj === "object" &&
    obj.constructor === Object &&
    isObject(obj)
  );
};

/**
 * Tests to see whether something is an array or not.
 *
 * @param {*} something A variable to check whether it is an array or not.
 * @return {boolean} True if the parameter passed in is an array, false otherwise.
 */
function isArray(something) {
  return (
    Object.prototype.toString.call(something) ===
    Object.prototype.toString.call([])
  );
}

/**
 * Tests if the given value is callable.
 *
 * @param {*} v The value.
 * @return {boolean} True if callable, false otherwise.
 */
function isCallable(v) {
  return typeof v === "function";
}

/**
 * Tests if a variable is empty returning true for empty strings and empty arrays.
 *
 * @param {*} data The variable to test.
 * @return {boolean} True if the variable is empty, false otherwise.
 */
function isEmpty(data) {
  return !data || data.length === 0;
}

/**
 * Tests if a variable is empty or 0 ("0" string) returning true for empty strings,
 * empty arrays, the "0" string and empty values.
 *
 * @param {*} data The variable to test.
 * @return {boolean} True if the variable is empty or "0", false otherwise.
 */
function isEmptyOr0(data) {
  return !data || data === "0" || data.length === 0;
}

/**
 * Returns a reference to the global object.
 *
 * @return {Window|global} The global object (this function is cross-platform aware).
 */
function getGlobalObject() {
  return typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : window;
}

/**
 * @type {string}
 */
const JSUtlUniqueIdCounterProp = "JSUtlUniqueIdCounterLEzKKl87QCDxwVH";

/**
 * Generates a unique ID which can be used as an "id" attribute.
 *
 * @param {string|undefined} [uniqueIdPrefix] Local unique ID prefix which overrides the prefix
 *                                            set on the "config" configuration object.
 * @return {string} The unique ID.
 */
function uniqueId(uniqueIdPrefix = void 0) {
  const globalObject = getGlobalObject();
  globalObject[JSUtlUniqueIdCounterProp] =
    globalObject[JSUtlUniqueIdCounterProp] || 0;
  globalObject[JSUtlUniqueIdCounterProp]++;
  const uniqueIdCounter = globalObject[JSUtlUniqueIdCounterProp];
  const uniqueId = (uniqueIdPrefix || config.uniqueIdPrefix) + uniqueIdCounter;
  return uniqueId;
}

/**
 * Gets a nested value of an object given an array of nested property names (keys).
 *
 * @param {Object} data JS POJO object.
 * @param {Array} props Array of object nested keys.
 * @return {*} The leaf value.
 */
function nestedPropertyValue(data, props) {
  let root = data;
  for (let i = 0; i < props.length; i++) {
    const prop = props[i];
    root = root[prop];
  }
  return root;
}

/**
 * Alias for "nestedPropertyValue".
 *
 * @alias
 */
const getNestedPropertyValue = nestedPropertyValue;

/**
 * Checks if a nested value of an object given an array of nested property names (keys) exists.
 *
 * @param {Object} data JS POJO object.
 * @param {Array} props Array of object nested keys.
 * @return {boolean} True if the nested key exists, false otherwise.
 */
function hasNestedPropertyValue(data, props) {
  if (!props.length) {
    return false;
  }
  let root = data;
  for (let i = 0; i < props.length; i++) {
    const prop = props[i];
    if (!root[prop]) {
      return false;
    }
    root = root[prop];
  }
  return true;
}

/**
 * Sets a nested value of an object given an array of nested property names (keys).
 *
 * @param {Object} data JS POJO object.
 * @param {Array} props Array of object nested keys.
 * @param {*} value Leaf value.
 * @return {undefined}
 */
function setNestedPropertyValue(data, props, value) {
  if (!props.length) {
    return;
  }
  let root = data;
  let prev = null;
  for (let i = 0; i < props.length; i++) {
    const prop = props[i];
    if (typeof root[prop] !== "object") {
      root[prop] = {};
    }
    prev = root;
    root = root[prop];
  }
  if (prev) {
    prev[props[props.length - 1]] = value;
  }
}

/**
 * Sets a nested value on a nested map.
 *
 * @param {Map|WeakMap} map A map or weak map.
 * @param {Array} keys Array of keys to traverse. Each key will lead to a nested map.
 * @param {*} value The value to set at the inner key.
 * @return {undefined}
 */
const nestedMapSet = (map, keys, value) => {
  let i = 0;
  let current = map;
  while (i < keys.length - 1) {
    const key = keys[i];
    const nested = current.get(key);
    if (nested instanceof Map || nested instanceof WeakMap) {
      current = nested;
    } else {
      const newMap = new Map();
      current.set(key, newMap);
      current = newMap;
    }
    i++;
  }
  current.set(keys[i], value);
};

/**
 * Tests if a map has the given nested keys.
 *
 * @param {Map|WeakMap} map A map or weak map.
 * @param {Array} keys Array of keys to check. Each key represents a nested map.
 * @return {boolean} "true" if all the nested keys exist, false otherwise.
 */
const nestedMapHas = (map, keys) => {
  let current = map;
  let i = 0;
  const l = keys.length;
  while (
    (current instanceof Map || current instanceof WeakMap) &&
    current.has(keys[i]) &&
    i < l
  ) {
    current = current.get(keys[i]);
    i++;
  }
  return i == l;
};

/**
 * Gets a value from a nested map.
 *
 * @param {Map|WeakMap} map A map or weak map.
 * @param {Array} keys Array of keys. Each key represents a nested map.
 * @return {*} The value of the map or "undefined" if there is no value for the given nested keys.
 */
const nestedMapGet = (map, keys) => {
  let current = map;
  let i = 0;
  const l = keys.length;
  while (
    (current instanceof Map || current instanceof WeakMap) &&
    current.has(keys[i]) &&
    i < l
  ) {
    current = current.get(keys[i]);
    i++;
  }
  return i == l ? current : void 0;
};

/**
 * @type {Symbol}
 */
const treeMapSubtree = Symbol("treeMapSubtree");

/**
 * Sets a nested value on a nested tree map.
 *
 * @param {Map|WeakMap} rootMap A map or weak map to use as the root.
 * @param {Array} keys Array of keys to traverse. Each key will lead to a nested node of the tree map.
 * @param {*} value The value to set at the inner nested key.
 * @return {undefined}
 */
const nestedTreeMapSet = (rootMap, keys, value) => {
  let i = 0;
  let current = rootMap;
  const MapConstructor = rootMap instanceof WeakMap ? WeakMap : Map;
  while (i < keys.length - 1) {
    const key = keys[i];
    const nested = current.get(key);
    if (nested) {
      current =
        nested[treeMapSubtree] ||
        (nested[treeMapSubtree] = new MapConstructor());
    } else {
      const newMap = new MapConstructor();
      const node = {
        [treeMapSubtree]: newMap,
        value: void 0,
      };
      current.set(key, node);
      current = newMap;
    }
    i++;
  }
  const key = keys[i];
  !current.has(key)
    ? current.set(key, {
        value,
      })
    : (current.get(key).value = value);
};

/**
 * Tests if a tree map has the given nested keys.
 *
 * @param {Map|WeakMap} rootMap The root of the map or weak map.
 * @param {Array} keys Array of keys to check. Each key represents a nested node of the tree map.
 * @return {boolean} "true" if all the nested keys exist, false otherwise.
 */
const nestedTreeMapHas = (rootMap, keys) => {
  let current = rootMap;
  let i = 0;
  const l = keys.length;
  while (
    (current instanceof Map || current instanceof WeakMap) &&
    current.has(keys[i]) &&
    i < l
  ) {
    current = current.get(keys[i])[treeMapSubtree];
    i++;
  }
  return i == l;
};

/**
 * Gets a value from a nested tree map.
 *
 * @param {Map|WeakMap} rootMap The root of the map or weak map.
 * @param {Array} keys Array of keys. Each key represents a nested node of the tree map.
 * @return {*} The value of the tree map or "undefined" if there is no value for the given nested keys.
 */
const nestedTreeMapGet = (rootMap, keys) => {
  let current = rootMap;
  let i = 0;
  const lastIndex = keys.length - 1;
  while (
    (current instanceof Map || current instanceof WeakMap) &&
    current.has(keys[i]) &&
    i < lastIndex
  ) {
    current = current.get(keys[i])[treeMapSubtree];
    i++;
  }
  if (i === lastIndex && current) {
    const lastKey = keys[i];
    if (current.has(lastKey)) {
      const nested = current.get(lastKey);
      return nested.value;
    }
  }
  return void 0;
};

/**
 * Yields values of an array mapping the yielded value.
 *
 * @generator
 * @param {Array} items An array of items.
 * @param {*} fn The function to call.
 *               The function will receive, in order the nth item,
 *               the index of the item in the array of items and the whole items array
 *               as parameters.
 * @param {*} thisArg Optional this arg of the called function (defaults to undefined).
 * @yields {*} The next yielded mapped item.
 */
function* mapYield(items, fn, thisArg = void 0) {
  items.map();
  const boundFn = fn.bind(thisArg);
  for (let i = 0; i < items.length; i++) {
    yield boundFn(items[i], i, items);
  }
}

/**
 * Compares two arrays deeply.
 *
 * @param {Array} arr1 First array.
 * @param {Array} arr2 Second array.
 * @return {boolean} True if they are equal (same indexes and same values), false otherwise.
 */
function deepArrayCompare(arr1, arr2) {
  if (arr1.length != arr2.length) {
    return false;
  }
  const toString = Object.prototype.toString;
  const arrayToStringStr = toString.call([]);
  for (let i = 0; i < arr1.length; i++) {
    if (!(i in arr2)) {
      return false;
    } else if (isPlainObject(arr1[i])) {
      if (
        !isPlainObject(arr2[i]) ||
        // eslint-disable-next-line @typescript-eslint/no-use-before-define
        !deepObjectCompare(arr1[i], arr2[i])
      ) {
        return false;
      }
    } else if (arrayToStringStr === toString.call(arr1[i])) {
      if (
        arrayToStringStr !== toString.call(arr2[i]) ||
        !deepArrayCompare(arr1[i], arr2[i])
      ) {
        return false;
      }
    } else {
      if (arr1[i] !== arr2[i]) {
        return false;
      }
    }
  }
  return true;
}

/**
 * Compare two objects deeply.
 *
 * @param {Object} obj1 First object.
 * @param {Object} obj2 Second object.
 * @return {boolean} True if they are equal (same properties and same values), false otherwise.
 */
function deepObjectCompare(obj1, obj2) {
  const toString = Object.prototype.toString;
  const arrayToStringStr = toString.call([]);
  for (const property in obj1) {
    if (!(property in obj2)) {
      // `obj2[property]` does not contain the property of `obj1`.
      return false;
    } else if (isPlainObject(obj1[property])) {
      // `obj1[property]` is an object.
      if (
        !isPlainObject(obj2[property]) ||
        !deepObjectCompare(obj1[property], obj2[property])
      ) {
        // `obj2[property]` is not an object or the branches are different.
        return false;
      }
    } else if (arrayToStringStr === toString.call(obj1[property])) {
      // `obj1[property]` is an array.
      if (
        arrayToStringStr !== toString.call(obj2[property]) ||
        !deepArrayCompare(obj1[property], obj2[property])
      ) {
        // `obj2[property]` is not an array or the two objects are different.
        return false;
      }
    } else {
      // `obj1[property]` is not an object and is not an array.
      if (obj1[property] !== obj2[property]) {
        return false;
      }
    }
  }
  // `obj1` equals `obj2` (has the same properties and the same values).
  return true;
}

/**
 * Nests the properties of an object using an array of props definitions and defaults.
 * Returns the leaf.
 *
 * Example:
 *
 * ```
 * const obj = {};
 * let nest = [{a: {}}, {b: {}}, {c: {}}, {d: {}}, {e: {}}, {f: {}}, {g: {}}, {h: {}} ];
 * const leaf = nestedObjectConstructValue(obj, nest);
 * leaf.i = 'i';
 * leaf.l = { m: "m" };
 * JSON.stringify(obj); // {"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":"i","l":{"m":"m"}}}}}}}}}}
 * nest = nest.concat([ {n: {}}, {o: {}}, {p: {}} ]);
 * var pLeaf = nestedObjectConstructValue(obj, nest);
 * pLeaf.q = 'q';
 * nest = nest.concat([ {q: {}} ]);
 * nestedObjectConstructValue(obj, nest); // 'q'
 * ```
 *
 * @param {Object} root The root object.
 * @param {Array} nestedPropsDef The nexted props definitions.
 * @param {boolean} [isRootArrayIfRootFalsy] True if the root should be an array if the first argument "root" is falsy.
 * @return {*} The leaf.
 */
function nestedObjectConstructValue(
  root,
  nestedPropsDef,
  isRootArrayIfRootFalsy
) {
  root = root || (isRootArrayIfRootFalsy ? [] : {});
  let leaf = root;
  for (let i = 0; i < nestedPropsDef.length; i++) {
    const propDef = nestedPropsDef[i];
    const propKey = Object.keys(propDef)[0];
    const propDefault = propDef[propKey];
    leaf[propKey] = leaf[propKey] || propDefault;
    leaf = leaf[propKey];
  }
  return leaf;
}

/**
 * Clones an object deeply using the JSON API.
 *
 * @param {Object} obj The object to clone.
 * @return {Object} The cloned object.
 */
function cloneDeeplyJSON(obj) {
  return JSON.parse(JSON.stringify(obj));
}

/**
 * Tests whether the given value is a reference type or not.
 *
 * @param {*} value Any value which can be an object or a primitive type.
 * @return {boolean} True if the given value is a reference type, false otherwise.
 */
function isReferenceType(value) {
  return new Object(value) === value;
}

/**
 * Tests whether the given value is a primitive type or not.
 *
 * @param {*} value Any value which can be an object or a primitive type.
 * @return {boolean} True if the given value is a primitive type, false otherwise.
 */
function isPrimitiveType(value) {
  return new Object(value) !== value;
}

/**
 * Checks whether an object has a cyclic reference or not.
 *
 * @param {Object} obj The object to check for a cyclic reference.
 * @return {boolean} True if the object has a cyclic reference, false otherwise.
 */
function hasCyclicReference(obj) {
  const stackSet = [];
  let detected = false;

  function detect(obj) {
    if (detected) {
      return;
    }

    if (typeof obj !== "object") {
      return;
    }

    const indexOfObj = stackSet.indexOf(obj);
    if (indexOfObj !== -1) {
      detected = true;
      return;
    }

    stackSet.push(obj);
    for (const k in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, k)) {
        detect(obj[k]);
      }
    }

    stackSet.splice(indexOfObj, 1);
    return;
  }
  detect(obj);
  return detected;
}

/**
 * Converts a type to its string representation.
 *
 * @param {*} type A variable.
 * @return {string} The string representation of "type".
 */
function typeToStr(type) {
  return Object.prototype.toString.call(type);
}

/**
 * Clones an object deeply and returns the clone.
 *
 * @param {Object} object The object to clone.
 * @return {Object} The clone.
 * @throws {Error} If a circular reference if even only one property is of an unkown type
 *                 (this should never happen) or a circular reference is detected.
 */
function cloneObjDeeply(object) {
  const newObject = new object.constructor();
  for (const prop in object) {
    // If the property is defined on the prototype, ignore it. We don't want to assign it for each clone instance.
    if (!Object.prototype.hasOwnProperty.call(object, prop)) {
      continue;
    }

    const property = object[prop];
    if (isPrimitiveType(property)) {
      newObject[prop] = property;
    } else if (isReferenceType(property)) {
      if (!hasCyclicReference(property)) {
        const clone = cloneObjDeeply(property);
        newObject[prop] = clone;
      } else {
        throw new Error(
          "Circular reference detected inside of property '" +
            prop +
            "' (" +
            typeToStr(property) +
            ") in object (" +
            typeToStr(object) +
            ")"
        );
      }
    } else {
      throw new Error(
        "Oops! Unknown type for property '" +
          prop +
          "' (" +
          typeToStr(property) +
          ") in object (" +
          typeToStr(object) +
          ")"
      );
    }
  }
  return newObject;
}

/**
 * Deep object extension implementation.
 * Nothing is returned, but the destination object will be modified and merged with the source object
 * so that properties of the source object which are objects will recursively merge with the corresponding
 * destination property while the other properties with all the other types will replace the properties of the
 * destination object.
 * Note that this method should not be used for inheritance via the Prototypal Combination Inheritance pattern.
 * Also, this method doesn't perform a deep object cloning, it just extends the destinationObject by adding properties
 * it doesn't have in a deep way.
 *
 * @param {Object} destinationObject The destination object which will be modified and merged with the source object.
 * @param {Object} sourceObject The source object which will be used to extend the destination object.
 * @param {Object} [options] An object containing the options for the extension.
 *                           The currently available options are:
 *
 *                               - extendsArrays (boolean: false): Whether or not to extend nested arrays too (defaults to false);
 *
 * @return {undefined}
 */
function deepObjectExtend(
  destinationObject,
  sourceObject,
  options = {}
) {
  for (const property in sourceObject) {
    if (sourceObject[property] && isPlainObject(sourceObject[property])) {
      destinationObject[property] = destinationObject[property] || {};
      deepObjectExtend(
        destinationObject[property],
        sourceObject[property],
        options
      );
    } else if (
      options.extendArrays &&
      sourceObject[property] &&
      isArray(sourceObject[property])
    ) {
      destinationObject[property] = destinationObject[property] || [];
      deepObjectExtend(
        destinationObject[property],
        sourceObject[property],
        options
      );
    } else {
      destinationObject[property] = sourceObject[property];
    }
  }
}

/**
 * Deep object cloning extension implementation. If the source objects contain a property with a reference type, a clone object
 * of the same type of that property will be created and then merged with the property object of the destination object.
 *
 * @param {Object} destinationObject The destination object which will be modified and merged with the source object.
 * @param {...Object} sourceObject One or more objects which will be used to extend the destination object.
 * @return {undefined}
 */
function deepObjectCloningExtend(...args) {
  const destinationObject = args[0];
  let sourceObject;
  for (let i = 1; args[i]; i++) {
    sourceObject = args[i];
    for (const property in sourceObject) {
      if (sourceObject[property] && isPlainObject(sourceObject[property])) {
        destinationObject[property] = destinationObject[property] || {};
        deepObjectExtend(
          destinationObject[property],
          cloneObjDeeply(sourceObject[property])
        );
      } else {
        destinationObject[property] = sourceObject[property];
      }
    }
  }
}

/**
 * Extends a destination object with the provided source objects.
 *
 * @param {Object} destinationObj The destination object.
 * @param {...Object|Array} sourceObjects The source objects. If the last argument is an array containing one single truthy element,
 *                                        it will be treated as an options parameter and its single first truthy element will be treated as object
 *                                        containing the options for the extension.
 *                                        The currently available options are:
 *
 *                                            - extendsArrays (boolean: false): Whether or not to extend nested arrays too (defaults to false);
 *
 * @return {Object} The destination object "destinationObj" given as parameter after extension.
 */
function extend(destinationObj, ...sourceObjects) {
  let options = {};
  if (sourceObjects.length) {
    const last = sourceObjects.pop();
    if (isArray(last) && last.length === 1 && isPlainObject(last[0])) {
      options = last[0];
    } else {
      sourceObjects.push(last);
    }
  }
  for (const sourceObject of sourceObjects) {
    deepObjectExtend(destinationObj, sourceObject, options);
  }
  return destinationObj;
}

/**
 * Extends a destination object with the provided source objects.
 *
 * @param {Object} destinationObject The destination object.
 * @param {...*} rest The source objects with the last parameter being an array of rules,
 *                    each rule being a tuple array where the first element is an array of "ORed" property names (strings or numbers)
 *                    or regexes matching property names for which the corresponding values should be decorated
 *                    (or a single property name or regex matching a property name if the decoration should only happen on a single property),
 *                    and where the second element is a callback to execute for each value which is a value of a property
 *                    of a source object.
 *                    The callback has the following signature:
 *
 *                        (value: *, prop: string|number, parent: Object) => *|undefined
 *
 *                    The callback will receive the final value after extension, its associated property and the parent object
 *                    where that property is set with that value.
 *                    Its returned value will be used as the final value of the property for that object in "destinationObject".
 *
 *                    If the last parameter is not an array of rules, it will be treated as the last source object to use for the extension
 *                    (the "extend" function will be simply called under the hood without any decoration logic).
 * @return {Object} The destination object "destinationObject" given as parameter after extension and, if the callback is given
 *                  as the last parameter, after applying the given callback.
 */
function extendDecorate(destinationObject, ...rest) {
  const rules = rest[rest.length - 1];
  if (isArray(rules)) {
    rest.pop();
    const sourceObjects = rest;
    const initialRetValue = {};
    const matchedRulesMap = new Map();
    const callbacksMap = new Map();
    const paths = [];
    const mapKeys = (
      destinationObject,
      sourceObject,
      currentStack,
      currentPath
    ) => {
      for (const key in sourceObject) {
        currentStack.push({
          destinationObject,
          sourceObject,
          property: key,
          path: [...currentPath, key],
        });
      }
    };
    const matchRule = (rule, property) => {
      if (rule instanceof RegExp && typeof property === "string") {
        return property.match(rule);
      } else {
        return rule === property;
      }
    };
    const matchArrayRule = (arrayRule, property) => {
      for (const rule of arrayRule) {
        if (matchRule(rule, property)) {
          return true;
        }
      }
      return false;
    };
    const ruleMatches = (rule, property) => {
      if (isArray(rule)) {
        return matchArrayRule(rule, property);
      } else {
        return matchRule(rule, property);
      }
    };
    const matchRules = property => {
      if (!matchedRulesMap.has(property)) {
        const callbacks = [];
        for (const [rule, callback] of rules) {
          if (ruleMatches(rule, property)) {
            callbacks.push(callback);
          }
        }
        matchedRulesMap.set(property, callbacks);
      }
      return matchedRulesMap.get(property);
    };

    for (const sourceObject of sourceObjects) {
      const currentStack = [];
      const currentPath = [];
      mapKeys(destinationObject, sourceObject, currentStack, currentPath);
      while (currentStack.length) {
        const {
          destinationObject,
          sourceObject,
          property,
          path: currentPath,
        } = currentStack.pop();
        if (sourceObject[property] && isPlainObject(sourceObject[property])) {
          // "sourceObject[property]" is an object of class "Object".
          destinationObject[property] = isPlainObject(
            destinationObject[property]
          )
            ? destinationObject[property]
            : {};
          mapKeys(
            destinationObject[property],
            sourceObject[property],
            currentStack,
            currentPath
          );
        } else {
          // "sourceObject[property]" is not an object.
          destinationObject[property] = sourceObject[property];
        }
        const callbacks = matchRules(property);
        if (callbacks && callbacks.length) {
          if (!nestedTreeMapHas(callbacksMap, currentPath)) {
            paths.push([...currentPath]);
          }
          nestedTreeMapSet(
            callbacksMap,
            currentPath,
            callbacks.map(callback => retValue => path => {
              const value =
                retValue === initialRetValue
                  ? destinationObject[property]
                  : retValue;
              return callback(value, property, destinationObject, path);
            })
          );
        }
      }
    }

    // Decorating the final nested values.
    for (let i = paths.length - 1; i >= 0; i--) {
      const path = paths[i];
      const callbacks = nestedTreeMapGet(callbacksMap, path) || [];
      let retValue = initialRetValue;
      for (const callback of callbacks) {
        retValue = callback(retValue)(path);
      }
      if (retValue !== initialRetValue) {
        setNestedPropertyValue(destinationObject, path, retValue);
      }
    }

    return destinationObject;
  } else {
    return extend(destinationObject, ...rest);
  }
}

/**
 * Shallowly extends a destination object with the provided source objects (first dimension).
 *
 * @param {Object} destinationObject The destination object.
 * @param {...Object} sourceObjects The source objects.
 * @return {Object} The destination object "destinationObject" given as parameter after shallow extension.
 */
function shallowExtend(destinationObject, ...sourceObjects) {
  sourceObjects.map(obj =>
    Object.keys(obj).map(key => (destinationObject[key] = obj[key]))
  );
  return destinationObject;
}

/**
 * Like "Array.prototype.includes", but with type coercion.
 *
 * @param {Array} array The array.
 * @param {Anything} value The value.
 * @return {boolean} True if the value is included within the array (checking with type coercion`==`).
 */
function includesTypeCoercion(array, value) {
  for (const valueOfArray of array) {
    if (valueOfArray == value) {
      return true;
    }
  }
  return false;
}

/**
 * Tests whether a value is undefined or not.
 *
 * @param {*} value A value
 * @return {boolean} True value is undefined, false otherwise.
 */
function isUndefined(value) {
  return typeof value === "undefined";
}

/**
 * Tests if the given value is an int.
 *
 * @param {*} value The value.
 * @return {boolean} True if value is an int, false otherwise.
 */
function isInt(value) {
  return Number.isInteger(value);
}

/**
 * Tests if the given string is an integer string.
 *
 * @param {*} a The string.
 * @return {boolean} True if the given string is an integer string, false otherwise.
 */
function ctypeDigit(a) {
  return Boolean(a.match(/^[0-9]+$/));
}

/**
 * Tests if the given value is an int or an integer string.
 *
 * @param {*} a The value.
 * @return {boolean} True if the value is an int or an integer string, false otherwise.
 */
function isIntegerOrIntegerStr(a) {
  return Number.isInteger(a) || ctypeDigit(a);
}

/**
 * Finds the index of a value in an array without type juggling
 * (i.e. like "Array.prototype.indexOf", but using "==" for equality comparison).
 *
 * @param {Array} array An array.
 * @param {*} value A value.
 * @return {number} -1 if the value is not in array, otherwise the index of value in array.
 */
function findIndex(array, value) {
  return array.findIndex(el => el == value);
}

/**
 * Returns the first value of the first property of an object.
 *
 * @param {Object} obj The object.
 * @return {*} The value of the first property of the given object.
 */
function firstPropValue(obj) {
  let prop;
  for (prop in obj) {
    break;
  }
  return obj[prop];
}

/**
 * Tests if a value is strictly a boolean "true".
 *
 * @param {*} value A value.
 * @return {boolean} "true" if the value is a boolean "true", "false" otherwise.
 */
function isStrictlyTrue(value) {
  return value === true;
}

/**
 * Tests if a value is truthy or not.
 *
 * @param {*} value The value.
 * @return {boolean} "true" if the value is truthy (evaluates to boolean "true"), "false" otherwise.
 */
function isTruthy(value) {
  return Boolean(value);
}

/**
 * Tests if all the given values are truthy.
 *
 * @param {...*} values The values.
 * @return {boolean} "true" if and only if all the values are truthy.
 */
function allTruthy(...values) {
  return values.every(isTruthy);
}

/**
 * Tests if all the given values are not undefined.
 *
 * @param {...*} values The values.
 * @return {boolean} "true" if and only if all the values are not undefined.
 */
function allNotUndefined(...values) {
  return values.every(value => typeof value !== "undefined");
}

/**
 * Tests if a string is a valid JSON string.
 *
 * @param {string} str A string.
 * @return {boolean} "true" if the string represents a valid JSON string, "false" otherwise.
 */
function isJSONString(str) {
  try {
    JSON.parse(str);
  } catch (e) {
    return false;
  }
  return true;
}

/**
 * No-op function.
 *
 * @return {undefined}
 */
// eslint-disable-next-line @typescript-eslint/no-empty-function
function noOpFn() {}

/**
 * Tests if a partial object is a subset of another object.
 *
 * @param {Object} obj An object.
 * @param {Object} partialObj A partial object which may not have all the keys of "obj"
 *                            or may even have different keys, or keys with different values.
 * @return {boolean} False if "partialObj" has a key which is not in "obj",
 *                   or has at least one key which is also in "obj" but with a different value
 *                   (shallow comparison), true otherwise.
 */
function partialShallowEqual(obj, partialObj) {
  return (0,_compare__WEBPACK_IMPORTED_MODULE_0__.shallowEqual)(
    Object.keys(partialObj).reduce((carry, key) => {
      carry[key] = obj[key];
      return carry;
    }, {}),
    partialObj
  );
}

/**
 * Returns a shallow object diff, returning an object with two keys "objA" and "objB",
 * each containing an object with all the properties of one of the two objects which are not within
 * the other object, respectively.
 * If a property is on both objects but each object has a different value for that same property
 * (using shallow equality comparison), the returned property will be set on both objects with their
 * respective values.
 *
 * @param {Object} objA First object.
 * @param {Object} objB Second object.
 * @return {Object} An object containing the shallow diff, with two keys "objA" and "objB".
 */
function shallowObjectDiff(objA, objB) {
  const diff = {
    objA: {},
    objB: {},
  };
  if ((0,_compare__WEBPACK_IMPORTED_MODULE_0__.shallowEqual)(objA, objB)) {
    return diff;
  }
  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);
  for (let i = 0; i < keysA.length; i++) {
    const prop = keysA[i];
    if (!(0,_compare__WEBPACK_IMPORTED_MODULE_0__.objectPropEqual)(objA, objB, prop)) {
      diff.objA[prop] = objA[prop];
      if (hasOwnProperty.call(objB, prop)) {
        diff.objB[prop] = objB[prop];
      }
    }
  }
  for (let i = 0; i < keysB.length; i++) {
    const prop = keysB[i];
    if (!(0,_compare__WEBPACK_IMPORTED_MODULE_0__.objectPropEqual)(objB, objA, prop)) {
      diff.objB[prop] = objB[prop];
      if (hasOwnProperty.call(objA, prop)) {
        diff.objA[prop] = objA[prop];
      }
    }
  }
  return diff;
}

/**
 * Casts a value to a string.
 *
 * @param {*} v A value.
 * @return {string} The string representation of the value.
 */
function str(v) {
  return "" + v;
}

/**
 * Maps an object, executing a function on each of its properties
 * returning a new mapped object.
 *
 * @param {Object} obj The object to map.
 * @param {Function} fn The function to use for the mapping.
 * @return {Object} The new mapped object.
 */
const mapObject = (obj, fn) =>
  Object.fromEntries(
    Object.entries(obj).map(([key, value], index) => [
      key,
      fn(value, key, index),
    ])
  );

/**
 * Maps an array to an object.
 *
 * @param {Array} arr An array.
 * @param {Function} fn A function receiving the current value, its index as well as the whole array "arr"
 *                      as parameters returning a tuple with the key at index 0 and the value at index 1 to set on the object.
 * @returns {Object} The array mapped to an object.
 */
const mapToObject = (arr, fn) => {
  let res;
  return arr.reduce(
    (carry, ...rest) =>
      ((res = fn(...rest)) && false) ||
      ((carry[res[0]] = res[1]) && false) ||
      carry,
    {}
  );
};

/**
 * Selects the truthy properties of an object or the properties of an object
 * passing a test specified with a callback function.
 *
 * @param {Object} obj The input object.
 * @param {Function} fn A function which will receive two parameters:
 *
 *                          - value: The current value of the input object for a given property;
 *                          - prop: The name of the current property of the input object.
 *
 *                      The function will have to return a boolean "true" indicating that this value
 *                      and property has to be included in the returned object, or "false" otherwise.
 *
 * @return {Object} An object having only the properties which passed the test
 *                  implemented by the "fn" callback function.
 */
const propSelection = (obj, fn = isTruthy) =>
  Object.keys(obj).reduce((carry, key) => {
    if (fn(obj[key], key)) {
      carry[key] = obj[key];
    }
    return carry;
  }, {});

/**
 * Returns all the properties of the given object traversing its prototype chain.
 *
 * @param {Object} obj The object.
 * @param {Object} [options] An object with options.
 * @param {?Object} [options.stopAtPrototype] The prototype in the chain at which to stop the traversing.
 *                                            Defaults to null, in which case the whole prototype chain will be traversed.
 * @param {boolean} [options.stopAtPrototypeInclude] Whether or not to include the properties of the given prototype at which to stop.
 *                                                   Works only if "stopAtPrototype" is set to a valid prototype object in the prototype chain
 *                                                   of "obj".
 *                                                   Defaults to true, in which case the properties of the prototype at which to stop will be included
 *                                                   in the returned array.
 * @return {string[]} An array of containing the names of the properties.
 */
function prototypeChainProperties(
  obj,
  { stopAtPrototype = null, stopAtPrototypeInclude = true } = {}
) {
  let current = obj;
  const map = {};
  let isStopPrototype = false;
  let stop = false;
  while (!stop && current && (!isStopPrototype || stopAtPrototypeInclude)) {
    if (isStopPrototype) {
      stop = true;
    }
    const properties = Object.getOwnPropertyNames(current);
    properties.map(property => (map[property] = true));
    current = Object.getPrototypeOf(current);
    if (stopAtPrototype) {
      isStopPrototype = current === stopAtPrototype;
    }
  }
  const properties = Object.keys(map);
  return properties;
}

/**
 * Defines an object's property with a getter and an optional setter.
 *
 * @param {Object} obj An object (may be a prototype).
 * @param {string} propname The property name.
 * @param {Function} getfn Getter function.
 * @param {Function|undefined} [setfn] Setter function.
 * @return {undefined}
 */
function prop(obj, propname, getfn, setfn = void 0) {
  const propObj = {};
  propObj[propname] = {
    get: getfn,
    set: setfn,
  };
  Object.defineProperties(obj, propObj);
}

/**
 * Defines a property on an object.
 *
 * @param {Object} o An object.
 * @param {string} p The property to define.
 * @param {Object} descriptor Optional object containing the descriptor's properties to use to override the default properties.
 * @return {Object} The object that was passed to the function.
 */
function defineProperty(o, p, descriptor = {}) {
  return Object.defineProperty(o, p, {
    configurable: false,
    enumerable: false,
    writable: true,
    ...descriptor,
  });
}

/**
 * Assigns the properties of the given source objects to the target object.
 *
 * @source https://stackoverflow.com/questions/39515321/spread-operator-issues-with-property-accessors-getters#answer-39521418
 *
 * @param {Object} target The target object.
 * @param {...Object} sources The source objects.
 * @return {Object} The target object.
 */
function completeObjectAssign(target, ...sources) {
  sources.forEach(source => {
    const descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});
    // By default, Object.assign copies enumerable Symbols too.
    Object.getOwnPropertySymbols(source).forEach(sym => {
      const descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isValidDate": () => (/* binding */ isValidDate),
/* harmony export */   "isValidDateTimeStr": () => (/* binding */ isValidDateTimeStr),
/* harmony export */   "utcDate": () => (/* binding */ utcDate)
/* harmony export */ });
/* harmony import */ var _string__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./string */ "./src/modules/string.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */



/**
 * Tests if the given value is a valid date.
 *
 * @param {*} value The value to test.
 * @return {boolean} True if it is a valid date, false otherwise.
 */
function isValidDate(value) {
  return (
    Object.prototype.toString.call(value) === "[object Date]" &&
    !isNaN(value.getTime())
  );
}

/**
 * Tests if the given string is a valid datetime string (e.g. in ISO "YYYY-MM-DD HH:ii:ss" format).
 *
 * @param {string} str The given string.
 * @return {boolean} True if it is a valid datetime string, false otherwise.
 */
function isValidDateTimeStr(str) {
  return isValidDate(new Date(str));
}

/**
 * Returns a UTC datetime in ISO `YYYY-MM-DD HH:ii:ss` format.
 *
 * @param {Object} [options] An optional object of options.
 * @param {boolean} [options.Y] True to return the year of the UTC datetime. Defaults to true.
 * @param {boolean} [options.m] True to return the month of the UTC datetime. Defaults to true.
 * @param {boolean} [options.d] True to return the day of the UTC datetime. Defaults to true.
 * @param {boolean} [options.H] True to return the hours of the UTC datetime. Defaults to true.
 * @param {boolean} [options.i] True to return the minutes of the UTC datetime. Defaults to true.
 * @param {boolean} [options.s] True to return the seconds of the UTC datetime. Defaults to true.
 * @param {Date|string} [options.date] A date or a string that will be passed to the `Date` constructor
 *                                     which represents the date on which to compute and return the UTC date.
 * @return {string} The UTC datetime.
 */
const utcDate = ({
  Y = true,
  m = true,
  d = true,
  H = true,
  i = true,
  s = true,
  date = void 0,
} = []) => {
  const finalDate = date ? new Date(date) : new Date();
  const year = finalDate.getUTCFullYear();
  const month = (finalDate.getUTCMonth() + 1 + "").padStart(2, "0");
  const day = (finalDate.getUTCDate() + "").padStart(2, "0");
  const hours = (finalDate.getUTCHours() + "").padStart(2, "0");
  const minutes = (finalDate.getUTCMinutes() + "").padStart(2, "0");
  const seconds = (finalDate.getUTCSeconds() + "").padStart(2, "0");

  const UTCDate = (0,_string__WEBPACK_IMPORTED_MODULE_0__.trim)(
    (0,_string__WEBPACK_IMPORTED_MODULE_0__.trim)(
      `${Y ? year : ""}-${m && (Y || d || (!Y && !d)) ? month : ""}-${
        d ? day : ""
      }`,
      " -"
    ) +
      " " +
      (0,_string__WEBPACK_IMPORTED_MODULE_0__.trim)(
        `${H ? hours : ""}:${i && (H || s || (!H && !s)) ? minutes : ""}:${
          s ? seconds : ""
        }`,
        " :"
      ),
    " "
  );

  let finalUTCDate = UTCDate.replace("--", "-");
  finalUTCDate = finalUTCDate.replace("::", ":");

  return finalUTCDate;
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "_": () => (/* binding */ _),
/* harmony export */   "proceedCallingFn": () => (/* binding */ proceedCallingFn),
/* harmony export */   "curry": () => (/* binding */ curry),
/* harmony export */   "POJOCurry": () => (/* binding */ POJOCurry),
/* harmony export */   "compose": () => (/* binding */ compose),
/* harmony export */   "pipe": () => (/* binding */ pipe),
/* harmony export */   "pick": () => (/* binding */ pick),
/* harmony export */   "liftBinaryFn": () => (/* binding */ liftBinaryFn),
/* harmony export */   "juxt": () => (/* binding */ juxt),
/* harmony export */   "converge": () => (/* binding */ converge),
/* harmony export */   "execIfPOJOHas": () => (/* binding */ execIfPOJOHas),
/* harmony export */   "execWithExistentProps": () => (/* binding */ execWithExistentProps),
/* harmony export */   "forGen": () => (/* binding */ forGen),
/* harmony export */   "flatten": () => (/* binding */ flatten),
/* harmony export */   "flattenDeep": () => (/* binding */ flattenDeep),
/* harmony export */   "cartesianProduct": () => (/* binding */ cartesianProduct),
/* harmony export */   "identityFn": () => (/* binding */ identityFn),
/* harmony export */   "identityArgsFn": () => (/* binding */ identityArgsFn),
/* harmony export */   "chain": () => (/* binding */ chain)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/* harmony import */ var _array__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./array */ "./src/modules/array.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions for functional programming.
 */




/**
 * @type {string}
 */
const JSUtlCurryPlaceholderProp = "JSUtlCurryPlaceholderPropRPecoyYmCYqZ2lE";

/**
 * Curry function placeholder.
 *
 * @type {Object}
 */
const _ = {
  [JSUtlCurryPlaceholderProp]: true,
};

/**
 * @type {string}
 */
const JSUtlProceedCallingFnProp = "JSUtlProceedCallingFnPropRBmGaAgOCgftF9t";

/**
 * Return value of "onFnCall" to call the curried function and return its value.
 *
 * @type {Object}
 */
const proceedCallingFn = {
  [JSUtlProceedCallingFnProp]: true,
};

/**
 * Curries a function.
 *
 * @see https://medium.com/@kj_huang/implementation-of-lodash-curry-function-8b1024d71e3b
 *
 * @param {Function} fn A function to curry in order to return the curried version of the function.
 * @param {Object} [obj] An optional object with further properties to tweak the currying behaviour
 *                       and execute code while collecting the arguments of the curried function.
 * @param {number|undefined} [obj.arity] The arity of the function, i.e. its number of arguments.
 *                                       If omitted, "fn.length" will be used.
 * @param {Function|undefined} [obj.onEffectiveArgAdded] An optional callback to execute whenever a new effective argument
 *                                                       (not a placeholder) is added to the curried function.
 *                                                       The callback will receive an object with the following properties as argument:
 *
 *                                                           - addedArg: The effective argument added;
 *                                                           - args: An array with all the previously arguments collected so far
 *                                                                   without considering "addedArg";
 *                                                           - fn: The function "fn";
 *                                                           - curriedFn: The current curried function;
 *
 *                                                       The return value of the function is ignored.
 * @param {Function|undefined} [obj.onPlaceholder] An optional callback to execute whenever a new placeholder is added to the curried function.
 *                                                 The callback will receive an object with the following properties as argument:
 *
 *                                                     - args: An array with all the previously arguments collected so far
 *                                                             without considering "addedArg";
 *                                                     - fn: The function "fn";
 *                                                     - curriedFn: The current curried function;
 *
 *                                                 The return value of the function is ignored.
 * @param {Function|undefined} [obj.onFnCall] An optional callback to execute just before calling the "fn" function
 *                                            (i.e. when the "fn" function is ready to be called and all its arguments have been collected).
 *
 *                                            The callback will receive an object with the following properties as argument:
 *
 *                                                - args: The array of the effective arguments of the "fn" function;
 *                                                - fn: The function "fn" which was initially passed to "curry";
 *                                                - curriedFn: The current curried function;
 *
 *                                            This way, the code of the callback may decide what to do and may even call the function on its own
 *                                            and prevent the call from the caller side (i.e. within the "curry" function).
 *
 *                                            The callback must explicitly tell "curry" to call the function by returing "proceedCallingFn".
 *                                            If the callback returns any other value, then "fn" will not be called in "curry" and the return value
 *                                            of this callback will be returned.
 * @param {Function|undefined} [obj.onCurriedFnFirstCall] An optional callback to execute only the first time when the first curried function returned by "curry"
 *                                                        is invoked for the very first time with the very first argument or arguments.
 *
 *                                                        The callback will receive an object with the following properties as argument:
 *
 *                                                            - addedArgs: The arguments provided by the caller;
 *                                                            - fn: The "fn" function;
 *                                                            - curriedFn: The current curried function;
 *
 * @param {Function|undefined} [obj.onNewCurriedFn] An optional callback to execute initially and each time a new curried function is going to be returned.
 *
 *                                                  The callback will an object with the following properties as argument:
 *
 *                                                      - curriedFn: The current curried function (same as "newCurriedFn" when this callback is invoked
 *                                                                   for the very first time);
 *                                                      - newCurriedFn: The new curried function (will be the same as "curriedFn" when this callback is invoked
 *                                                                      for the very first time);
 *
 *
 * @return {Function} The curried version of the function.
 */
const curry = (
  fn,
  {
    arity = void 0,
    onEffectiveArgAdded = void 0,
    onPlaceholder = void 0,
    onFnCall = void 0,
    onCurriedFnFirstCall = void 0,
    onNewCurriedFn = void 0,
  } = {}
) => {
  let curriedFnFirstCall = true;

  const expectedNumberOfArgs = typeof arity !== "undefined" ? arity : fn.length;
  const nextParameterIndex = 0;
  const placeholdersIndices = [];

  const curriedInner = (
    expectedNumberOfArgs,
    nextParameterIndex,
    placeholdersIndices,
    ...args
  ) =>
    function curriedFn(...addedArgs) {
      let newExpectedNumberOfArgs = expectedNumberOfArgs;
      let newNextParameterIndex = nextParameterIndex;
      let newPlaceholdersIndices = null;
      let argsRequiredChange = false;
      curriedFnFirstCall &&
        ((onCurriedFnFirstCall &&
          onCurriedFnFirstCall({ addedArgs, fn, curriedFn })) ||
          true) &&
        (curriedFnFirstCall = false);
      let numberOfConsumablePlaceholders = placeholdersIndices.length;
      for (const addedArg of addedArgs) {
        !argsRequiredChange && (args = [...args]);
        argsRequiredChange = true;
        // "addedArg" may be either a placeholder or an effective argument.
        const isPlaceholder = addedArg
          ? addedArg[JSUtlCurryPlaceholderProp] === _[JSUtlCurryPlaceholderProp]
          : false;
        if (numberOfConsumablePlaceholders > 0 && !isPlaceholder) {
          // Argument is an effective argument consuming a previously set placeholder.
          onEffectiveArgAdded &&
            onEffectiveArgAdded({ addedArg, args, fn, curriedFn });
          let argIndex;
          if (newPlaceholdersIndices === null) {
            const [firstIndex, ...rest] = placeholdersIndices;
            argIndex = firstIndex;
            newPlaceholdersIndices = rest;
          } else {
            argIndex = newPlaceholdersIndices.shift();
          }
          args[argIndex] = addedArg;
          numberOfConsumablePlaceholders--;
          newExpectedNumberOfArgs--;
        } else {
          if (isPlaceholder) {
            // Argument is a new placeholder.
            if (newPlaceholdersIndices === null) {
              newPlaceholdersIndices = placeholdersIndices.concat(
                newNextParameterIndex
              );
            } else {
              newPlaceholdersIndices.push(newNextParameterIndex);
            }
            onPlaceholder && onPlaceholder({ args, fn, curriedFn });
          } else {
            // Argument is an effective argument.
            newExpectedNumberOfArgs--;
            onEffectiveArgAdded &&
              onEffectiveArgAdded({ addedArg, args, fn, curriedFn });
          }
          args[newNextParameterIndex] = addedArg;
          newNextParameterIndex++;
        }
      }
      // eslint-disable-next-line @typescript-eslint/no-use-before-define
      return curried.call(
        null,
        curriedFn,
        newExpectedNumberOfArgs,
        newNextParameterIndex,
        newPlaceholdersIndices === null
          ? [...placeholdersIndices]
          : newPlaceholdersIndices,
        ...args
      );
    };

  const curried = (
    curriedFn,
    expectedNumberOfArgs,
    nextParameterIndex,
    placeholdersIndices,
    ...args
  ) => {
    if (expectedNumberOfArgs <= 0) {
      if (onFnCall) {
        const shouldCallCurriedFn = onFnCall({ args, fn, curriedFn });
        if (
          shouldCallCurriedFn &&
          shouldCallCurriedFn[JSUtlProceedCallingFnProp] ===
            proceedCallingFn[JSUtlProceedCallingFnProp]
        ) {
          return fn(...args);
        } else {
          return shouldCallCurriedFn;
        }
      } else {
        return fn(...args);
      }
    } else {
      const newCurried = curriedInner(
        expectedNumberOfArgs,
        nextParameterIndex,
        placeholdersIndices,
        ...args
      );
      onNewCurriedFn && onNewCurriedFn({ curriedFn, newCurriedFn: newCurried });
      return newCurried;
    }
  };

  const newCurried = curriedInner(
    expectedNumberOfArgs,
    nextParameterIndex,
    placeholdersIndices
  );
  onNewCurriedFn &&
    onNewCurriedFn({ curriedFn: newCurried, newCurriedFn: newCurried });
  return newCurried;
};

/**
 * Curries a POJO function, i.e. a function having only a single POJO (Plain Old JavaScript Object)
 * as parameter (a function with named arguments).
 *
 * Each object passed to the returned curried function will be merged with the final object
 * to pass to the function "fn" when finally calling it.
 *
 * @param {Function} fn A function to curry in order to return the curried version of the function.
 * @param {Object} [obj] An optional object with further properties to tweak the currying behaviour
 *                       and execute code while collecting the POJO objects which will construct
 *                       the final POJO object to pass to the curried function after plugging the curried POJO function.
 * @param {string} [obj.plugPropertyName] The name of the property which instructs that it's time to call the function.
 * @param {boolean} [obj.plugPropertyMustBeTruthy] By default, it is enough that the property with "obj.plugPropertyName" name
 *                                                 is set on the object passed to the curried function to instruct it to call
 *                                                 "fn".
 *                                                 If this property is set to "true", the property with "plugPropertyName" name
 *                                                 will also have to be truthy.
 * @param {Function} [obj.onPOJOArgMerged] An optional callback to execute right after merging the next POJO argument with the so far accumulated POJO object.
 *                                         The callback will an object with the following properties as argument:
 *
 *                                             - POJOArg: The given POJO argument;
 *                                             - POJO: the so far merged POJO object merged with the given "POJOArg";
 *                                             - fn: The "fn" function;
 *                                             - curriedFn: The current curried function;
 *
 * @param {Function} [obj.onFnCall] An optional callback to execute just before calling the "fn" function
 *                                  (i.e. when the "fn" function is ready to be called and has been plugged and all
 *                                  of its POJO object argument properties have been collected).
 *
 *                                  The callback will receive an object with the following properties as argument:
 *
 *                                      - POJO: The callback will receive the function "fn" POJO argument (an object) as its first argument;
 *                                      - fn: The "fn" function;
 *                                      - curriedFn: The current curried function;
 *
 *                                  This way, the code of the callback may decide what to do and may even call the function on its own
 *                                  and prevent the call from the caller side (i.e. within the "POJOCurry" function).
 *
 *                                  The callback must explicitly tell "POJOCurry" to call the function by returing "proceedCallingFn"
 *                                  If the callback returns any other value, then "fn" will not be called in "POJOCurry" and the return value
 *                                  of this callback will be returned.
 * @param {Function|undefined} [obj.onCurriedFnFirstCall] An optional callback to execute only the first time when the first curried function returned by "curry"
 *                                                        is invoked for the very first time with the very first POJO argument.
 *
 *                                                        The callback will receive an object with the following properties as argument:
 *
 *                                                            - POJOArg: The given POJO argument yet to merge with the internal final POJO;
 *                                                            - fn: The "fn" function;
 *                                                            - curriedFn: The current curried function;
 *
 * @param {Function|undefined} [obj.onNewCurriedFn] An optional callback to execute initially and each time a new curried function is going to be returned.
 *
 *                                                  The callback will receive an object with the following properties as argument:
 *
 *                                                      - curriedFn: The current curried function (same as "newCurriedFn" when this callback is invoked
 *                                                                   for the very first time);
 *                                                      - newCurriedFn: The new curried function (will be the same as "curriedFn" when this callback is invoked
 *                                                                      for the very first time);
 *
 * @return {Function} The curried version of the function.
 */
const POJOCurry = (
  fn,
  {
    plugPropertyName = "plugCurried",
    plugPropertyMustBeTruthy = false,
    onPOJOArgMerged = void 0,
    onFnCall = void 0,
    onCurriedFnFirstCall = void 0,
    onNewCurriedFn = void 0,
  } = {}
) => {
  const POJO = {};
  let curriedFnFirstCall = true;

  const curriedInner = accPOJO =>
    function curriedFn(POJOArg) {
      curriedFnFirstCall &&
        ((onCurriedFnFirstCall &&
          onCurriedFnFirstCall({ POJOArg, fn, curriedFn })) ||
          true) &&
        (curriedFnFirstCall = false);
      let POJO = Object.assign({}, accPOJO, POJOArg || {});
      if (
        Object.prototype.hasOwnProperty.call(POJO, plugPropertyName) &&
        (!plugPropertyMustBeTruthy || POJO[plugPropertyName])
      ) {
        const { [plugPropertyName]: POJOArgIgnoredProperty, ...rest } = POJOArg;
        const { [plugPropertyName]: POJOIgnoredProperty, ...POJORest } = POJO;
        POJO = POJORest;
        if (!(0,_core__WEBPACK_IMPORTED_MODULE_0__.isObjectEmpty)(rest)) {
          onPOJOArgMerged &&
            onPOJOArgMerged({ POJOArg: rest, POJO, fn, curriedFn });
        }
        let shouldCallCurriedFn = true;
        let ret = void 0;
        if (onFnCall) {
          ret = onFnCall({ POJO, fn, curriedFn });
          shouldCallCurriedFn = ret
            ? ret[JSUtlProceedCallingFnProp] ===
              proceedCallingFn[JSUtlProceedCallingFnProp]
            : false;
        }

        if (shouldCallCurriedFn) {
          return fn(POJO);
        } else {
          return ret;
        }
      } else {
        onPOJOArgMerged && onPOJOArgMerged({ POJOArg, POJO, fn, curriedFn });
        const newCurried = curriedInner(POJO);
        onNewCurriedFn &&
          onNewCurriedFn({ curriedFn, newCurriedFn: newCurried });
        return newCurried;
      }
    };

  const newCurried = curriedInner(POJO);
  onNewCurriedFn &&
    onNewCurriedFn({ curriedFn: newCurried, newCurriedFn: newCurried });
  return newCurried;
};

/**
 * A utility function which composes functions or higher-order functions.
 *
 * @param {...Function|...Function[]} fns A list of functions or higher-order functions or arrays of functions
 *                                        (arrays will be flattened) to compose.
 * @return {Function} A function composed of all the functions or higher-order functions
 *                    used for composition.
 */
const compose = (...fns) => (...args) => {
  let outerArgs = args;
  let hoFn = void 0;
  fns = fns.flat(1);
  for (let i = fns.length - 1; i >= 0; i--) {
    const fn = fns[i];
    hoFn = fn(...outerArgs);
    outerArgs = [hoFn];
  }
  return hoFn;
};

/**
 * A utility function which pipes functions.
 *
 * @param {...Function|...Function[]} fns A list of functions or arrays of functions (arrays will be flattened)
 *                                        to pipe.
 * @return {Function} A function representing the pipe.
 */
const pipe = (...fns) => (...args) => {
  fns = fns.flat(1);
  return fns.length ? fns.reduce((arg, fn) => [fn(...arg)], args)[0] : void 0;
};

/**
 * Returns a function which lets picking the properties of an object.
 *
 * @param {...string|...number} props The properties to pick.
 * @return {Function} A function which if called picks the "props" properties from its argument object
 *                    and returns a new object with the picked properties.
 */
const pick = (...props) => o =>
  props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});

/**
 * Lifts two functions using a binary function which takes their results as arguments.
 *
 * @param {Function} binaryFn A binary function (i.e. a function which takes two arguments).
 * @return {Function} A higher-order function which has to be called with the first function as argument ("firstFn")
 *                    and returns another higher-order function which has to be called with the second function as argument ("secondFn").
 *                    Then, the returned function will take the parameters to pass to the two functions ("firstFn" and "secondFn")
 *                    and return the result of calling "binaryFn" with the result of those functions given as parameters.
 */
const liftBinaryFn = binaryFn => firstFn => secondFn => (...params) =>
  binaryFn(firstFn(...params), secondFn(...params));

/**
 * Applies an array of functions to a list of values.
 *
 * @param {Function[]} fns An array of functions.
 * @return {Function} A function which if called with a list of values, will pass the list to each function of "fns"
 *                    and return an array with the values after applying each of the original "fns" to its parameters.
 */
const juxt = fns => (...values) => fns.map(fn => fn(...values));

/**
 * Converges a multi-arg function.
 *
 * @param {Function} multiArgFn A multi-arg function.
 * @param {Function[]} fns An array of functions to converge.
 *                         Each function will receive the parameter passed to the function returned
 *                         by this higher-order function (i.e. "params").
 * @return {Function} A function which, if called, will pass its arguments to each of the functions in "fns"
 *                    and pass each result of those functions to the multi-arg function "multiArgFn",
 *                    returning its result.
 */
const converge = (multiArgFn, fns) => (...params) =>
  multiArgFn(...fns.map(fn => fn(...params)));

/**
 * Executes a callback if a POJO object has a property.
 *
 * @param {Object} POJO A POJO object.
 * @return {(prop: string|number) => (fn: Function) => *} A function which receives the property
 *                                                        and returns and returns a function receiving the callback
 *                                                        function ("fn") to execute.
 */
const execIfPOJOHas = POJO => prop => fn =>
  Object.prototype.hasOwnProperty.call(POJO, prop) && fn(POJO[prop], POJO);

/**
 * Executes a callback with the existent properties of an object.
 *
 * @param {...string|...number} props The properties to check for existence.
 * @return {(o: Object) => (fn: (existentProps: string[]|number[]) => *) => *} A function which receives the POJO object for which to check for the given properties
 *                                                                             and returns a function receiving a callback which will receive the existent properties
 *                                                                             of the object as parameter.
 */
const execWithExistentProps = (...props) => o => fn =>
  fn(props.filter(prop => Object.prototype.hasOwnProperty.call(o, prop)));

/**
 * Loops through the values of a generator and returns an array with its mapped
 * values mapped with the given callback.
 *
 * @param {GeneratorFunction} gen A generator function.
 * @return {(args: ...*) => (fn: (val: *) => *) => Array} A function which takes the arguments for the generator and returns
 *                                                        another function which takes the callback to use to map each
 *                                                        value of the generator returning an array with all the mapped values of the generator.
 */
const forGen = gen => (...args) => fn => {
  const generator = gen(...args);
  const arr = [];
  for (const value of generator) {
    const res = fn(value);
    arr.push(res);
  }
  return arr;
};

/**
 * Flattens an array (its first dimension, at most).
 *
 * @param {Array} arr An array.
 * @return {Array} A new flattened array.
 */
const flatten = arr => Array.prototype.concat.apply([], arr);

/**
 * Flattens an array with any dimension.
 *
 * @param {Array} arr An array.
 * @param {number} dimension The flattening dimension (defaults to 1, but can be greater, even "Infinity").
 * @return {Array} The flattened array.
 */
const flattenDeep = (arr, dimension = 1) => {
  return dimension > 0
    ? arr.reduce(
        (acc, val) =>
          acc.concat((0,_core__WEBPACK_IMPORTED_MODULE_0__.isArray)(val) ? flattenDeep(val, dimension - 1) : val),
        []
      )
    : (0,_array__WEBPACK_IMPORTED_MODULE_1__.arrayOrArrayLike)(arr);
};

/**
 * Computes the cartesian product of the given sets.
 *
 * @param  {...Array} sets The sets to use to compute the cartesian product.
 * @return {Array} The cartesian product of the given sets.
 */
const cartesianProduct = (...sets) =>
  sets.reduce((acc, set) => flatten(acc.map(x => set.map(y => [...x, y]))), [
    [],
  ]);

/**
 * Identity function.
 *
 * @see https://en.wikipedia.org/wiki/Identity_function
 *
 * @param {*} value Any value.
 * @return {*} The same passed value.
 */
const identityFn = value => value;

/**
 * Identity function for multiple args returning an array of those args.
 *
 * @param  {...*} args The args.
 * @return {Array} The same args returned in an array.
 */
const identityArgsFn = (...args) => args;

/**
 * @type {Function}
 */
const chainLink = (fn, next) => args =>
  fn(args, next && ((...args) => next(args)));

/**
 * A higher-order function to create a chain of functions following the Chain of Responsibility design pattern.
 *
 * @param {...Function|...Function[]} fns A list of functions or higher-order functions or arrays of functions
 *                                        (arrays will be flattened) to chain.
 * @return {Function} A function representing the chain of the given functions which, if called, will return the result of the chain.
 *                    Each function will receive the next function as its last parameter.
 */
const chain = (...fns) => (...args) => {
  fns = fns.flat(1);
  const chainFn = fns.reduceRight((nextChainLink, fn) => {
    return chainLink(fn, nextChainLink);
  }, void 0);
  return chainFn(args);
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "googleMapBestZoomLevelFromBounds": () => (/* binding */ googleMapBestZoomLevelFromBounds)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions related to Google.
 */

/**
 * Determines the best zoom level for a Google map.
 *
 * @param {google.maps.LatLngBounds} bounds The bounds.
 * @param {Object} mapDim JS POJO with the properties height and width.
 * @param {number} mapDim.height The height of the map's div.
 * @param {number} mapDim.width The width of the map's div.
 * @return {number} The best zoom level.
 */
function googleMapBestZoomLevelFromBounds(bounds, mapDim) {
  const WORLD_DIM = { height: 256, width: 256 };
  const ZOOM_MAX = 21;

  function latRad(lat) {
    const sin = Math.sin((lat * Math.PI) / 180);
    const radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
    return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
  }

  function zoom(mapPx, worldPx, fraction) {
    return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2);
  }

  const ne = bounds.getNorthEast();
  const sw = bounds.getSouthWest();

  const latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI;

  const lngDiff = ne.lng() - sw.lng();
  const lngFraction = (lngDiff < 0 ? lngDiff + 360 : lngDiff) / 360;

  const latZoom = zoom(mapDim.height, WORLD_DIM.height, latFraction);
  const lngZoom = zoom(mapDim.width, WORLD_DIM.width, lngFraction);

  return Math.min(latZoom, lngZoom, ZOOM_MAX);
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "stringHashArray": () => (/* binding */ stringHashArray),
/* harmony export */   "hashString": () => (/* binding */ hashString),
/* harmony export */   "onePassStringHash": () => (/* binding */ onePassStringHash),
/* harmony export */   "intSumHash": () => (/* binding */ intSumHash)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Hashing-related utility functions.
 */

/**
 * Computes a hash of an array of strings (the order of strings does not matter).
 *
 * NOTE: An array with duplicate values given as parameter to this function
 *       may yield to a hash which would collide with other hashes computed
 *       on different arrays with this same function.
 *       Therefore is on behalf of the caller to be sure that "array" contains
 *       unique strings.
 *
 * @param {string[]} array An array of strings.
 * @return {number} A number representing the hash code of the array.
 */
function stringHashArray(array) {
  let code = 0;
  for (let i = 0; i < array.length; i++) {
    let n = 0;
    for (let j = 0; j < array[i].length; j++) {
      n = (n * 251) ^ array[i].charCodeAt(j);
    }
    code ^= n;
  }
  return code;
}

/**
 * Returns the hash of a string.
 *
 * @see https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript#answer-7616484
 *
 * @param {string} str The string.
 * @return {number} The hash code of the string, represented as a number.
 */
const hashString = str => {
  let hash = 0,
    i,
    chr;
  if (str.length === 0) {
    return hash;
  }
  for (i = 0; i < str.length; i++) {
    chr = str.charCodeAt(i);
    hash = (hash << 5) - hash + chr;
    hash |= 0; // Convert to 32 bit integer.
  }
  return hash;
};

/**
 * A one-pass algorithm to compute the hash of a series of unique strings incrementally.
 *
 * NOTE: Duplicate values given as parameter to this function
 *       may yield to a hash which would collide with other hashes computed
 *       on different string series with this same function.
 *       Therefore is on behalf of the caller to be sure that the series of strings will be unique
 *       while calling this function incrementally.
 *
 * @param {string} str The string.
 * @param {number} [hash] The previous hash computed with this same function if this call is the continuation
 *                        of the unique string series.
 * @return {number} The next hash.
 */
function onePassStringHash(str, hash = 0) {
  let nextHash = hash;
  let n = 0;
  for (let j = 0; j < str.length; j++) {
    n = (n * 251) ^ str.charCodeAt(j);
  }
  nextHash ^= n;
  return nextHash;
}

/**
 * Given a sequence of integers, computes the hash of their sum so that two different sequences
 * will have the same hash if the sum of their integers will be the same (the overall sum of the sequences may be higher than `Number.MAX_SAFE_INTEGER`).
 *
 * @see https://stackoverflow.com/questions/69749629/hash-function-that-returns-the-same-hash-for-a-sum-even-if-different-terms-lead/69749873
 *
 * Example:
 *
 * ```
 * intSumHash([1, 2, 3, 4, 5, 6]); // 21
 * intSumHash([1, 2, 3, 4, 5, 6]) === intSumHash([2, 3, 1, 4, 6, 5]); // true
 * intSumHash([1, 2, 3, 4, 5, 6]) === intSumHash([5, 1, 10, 4, 1]); // true
 * intSumHash([1, 2, 3, 4, 5, 6]) === intSumHash([21]); // true
 * intSumHash([1, 2, 3, 4, 5, 6]) === intSumHash([7, 7, 7]); // true
 *
 * intSumHash([1, 2]); // 3
 *
 * const LARGE_PRIME = 999999999989;
 * intSumHash([4504 * LARGE_PRIME + 1, 4504 * LARGE_PRIME + 2]); // 800745160017
 *
 * intSumHash([Number.MAX_SAFE_INTEGER - 1, Number.MAX_SAFE_INTEGER - 2, Number.MAX_SAFE_INTEGER - 90, 10, 13]); // 209
 * intSumHash([Number.MAX_SAFE_INTEGER - 2, Number.MAX_SAFE_INTEGER - 90, 10, Number.MAX_SAFE_INTEGER - 1, 13]); // 209
 * intSumHash([209, -10, 2, 3, 5]); // 209
 * intSumHash([1, 2, 3, 20, 209 - (20 + 3 + 2 + 1)]); // 209
 * intSumHash([4, 1, 2, 1, 1, 1, 20, 209 - 10, -86, 70, -25, 1, 7, 13]); // 209
 *
 * intSumHash([9007597764421056, -10, 2, 3, 5]); // 398509680158
 * intSumHash([1, 2, 3, 20, 9007597764421056 - (20 + 3 + 2 + 1)]); // 398509680158
 * intSumHash([4, 1, 2, 1, 1, 1, 20, 9007597764421056 - 10, -86, 70, -25, 1, 7, 13]); // 398509680158
 * ```
 *
 * @param {number[]} seq A sequence of integers (an array).
 * @return {number} The hash of the sum of the sequence of integers.
 */
function intSumHash(seq) {
  const BIG_PRIME = 4503599627370449;
  let h = 0;
  for (let i = 0; i < seq.length; i++) {
    const value = seq[i];
    h = (h % BIG_PRIME) + (value % BIG_PRIME);
  }
  return h;
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "xrange": () => (/* binding */ xrange)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions related to iterators, generators and iterations.
 */

/**
 * Yields all the numbers of the specified range
 * (including "start" and "limit" if they fall in the range while stepping
 * with "step").
 *
 * @generator
 * @param {number} start An int specifying the start of the range.
 * @param {number} limit An int specifying the limit of the range.
 * @param {number} step An int specifying the step to take within each value of the range.
 * @yield {number} The next number of the range.
 */
function* xrange(start, limit, step = 1) {
  if (start < limit) {
    if (step <= 0) {
      throw new RangeError("Step must be a positive int greater than 0.");
    }
    for (let i = start; i <= limit; i += step) {
      yield i;
    }
  } else {
    if (step >= 0) {
      throw new RangeError("Step must be a negative int greater than 0.");
    }
    for (let i = start; i >= limit; i += step) {
      yield i;
    }
  }
}


/***/ }),

/***/ "./src/modules/map-coordinates.js":
/*!****************************************!*\
  !*** ./src/modules/map-coordinates.js ***!
  \****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "clampLat": () => (/* binding */ clampLat),
/* harmony export */   "wrapLng": () => (/* binding */ wrapLng),
/* harmony export */   "normalizeLat": () => (/* binding */ normalizeLat),
/* harmony export */   "normalizeLng": () => (/* binding */ normalizeLng)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions related to the coordinates of a map.
 */

/**
 * Clamps a latitude value so that it is always between -90 and 90.
 *
 * Latitude ranges between -90 and 90 degrees, inclusive.
 * Values above or below this range will be clamped to the range [-90, 90].
 * This means that if the value specified is less than -90, it will be set to -90.
 * And if the value is greater than 90, it will be set to 90.
 *
 * @param {number|string} lat Latitude. Either a number or a string which can be casted to a number.
 * @return {number} Latitude, clamped.
 */
const clampLat = lat => Number(lat < -90 ? -90 : lat > 90 ? 90 : lat);

/**
 * Wraps a longitude value so that it is always between -180 and 180.
 *
 * Longitude ranges between -180 and 180 degrees, inclusive.
 * Values above or below this range will be wrapped so that they fall within the range.
 * For example, a value of -190 will be converted to 170.
 * A value of 190 will be converted to -170.
 * This reflects the fact that longitudes wrap around the globe.
 *
 * @param {number|string} lng Longitude. Either a number or a string which can be casted to a number.
 * @return {number} lng Longitude, wrapped.
 */
const wrapLng = lng => {
  lng = Number(lng);
  while (lng > 180) {
    lng -= 360;
  }
  while (lng < -180) {
    lng += 360;
  }
  return lng;
};

/**
 * Normalizes a latitude so that it is within the range [0, 180].
 *
 * 1. normalizeLat(90) === 0;
 * 2. normalizeLat(0) === 90;
 * 3. normalizeLat(-90) === 180;
 *
 * @param {number|string} lat Latitude. Either a number or a string which can be casted to a number.
 * @return {number} Latitude, normalized.
 */
const normalizeLat = lat => {
  lat = clampLat(lat);
  if (lat >= 0) {
    // 1. + 2.
    return 90 - lat;
  } else {
    // 3.
    return 90 + Math.abs(lat);
  }
};

/**
 * Normalizes a longitude so that it is within the range [0, 360].
 *
 * 1. normalizeLng(-180) === 0;
 * 2. normalizeLng(0) === 180;
 * 3. normalizeLng(180) === 360;
 *
 * @param {number} lng Longitude. Either a number or a string which can be casted to a number.
 * @return {number} Longitude, normalized.
 */
const normalizeLng = lng => {
  lng = wrapLng(lng);
  return lng + 180;
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "round": () => (/* binding */ round),
/* harmony export */   "sum": () => (/* binding */ sum),
/* harmony export */   "intDiv": () => (/* binding */ intDiv),
/* harmony export */   "isEven": () => (/* binding */ isEven),
/* harmony export */   "isOdd": () => (/* binding */ isOdd),
/* harmony export */   "proportion": () => (/* binding */ proportion)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Mathematical utility functions.
 */

/**
 * Rounds a number.
 *
 * @param {number} number The number to round.
 * @param {number} precision The decimal precision.
 * @return {number} The rounded number.
 */
function round(number, precision = 0) {
  const factor = 10 ** precision;
  return Math.round(number * factor) / factor;
}

/**
 * Sums two or more numbers.
 *
 * @param {...number} numbers The numbers to sum.
 * @return {number} The sum.
 */
function sum(...numbers) {
  return numbers.reduce((carry, num) => carry + num);
}

/**
 * Integer division (without decimal part).
 *
 * @param {number} num A number.
 * @param {number} divideBy The number by which to divide "num".
 * @return {number} The result of the integer division.
 */
function intDiv(num, divideBy) {
  return Math.floor(num / divideBy);
}

/**
 * Tests if a number is even.
 *
 * @param {number} num A number.
 * @return {boolean} True if even, false if odd.
 */
function isEven(num) {
  return num % 2 === 0;
}

/**
 * Tests if a number is odd.
 *
 * @param {number} num A number.
 * @return {boolean} True if odd, false if even.
 */
function isOdd(num) {
  return !isEven(num);
}

/**
 * Converts a source value of a source range to a value that is proportional
 * in another destination range.
 *
 * @param {number[]} sourceTuple The source range tuple, i.e. a tuple of two values, the starting value of the range at index 0 and the ending value of the range at index 1,
 *                               respectively.
 *                               This function assumes that both the starting and ending values are positive numbers (the starting value can be 0).
 * @return {(destRange: number[]) => (sourceValue: number) => number} A function receiving the destination range tuple as argument (having the same shape as the source range)
 *                                                                    returning a function taking the source value as argument returning the value proportional
 *                                                                    in the destination range.
 */
const proportion = ([sourceFrom, sourceTo]) => ([
  destFrom,
  destTo,
]) => sourceValue =>
  (sourceValue - sourceFrom) * ((destTo - destFrom) / (sourceTo - sourceFrom)) +
  destFrom;


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "objectMin": () => (/* binding */ objectMin)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Object-related utility functions.
 */

/**
 * @type {Function}
 */
const defaultObjectComparator = (a, b) => (a < b ? -1 : a > b ? 1 : 0);

/**
 * Finds the minimum value of an object.
 *
 * @param {Object} obj An object.
 * @param {Object} [options] An optional object with further options.
 * @param {(a: *, c: *) => number} [options.comparator] A comparator function receiving two values as arguments which must return a number less than 0 if the first
 *                                                      given value is the new minimum value.
 * @param {boolean} [options.returnAsKeyVal] True to return an object containing two properties `value` and `key`, namely the minimum value's key
 *                                           (`key` property) as well as the minimum value itself (`value` property).
 * @return {*} The minimum value or an object with the key and the minimum value if "returnAsKeyVal" is truthy.
 */
const objectMin = (
  obj,
  { comparator = defaultObjectComparator, returnAsKeyVal = false } = {}
) => {
  const min = { key: void 0, value: void 0 };
  for (const key in obj) {
    const value = obj[key];
    if (typeof min.key === "undefined" || comparator(value, min.value) < 0) {
      min.key = key;
      min.value = value;
    }
  }
  return returnAsKeyVal ? min : min.value;
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "basename": () => (/* binding */ basename),
/* harmony export */   "pathinfo": () => (/* binding */ pathinfo),
/* harmony export */   "filenameExtension": () => (/* binding */ filenameExtension),
/* harmony export */   "dirname": () => (/* binding */ dirname)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions for filenames and paths.
 */

/**
 * Returns the basename of a path.
 *
 * @param {string} path A path.
 * @return {string} The basename of the given path.
 */
function basename(path) {
  return path.split(/[\\/]/).pop();
}

/**
 * Returns info about a path.
 *
 * @param {string} path The path.
 * @param {number} [options] Optioanl options flag.
 */
function pathinfo(path, options) {
  //  discuss at: http://locutus.io/php/pathinfo/
  // original by: Nate
  //  revised by: Kevin van Zonneveld (http://kvz.io)
  // improved by: Brett Zamir (http://brett-zamir.me)
  // improved by: Dmitry Gorelenkov
  //    input by: Timo
  //      note 1: Inspired by actual PHP source: php5-5.2.6/ext/standard/string.c line #1559
  //      note 1: The way the bitwise arguments are handled allows for greater flexibility
  //      note 1: & compatability. We might even standardize this
  //      note 1: code and use a similar approach for
  //      note 1: other bitwise PHP functions
  //      note 1: Locutus tries very hard to stay away from a core.js
  //      note 1: file with global dependencies, because we like
  //      note 1: that you can just take a couple of functions and be on your way.
  //      note 1: But by way we implemented this function,
  //      note 1: if you want you can still declare the PATHINFO_*
  //      note 1: yourself, and then you can use:
  //      note 1: pathinfo('/www/index.html', PATHINFO_BASENAME | PATHINFO_EXTENSION);
  //      note 1: which makes it fully compliant with PHP syntax.
  //   example 1: pathinfo('/www/htdocs/index.html', 1)
  //   returns 1: '/www/htdocs'
  //   example 2: pathinfo('/www/htdocs/index.html', 'PATHINFO_BASENAME')
  //   returns 2: 'index.html'
  //   example 3: pathinfo('/www/htdocs/index.html', 'PATHINFO_EXTENSION')
  //   returns 3: 'html'
  //   example 4: pathinfo('/www/htdocs/index.html', 'PATHINFO_FILENAME')
  //   returns 4: 'index'
  //   example 5: pathinfo('/www/htdocs/index.html', 2 | 4)
  //   returns 5: {basename: 'index.html', extension: 'html'}
  //   example 6: pathinfo('/www/htdocs/index.html', 'PATHINFO_ALL')
  //   returns 6: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}
  //   example 7: pathinfo('/www/htdocs/index.html')
  //   returns 7: {dirname: '/www/htdocs', basename: 'index.html', extension: 'html', filename: 'index'}
  let opt = "";
  let realOpt = "";
  let optName = "";
  let optTemp = 0;
  const tmpArr = {};
  let cnt = 0;
  let i = 0;
  let haveBasename = false;
  let haveExtension = false;
  let haveFilename = false;
  // Input defaulting & sanitation
  if (!path) {
    return false;
  }
  if (!options) {
    options = "PATHINFO_ALL";
  }
  // Initialize binary arguments. Both the string & integer (constant) input is
  // allowed
  const OPTS = {
    PATHINFO_DIRNAME: 1,
    PATHINFO_BASENAME: 2,
    PATHINFO_EXTENSION: 4,
    PATHINFO_FILENAME: 8,
    PATHINFO_ALL: 0,
  };
  // PATHINFO_ALL sums up all previously defined PATHINFOs (could just pre-calculate)
  for (optName in OPTS) {
    if (Object.prototype.hasOwnProperty.call(OPTS, optName)) {
      OPTS.PATHINFO_ALL = OPTS.PATHINFO_ALL | OPTS[optName];
    }
  }
  if (typeof options !== "number") {
    // Allow for a single string or an array of string flags
    options = [].concat(options);
    for (i = 0; i < options.length; i++) {
      // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
      if (OPTS[options[i]]) {
        optTemp = optTemp | OPTS[options[i]];
      }
    }
    options = optTemp;
  }
  // Internal Functions
  const _getExt = function (path) {
    const str = path + "";
    const dotP = str.lastIndexOf(".") + 1;
    return !dotP ? false : dotP !== str.length ? str.substr(dotP) : "";
  };
  // Gather path infos
  if (options & OPTS.PATHINFO_DIRNAME) {
    const dirName = path.replace(/\\/g, "/").replace(/\/[^/]*\/?$/, ""); // dirname
    tmpArr.dirname = dirName === path ? "." : dirName;
  }
  if (options & OPTS.PATHINFO_BASENAME) {
    if (haveBasename === false) {
      haveBasename = basename(path);
    }
    tmpArr.basename = haveBasename;
  }
  if (options & OPTS.PATHINFO_EXTENSION) {
    if (haveBasename === false) {
      haveBasename = basename(path);
    }
    if (haveExtension === false) {
      haveExtension = _getExt(haveBasename);
    }
    if (haveExtension !== false) {
      tmpArr.extension = haveExtension;
    }
  }
  if (options & OPTS.PATHINFO_FILENAME) {
    if (haveBasename === false) {
      haveBasename = basename(path);
    }
    if (haveExtension === false) {
      haveExtension = _getExt(haveBasename);
    }
    if (haveFilename === false) {
      haveFilename = haveBasename.slice(
        0,
        haveBasename.length -
          (haveExtension
            ? haveExtension.length + 1
            : haveExtension === false
            ? 0
            : 1)
      );
    }
    tmpArr.filename = haveFilename;
  }
  // If array contains only 1 element: return string
  cnt = 0;
  for (opt in tmpArr) {
    if (Object.prototype.hasOwnProperty.call(tmpArr, opt)) {
      cnt++;
      realOpt = opt;
    }
  }
  if (cnt === 1) {
    return tmpArr[realOpt];
  }
  // Return full-blown array
  return tmpArr;
}

/**
 * Returns the extension of a filename.
 *
 * @param {string} filename The filename.
 * @return {string} The extension of the given filename.
 */
function filenameExtension(filename) {
  const extension = pathinfo(filename, "PATHINFO_EXTENSION");
  if (typeof extension !== "string") {
    return "";
  }
  return extension;
}

/**
 * Returns the dirname of a path.
 *
 * @param {string} path A path.
 * @return {string} The dirname of the given path.
 */
function dirname(path) {
  //  discuss at: http://locutus.io/php/dirname/
  // original by: Ozh
  // improved by: XoraX (http://www.xorax.info)
  //   example 1: dirname('/etc/passwd')
  //   returns 1: '/etc'
  //   example 2: dirname('c:/Temp/x')
  //   returns 2: 'c:/Temp'
  //   example 3: dirname('/dir/test/')
  //   returns 3: '/dir'
  return path.replace(/\\/g, "/").replace(/\/[^/]*\/?$/, "");
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "timeout": () => (/* binding */ timeout),
/* harmony export */   "minDelayPromise": () => (/* binding */ minDelayPromise),
/* harmony export */   "maxDelayFallbackPromise": () => (/* binding */ maxDelayFallbackPromise),
/* harmony export */   "applyAsync": () => (/* binding */ applyAsync),
/* harmony export */   "composeAsync": () => (/* binding */ composeAsync),
/* harmony export */   "asSoonAtLeastSomeFulfilled": () => (/* binding */ asSoonAtLeastSomeFulfilled)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Promise-related utility functions.
 */



/**
 * Creates a new timeout promise which will resolve after the given milliseconds timeout.
 *
 * @param {number} delayMs Delay in milliseconds after which the promise will resolve.
 * @param {*} [value] Optional value to resolve with.
 * @return {Promise} A new promise which resolves right after "delayMs" have elapsed.
 */
function timeout(delayMs, value) {
  return new Promise(resolve => setTimeout(resolve, delayMs, value));
}

/**
 * Creates a new promise with a minimum delay before it is fulfilled.
 *
 * @param {Promise} promise A promise.
 * @param {number} minDelay Minumum delay in milliseconds.
 * @return {Promise} A new promise which resolves with the given value of the given promise
 *                   or rejects with the rejected value of the promise if it rejects.
 */
function minDelayPromise(promise, minDelay) {
  return Promise.all([promise, timeout(minDelay)])
    .then(([value]) => {
      return value;
    })
    .catch(e => {
      throw e;
    });
}

/**
 * Resolves a promise with an optional fallback which fires if the promise does not resolve
 * under a certain time constraint.
 *
 * @param {Object} obj An object.
 * @param {Promise} obj.promise A promise.
 * @param {number} obj.maxDelayMs Max delay in milliseconds to wait before executing "onFallback" code if the time elapses.
 * @param {Function} obj.onFallback Function to execute if the given "promise" takes more than "maxDelayMs" to resolve.
 * @param {number} obj.fallbackMinDelayMs Number of milliseconds to wait if the fallback code gets executed before resolving the promise.
 * @return {Promise} A promise which resolves with the value of "promise" or rejects with the error of the given "promise".
 */
function maxDelayFallbackPromise({
  promise,
  maxDelayMs,
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  onFallback = () => {},
  fallbackMinDelayMs,
} = {}) {
  const uniqueIdentifier = (0,_core__WEBPACK_IMPORTED_MODULE_0__.uniqueId)();
  return Promise.race([
    promise,
    timeout(maxDelayMs).then(() => uniqueIdentifier),
  ]).then(value => {
    if (value === uniqueIdentifier) {
      onFallback();
      return minDelayPromise(promise, fallbackMinDelayMs);
    } else {
      return value;
    }
  });
}

/**
 * Applies an async operation to a promise returning a new one.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#Composition
 *
 * @param {Promise} acc A promise.
 * @param {Function} onfulfilled Fulfilled callback.
 * @param {Function} onrejected Rejected callback.
 * @return {Promise} A new promise.
 */
const applyAsync = (acc, onfulfilled, onrejected) => {
  return typeof onrejected !== "undefined"
    ? acc.then(onfulfilled, onrejected)
    : acc.then(onfulfilled);
};

/**
 * Composes functions which are run subsequently
 * (sequential composition) using promises.
 *
 * This function is useful when a chain of operations is known ahead of time
 * and they must be executed subsequently.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#Composition
 *
 * @param {...(Function|Array)} funcs The functions (fulfilled callbacks). An array can be given and it MUST have
 *                                    the fulfilled callback at index 0 and the reject callback at index 1.
 * @return {Function} A new function that accepts an initial value to be passed through the composition pipeline.
 *                    If the returned function is called, it will return a Promise which represents the chain formed
 *                    by the promises composed subsequently.
 */
const composeAsync = (...funcs) => x => {
  return funcs.reduce((acc, func) => {
    let promise;
    if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isArray)(func)) {
      // Item at index 0 is the fulfilled callback,
      // while the item at index 1 is the reject callback.
      promise = applyAsync(acc, func[0], func[1]);
    } else {
      promise = applyAsync(acc, func);
    }
    return promise;
  }, Promise.resolve(x));
};

/**
 * Returns a promise which resolves as soon as at least some of the promises given as parameter are fulfilled,
 * and rejects if the minimum number of resolved promises ("minNumberOfFulfilledPromises") is not reached after all the given promises are settled.
 *
 * @param {Promise[]} promises An array of promises. If an empty array is given, then the returned promise will never resolve (will remain in pending state forever).
 * @param {number} minNumberOfFulfilledPromises The minimum number of the given promises that must be fulfilled to consider the returned promise fulfilled
 *                                              (e.g. at least 3 of the given promises must be fulfilled).
 *                                              Defaults to 1.
 *                                              If "minNumberOfFulfilledPromises" is less than 0, then it is treated as if it was 1.
 *                                              If "minNumberOfFulfilledPromises" is greater than the number of the given promises "promises",
 *                                              then "minNumberOfFulfilledPromises" is treated as if it was "promises.length".
 * @return {Promise} A new promise. The promise either fulfills or rejects with an object having the following properties:
 *
 *                       - fulfilled: An array, each element being an object having the following properties:
 *
 *                           - promise: The fulfilled promise of the array of promises "promises";
 *                           - value: The value that the promise has resolved with;
 *                           - index: The positional index of the given array of promises "promises";
 *
 *                       - rejected: An array, each element being an object having the following properties:
 *
 *                           - promise: The rejected promise of the array of promises "promises";
 *                           - reason: The reason that the promise has rejected with;
 *                           - index: The positional index of the given array of promises "promises";
 *
 *                   The "fulfilled" array will have "minNumberOfFulfilledPromises" elements.
 */
const asSoonAtLeastSomeFulfilled = (
  promises,
  minNumberOfFulfilledPromises = 1
) => {
  const length = promises.length;
  const unresolvablePromise = new Promise(_core__WEBPACK_IMPORTED_MODULE_0__.noOpFn);
  let promiseToReturn = unresolvablePromise;
  if (minNumberOfFulfilledPromises < 0) {
    minNumberOfFulfilledPromises = 1;
  } else if (minNumberOfFulfilledPromises > length) {
    minNumberOfFulfilledPromises = length;
  }
  if (length > 0) {
    let settledCount = 0;
    let isPromiseSettled = false;
    promiseToReturn = new Promise((resolve, reject) => {
      const fulfilled = [];
      const rejected = [];
      promises.map((promise, index) => {
        let isFulfilled = false;
        promise
          .then(value => {
            if (!isPromiseSettled) {
              isFulfilled = true;
              settledCount++;
              fulfilled.push({
                promise,
                index,
                value,
              });
              if (fulfilled.length === minNumberOfFulfilledPromises) {
                isPromiseSettled = true;
                resolve({ fulfilled, rejected });
              }
            }
          })
          .catch(reason => {
            if (!isPromiseSettled) {
              if (!isFulfilled) {
                settledCount++;
                rejected.push({ promise, index, reason });
                if (settledCount === length) {
                  isPromiseSettled = true;
                  reject({ fulfilled, rejected });
                }
              }
            }
          });
      });
    });
  }
  return promiseToReturn;
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "randomStr": () => (/* binding */ randomStr),
/* harmony export */   "randomInt": () => (/* binding */ randomInt),
/* harmony export */   "randomFloat": () => (/* binding */ randomFloat),
/* harmony export */   "randomDifferentFromValue": () => (/* binding */ randomDifferentFromValue),
/* harmony export */   "uuid": () => (/* binding */ uuid),
/* harmony export */   "noncanonicalUUID": () => (/* binding */ noncanonicalUUID),
/* harmony export */   "randomArrayShuffle": () => (/* binding */ randomArrayShuffle),
/* harmony export */   "randomString": () => (/* binding */ randomString)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions providing random functionality.
 */

/**
 * Generates a random string.
 *
 * @param {number} length The length of the string to return.
 * @return {string} The random string.
 */
function randomStr(length) {
  let result = "";
  const characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const charactersLength = characters.length;
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

/**
 * Generates a random int between min and max (both included).
 *
 * @param {number} min Min int value.
 * @param {number} max Max int value.
 * @return {number} A random int between min and max.
 */
function randomInt(min = 0, max = Number.MAX_SAFE_INTEGER) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

/**
 * Generates a random float between min and max integers (both included).
 *
 * @param {number} min Min int value.
 * @param {number} max Max int value.
 * @return {number} A random float between min and max.
 */
function randomFloat(min = 0, max = 562949953421311) {
  const randInt = randomInt(min, max);
  if (randInt >= max) {
    return randInt;
  }
  return randInt + Math.random();
}

/**
 * Returns a random float (using "Math.random()") not equal to the given value.
 *
 * @param {number} value The given value.
 * @return {number} A random float not equal to value.
 */
function randomDifferentFromValue(value) {
  let ret = Math.random();
  while (value == ret) {
    ret = Math.random();
  }
  return ret;
}

/**
 * @type {Array}
 */
let noncanonicalUUIDCounter = 1;

/**
 * Generates a new UUID.
 *
 * @see https://github.com/tastejs/todomvc/blob/gh-pages/examples/react/js/utils.js
 *
 * @return {string} The UUID.
 */
function uuid() {
  let i, random;
  let uuid = "";

  for (i = 0; i < 32; i++) {
    random = (Math.random() * 16) | 0;
    if (i === 8 || i === 12 || i === 16 || i === 20) {
      uuid += "-";
    }
    uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(16);
  }

  return uuid;
}

/**
 * Generates a new noncanonical UUID. This noncanonical UUID has a further
 * int prefixed by "-" which is concatenated to a canonical UUID at the end
 * of the canonical UUID before returning this noncanonical UUID.
 * The int starts with 1 and increments every time this function is called.
 *
 * @return {string} A noncanonical UUID.
 */
function noncanonicalUUID() {
  const UUID = uuid();
  return UUID + "-" + noncanonicalUUIDCounter++;
}

/**
 * Shuffles an array randomly modifing the given array.
 *
 * @param {Array} array The input array.
 * @return {Array} A reference to the same array given as input,
 *                 but with its elements randomly shuffled.
 */
const shuffleArrayRandomly = array => {
  let i = array.length,
    temporaryValue,
    randomIndex;
  while (0 !== i) {
    randomIndex = Math.floor(Math.random() * i);
    i--;
    temporaryValue = array[i];
    array[i] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
};

/**
 * Returns an array with the elements of the given array randomly shuffled.
 *
 * @param {Array} array An array.
 * @return {Array} A new array with the same elements of the input array, but randomly shuffled.
 */
function randomArrayShuffle(array) {
  return shuffleArrayRandomly(Object.keys(array)).map(i => array[i]);
}

/**
 * Generates a random string.
 *
 * @return {string} A random string.
 */
const randomString = () => Math.random().toString(36).substr(2);


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "mean": () => (/* binding */ mean),
/* harmony export */   "median": () => (/* binding */ median),
/* harmony export */   "minAbsDeviationFromValue": () => (/* binding */ minAbsDeviationFromValue),
/* harmony export */   "minAbsDeviationFromExcludedValue": () => (/* binding */ minAbsDeviationFromExcludedValue)
/* harmony export */ });
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ "./src/modules/math.js");
/* harmony import */ var _array__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./array */ "./src/modules/array.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Statistics-related utility functions.
 */




/**
 * Computes the mean of the given numbers.
 *
 * @param {...number} numbers The numbers.
 * @return {number} The mean.
 */
function mean(...numbers) {
  return (0,_math__WEBPACK_IMPORTED_MODULE_0__.sum)(...numbers) / numbers.length;
}

/**
 * Computes the median of the given numbers.
 *
 * @param {...number} numbers The numbers.
 * @return {number} The median value.
 */
function median(...numbers) {
  const sorted = (0,_array__WEBPACK_IMPORTED_MODULE_1__.sortNums)(numbers);
  const middleIndex = (0,_math__WEBPACK_IMPORTED_MODULE_0__.intDiv)(sorted.length, 2);
  return (0,_math__WEBPACK_IMPORTED_MODULE_0__.isOdd)(sorted.length)
    ? sorted[middleIndex]
    : mean(sorted[middleIndex - 1], sorted[middleIndex]);
}

/**
 * Computes the min deviation from a value.
 *
 * @param {number} value A value.
 * @return {(...numbers: number[]) => number} A function receiving the numbers to use to compute the minimum deviation
 *                                            from "value".
 */
const minAbsDeviationFromValue = value => (...numbers) => {
  let minAbsDeviation = Infinity;
  numbers.map(num => {
    const deviation = Math.abs(num - value);
    if (deviation < minAbsDeviation) {
      minAbsDeviation = deviation;
    }
  });
  return minAbsDeviation;
};

/**
 * Computes the min deviation from a value excluding that value from the numbers received.
 *
 * @param {number} value A value.
 * @return {(...numbers: number[]) => number} A function receiving the numbers to use to compute the minimum deviation
 *                                            from "value" exluding "value".
 */
const minAbsDeviationFromExcludedValue = value => (...numbers) =>
  minAbsDeviationFromValue(value)(...numbers.filter(num => num !== value));


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "escapeRegExp": () => (/* binding */ escapeRegExp),
/* harmony export */   "trimCharacterMask": () => (/* binding */ trimCharacterMask),
/* harmony export */   "trimCharacterRegex": () => (/* binding */ trimCharacterRegex),
/* harmony export */   "trim": () => (/* binding */ trim),
/* harmony export */   "trimLeft": () => (/* binding */ trimLeft),
/* harmony export */   "trimRight": () => (/* binding */ trimRight),
/* harmony export */   "concatWithInnerOuterSeparators": () => (/* binding */ concatWithInnerOuterSeparators),
/* harmony export */   "optionsValueLabel": () => (/* binding */ optionsValueLabel),
/* harmony export */   "startsWith": () => (/* binding */ startsWith),
/* harmony export */   "ucaseFirst": () => (/* binding */ ucaseFirst),
/* harmony export */   "reverseString": () => (/* binding */ reverseString),
/* harmony export */   "separateIntThousands": () => (/* binding */ separateIntThousands)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Utility functions for working with strings.
 */



/**
 * Escapes special characters for a JS regex.
 *
 * @see https://stackoverflow.com/questions/3115150/how-to-escape-regular-expression-special-characters-using-javascript#answer-9310752
 *
 * @param {string} text The string to escape.
 * @return {string} The same string with special regex characters escaped.
 */
function escapeRegExp(text) {
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}

/**
 * Trim characters from the beginning and end of a string.
 *
 * @param {string} str The string.
 * @param {string} characterMask Character mask.
 * @param {Object} options Options.
 * @param {Object.boolean} options.shouldTrimLeft "true" to trim left (defaults to "true" if omitted).
 * @param {Object.boolean} options.shouldTrimRight "true" to trim right (defaults to "true" if omitted).
 * @return {string} The trimmed string.
 */
function trimCharacterMask(str, characterMask, options = {}) {
  if (typeof characterMask === "undefined") {
    characterMask = " ";
  }
  const escapedCharacterMask = escapeRegExp(characterMask);

  const shouldTrimLeft =
    typeof options.shouldTrimLeft === "undefined" || options.shouldTrimLeft;
  const shouldTrimRight =
    typeof options.shouldTrimRight === "undefined" || options.shouldTrimRight;

  const regexParts = [];
  if (shouldTrimLeft) {
    regexParts[regexParts.length] = "^[" + escapedCharacterMask + "]+";
  }
  if (shouldTrimRight) {
    regexParts[regexParts.length] = "[" + escapedCharacterMask + "]+$";
  }
  const regex = new RegExp(regexParts.join("|"), "gm");
  return str.replace(regex, "");
}

/**
 * Trim characters from the beginning and end of a string using an array
 * of regex characters.
 *
 * @param {string} str The string.
 * @param {string} regexCharacters Regex characters.
 * @param {string} additionalModifiers Additional regex modifiers.
 * @return {string} The trimmed string.
 */
function trimCharacterRegex(str, regexCharacters, additionalModifiers) {
  if (typeof regexCharacters === "undefined") {
    regexCharacters = ["\\s"];
  }
  additionalModifiers = additionalModifiers || "";
  const regex = new RegExp(
    "(^(" +
      regexCharacters.join("|") +
      ")+)|((" +
      regexCharacters.join("|") +
      ")+$)",
    "g" + additionalModifiers
  );
  return str.replace(regex, "");
}

/**
 * Alias of "trimCharacterMask".
 * Trim characters from the beginning and end of a string.
 *
 * @param {string} str The string.
 * @param {string} characterMask Character mask.
 * @return {string} The trimmed string.
 */
function trim(str, characterMask) {
  return trimCharacterMask(str, characterMask);
}

/**
 * Trim characters from the beginning of a string.
 *
 * @param {string} str The string.
 * @param {string} characterMask Character mask.
 * @return {string} The left-trimmed string.
 */
function trimLeft(str, characterMask) {
  return trimCharacterMask(str, characterMask, {
    shouldTrimLeft: true,
    shouldTrimRight: false,
  });
}

/**
 * Trim characters from the end of a string.
 *
 * @param {string} str The string.
 * @param {string} characterMask Character mask.
 * @return {string} The right-trimmed string.
 */
function trimRight(str, characterMask) {
  return trimCharacterMask(str, characterMask, {
    shouldTrimLeft: false,
    shouldTrimRight: true,
  });
}

/**
 * Concats the values of an array with an outer separator using an inner separator
 * for first nesting level arrays.
 *
 * E.g.:
 *
 *     concatWithInnerOuterSeparators(["a", "value", ["with", "nested", "value"], "etc"], " # ", " $ ")
 *     // Returns:
 *     "a # value # with $ nested $ value # etc"
 *
 * @param {Array<string>|Array<Array<string>>} arrayToConcat An array of strings or arrays or strings.
 * @param {string} outerSeparator Outer separator.
 * @param {string} innerSeparator Inner separator.
 * @return {string} The concatenated string.
 */
function concatWithInnerOuterSeparators(
  arrayToConcat,
  outerSeparator = " ",
  innerSeparator = " "
) {
  const toConcatFinally = [];
  for (const value of arrayToConcat) {
    if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isArray)(value)) {
      toConcatFinally[toConcatFinally.length] = trim(
        value.join(innerSeparator),
        innerSeparator
      );
    } else {
      toConcatFinally[toConcatFinally.length] = value;
    }
  }
  const ret = trim(toConcatFinally.join(outerSeparator), outerSeparator);
  return ret;
}

/**
 * Returns an array of options with a value and a label string.
 *
 * @param {Object} obj An object with parameters.
 * @param {Object[]} obj.arrayOfObjects An array of objects.
 * @param {string[]|Array.<string|string[]>} obj.concatObjectProps Properties, keys of each object to use for the label
 *                                                                 and to concat with "outerSeparator".
 *                                                                 A nested array of properties can be used to specify an inner
 *                                                                 part of the label to concat using the "innerSeparator".
 * @param {string} obj.valueProp Name of the property which value has to be used for the value property
 *                               of the returned array of objects.
 * @param {string} obj.outerSeparator Outer separator.
 * @param {string} obj.innerSeparator Inner separator.
 * @return {Object[]} Array of objects, each object with two properties:
 *
 *                        - "value": The value of the object;
 *                        - "label": The label of the object.
 *
 */
function optionsValueLabel({
  arrayOfObjects,
  concatObjectProps,
  valueProp = "id",
  outerSeparator = " ",
  innerSeparator = " ",
}) {
  const options = [];
  for (const obj of arrayOfObjects) {
    const arrayToConcat = [];
    for (const prop of concatObjectProps) {
      if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isArray)(prop)) {
        arrayToConcat[arrayToConcat.length] = prop.map(
          propName => obj[propName]
        );
      } else {
        arrayToConcat[arrayToConcat.length] = obj[prop];
      }
    }
    options[options.length] = {
      value: obj[valueProp],
      label: concatWithInnerOuterSeparators(
        arrayToConcat,
        outerSeparator,
        innerSeparator
      ),
    };
  }
  return options;
}

/**
 * Tests if a string starts with another
 *
 * @param {string} haystack The haystack string.
 * @param {string} needle The needle string.
 * @return {boolean} True if the haystack string starts with needle, false otherwise.
 */
function startsWith(haystack, needle) {
  return haystack.indexOf(needle, 0) === 0;
}

/**
 * Makes the first character of the given string uppercase.
 *
 * @param {string} string A string.
 * @return {string} The string with its first character made uppercase.
 */
function ucaseFirst(string) {
  return string.charAt(0).toUpperCase() + string.slice(1);
}

/**
 * Reverses a string.
 *
 * @param {string} string A string to reverse.
 * @return {string} The reversed string.
 */
function reverseString(string) {
  return string.split("").reverse().join("");
}

/**
 * Given an integer, returns a string containing the same integer with additional thousands separators.
 *
 * @param {number} num An integer.
 * @param {string} [sep] The thousands separator to use.
 * @return {string} The same integer with thousands separators.
 */
function separateIntThousands(num, sep = ",") {
  return num
    .toString()
    .split("")
    .reverse()
    .map((d, i, a) =>
      (i + 1) % 3 === 0 && i !== a.length - 1 ? `${sep}${d}` : d
    )
    .reverse()
    .join("");
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "time": () => (/* binding */ time),
/* harmony export */   "msToTime": () => (/* binding */ msToTime),
/* harmony export */   "millisecToSec": () => (/* binding */ millisecToSec),
/* harmony export */   "secondsToTimeString": () => (/* binding */ secondsToTimeString)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math */ "./src/modules/math.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */




/**
 * Time-related utility functions.
 */

/**
 * Returns the current Unix time in seconds.
 *
 * @return {number} Current Unix time in seconds.
 */
function time() {
  const d = new Date();
  const seconds = Math.round(d.getTime() / 1000);
  return seconds;
}

/**
 * Returns the time string approximated to the nearest microsecond
 * corresponding the given Unix timestamp in milliseconds
 * in the format "HH:mm:ss.ms".
 *
 * @param {number} [ms] The time in microseconds to convert into a string.
 *                      If omitted, the current time will be used.
 * @return {string} The time string.
 */
function msToTime(ms) {
  const date = new Date(ms || new Date().getTime());
  const isoDate = new Date(
    date.getTime() - date.getTimezoneOffset() * 60000
  ).toISOString();
  return isoDate.slice(11, -1);
}

/**
 * Converts milliseconds to seconds.
 *
 * @param {number} millisec Number of milliseconds.
 * @return {number} The milliseconds in seconds.
 */
function millisecToSec(millisec) {
  return millisec * 0.001;
}

/**
 * Converts seconds to a `minutes:seconds` or `hours:minutes:seconds` time string
 * (if the second parameter is an object with `includeHours` set to a truthy value),
 * e.g. `123` becomes `"02:03"`, or `"00:02:03"` if `includeHours` is truthy.
 *
 * @param {number} secs The number of seconds.
 * @param {Object} options Options.
 * @param {Object.boolean} options.includeHours "true" to include hours (defaults to "false" if omitted).
 * @return {string} The time string.
 */
const secondsToTimeString = (secs, { includeHours = false } = {}) => {
  if (!secs || !(0,_core__WEBPACK_IMPORTED_MODULE_0__.isIntegerOrIntegerStr)(secs)) {
    return includeHours ? "00:00:00" : "00:00";
  }
  let hours = "";
  let minutes = (0,_math__WEBPACK_IMPORTED_MODULE_1__.intDiv)(secs, 60);
  if (includeHours) {
    hours = `${((0,_math__WEBPACK_IMPORTED_MODULE_1__.intDiv)(secs, 60 * 60) + "").padStart(2, "0")}:`;
    minutes = minutes % 60;
  }
  minutes += "";
  const seconds = (secs % 60) + "";
  return `${hours}${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`;
};


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "isValidHttpUrl": () => (/* binding */ isValidHttpUrl)
/* harmony export */ });
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Returns true if the given string is a valid HTTP URL (either HTTP or HTTPS).
 *
 * @see https://regex101.com/r/HjBD9T/1
 *
 * @param {string} maybeValidHttpUrl A string that's maybe a valid HTTP URL.
 * @return {boolean} True if the given string is a valid HTTP URL, false otherwise.
 */
function isValidHttpUrl(maybeValidHttpUrl) {
  return /^(?:(?:https?:)\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
    maybeValidHttpUrl
  );
}


/***/ }),

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

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "buildQueryString": () => (/* binding */ buildQueryString),
/* harmony export */   "formData": () => (/* binding */ formData),
/* harmony export */   "xhr": () => (/* binding */ xhr),
/* harmony export */   "checkNetwork": () => (/* binding */ checkNetwork),
/* harmony export */   "waitNetwork": () => (/* binding */ waitNetwork),
/* harmony export */   "setCookie": () => (/* binding */ setCookie),
/* harmony export */   "getCookie": () => (/* binding */ getCookie),
/* harmony export */   "unsetCookie": () => (/* binding */ unsetCookie),
/* harmony export */   "isInViewport": () => (/* binding */ isInViewport),
/* harmony export */   "isScrolledIntoView": () => (/* binding */ isScrolledIntoView),
/* harmony export */   "hasVerticalScrollbar": () => (/* binding */ hasVerticalScrollbar),
/* harmony export */   "hasHorizontalScrollbar": () => (/* binding */ hasHorizontalScrollbar),
/* harmony export */   "elementUniqueId": () => (/* binding */ elementUniqueId),
/* harmony export */   "getElementComputedStyle": () => (/* binding */ getElementComputedStyle),
/* harmony export */   "elementInnerDimensions": () => (/* binding */ elementInnerDimensions),
/* harmony export */   "countTextareaLines": () => (/* binding */ countTextareaLines),
/* harmony export */   "isScrollOnBottom": () => (/* binding */ isScrollOnBottom),
/* harmony export */   "getVerticalScrollBarWidth": () => (/* binding */ getVerticalScrollBarWidth),
/* harmony export */   "isEllipsisActive": () => (/* binding */ isEllipsisActive),
/* harmony export */   "copyTextToClipboard": () => (/* binding */ copyTextToClipboard),
/* harmony export */   "rAFLooper": () => (/* binding */ rAFLooper),
/* harmony export */   "nestedRAF": () => (/* binding */ nestedRAF),
/* harmony export */   "getRawURIFragment": () => (/* binding */ getRawURIFragment),
/* harmony export */   "getDecodedURIFragment": () => (/* binding */ getDecodedURIFragment),
/* harmony export */   "appendEncodedJSONFragmentToURI": () => (/* binding */ appendEncodedJSONFragmentToURI),
/* harmony export */   "getDecodedJSONFromFragmentURI": () => (/* binding */ getDecodedJSONFromFragmentURI),
/* harmony export */   "parseQueryStringArgsMultiDim": () => (/* binding */ parseQueryStringArgsMultiDim),
/* harmony export */   "getQueryStringArgsMultiDim": () => (/* binding */ getQueryStringArgsMultiDim),
/* harmony export */   "cursorFocus": () => (/* binding */ cursorFocus),
/* harmony export */   "detectWrapped": () => (/* binding */ detectWrapped),
/* harmony export */   "maxNestingLevel": () => (/* binding */ maxNestingLevel),
/* harmony export */   "getScrollableAncestor": () => (/* binding */ getScrollableAncestor),
/* harmony export */   "smoothScrollToTop": () => (/* binding */ smoothScrollToTop),
/* harmony export */   "downloadFile": () => (/* binding */ downloadFile)
/* harmony export */ });
/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./core */ "./src/modules/core/index.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Web application (browser) utility functions.
 */



/**
 * Builds a form data instance or object recursively.
 *
 * @see https://stackoverflow.com/questions/22783108/convert-js-object-to-form-data#answer-42483509
 *
 * @param {FormData|Object} formData Form data instance or JS POJO object.
 * @param {Array|Object} data JS POJO object or array with the form data to use to build the forma data.
 * @param {boolean} [shouldEncodeURIComponent] Optionally instructs the function if the parameters should be encoded
 *                                             (keys and values) using "encodeURIComponent".
 * @param {string} [parentKey] Parent key for nested parameters (used internally for recursion).
 * @return {undefined}
 */
function buildFormData(formData, data, shouldEncodeURIComponent, parentKey) {
  if (
    data &&
    typeof data === "object" &&
    !(data instanceof Date) &&
    !(data instanceof File)
  ) {
    Object.keys(data).forEach(key => {
      buildFormData(
        formData,
        data[key],
        shouldEncodeURIComponent,
        parentKey
          ? `${parentKey}[${key}]`
          : shouldEncodeURIComponent
          ? encodeURIComponent(key)
          : key
      );
    });
  } else {
    // Leaf value.
    const value =
      data == null
        ? ""
        : shouldEncodeURIComponent
        ? encodeURIComponent(data)
        : data;
    formData instanceof FormData
      ? formData.append(parentKey, value)
      : (formData[parentKey] = value);
  }
}

/**
 * Constructs a query string from the given data.
 * This method works with nested objects/arrays.
 *
 * @param {Array|Object} data The object.
 * @return {string} The query string.
 */
function buildQueryString(data) {
  const formData = {};
  buildFormData(formData, data, true); // "true" instructs the function to encode URI parts (keys and values).
  const parts = [];
  for (const prop in formData) {
    parts.push(prop + "=" + formData[prop]);
  }
  return parts.join("&");
}

/**
 * Converts an object (array or JS POJO object) to a form data instance.
 *
 * @param {Array|Object} data The data (array or POJO object).
 * @return {FormData} A form data instance.
 */
function formData(data) {
  const formData = new FormData();
  buildFormData(formData, data);
  return formData;
}

/**
 * Returns a new XMLHttpRequest or ActiveXObject object.
 *
 * @return {XMLHttpRequest|ActiveXObject}
 */
const xhr = () =>
  (window.ActiveXObject && new window.ActiveXObject("Microsoft.XMLHTTP")) ||
  new XMLHttpRequest();

/**
 * Checks whether the network is reachable or not.
 *
 * @param {string} URI An eventual URI to use for the request.
 *                     NOTE: If omitted, then "config.checkNetworkURI" will be used,
 *                           or, if "config.checkNetworkURI" is not set,
 *                           the website's hostname will be used.
 *                           Also, in every case, A GET query string with a random parameter
 *                           is always appended to the URI.
 * @return {Promise} A promise which resolves to "true" if the network is reachable and to "false" otherwise.
 *                   Note that the returned promise always resolves to "true" when this code runs on localhost.
 */
function checkNetwork(URI = null) {
  // Handle IE and more capable browsers.
  const xhrObj = xhr();

  return new Promise(resolve => {
    // Issue request and handle response.
    try {
      xhrObj.onreadystatechange = () => {
        if (xhrObj.readyState == 4) {
          resolve(
            xhrObj.status >= 200 &&
              (xhrObj.status < 300 || xhrObj.status === 304)
          );
        }
      };

      // Open new request as a HEAD to the root hostname with a random param to bust the cache.
      xhrObj.open(
        "HEAD",
        (URI ||
          _core__WEBPACK_IMPORTED_MODULE_0__.config.checkNetworkURI ||
          "//" +
            window.location.hostname +
            (window.location.port != 80 ? ":" + window.location.port : "")) +
          "?rand=" +
          Math.floor((1 + Math.random()) * 0x10000), // 0x10000 = 2^16
        true
      );

      xhrObj.send();
    } catch (error) {
      resolve(false);
    }
  });
}

/**
 * Returns a promise which resolves when the network is available.
 *
 * NOTE: If the network is available, the promise will resolve almost immediately.
 *
 * @param {number} intervalMillisecs An interval in milliseconds to wait before the next network check.
 * @return {Promise} A promise.
 */
function waitNetwork(intervalMillisecs = 3000) {
  return new Promise(resolve => {
    checkNetwork().then(isNetworkReachable => {
      if (isNetworkReachable) {
        resolve();
      } else {
        const interval = setInterval(() => {
          checkNetwork().then(isNetworkReachable => {
            if (isNetworkReachable) {
              clearInterval(interval);
              resolve();
            }
          });
        }, intervalMillisecs);
      }
    });
  });
}

/**
 * Sets a cookie value.
 *
 * @see https://www.w3schools.com/js/js_cookies.asp
 *
 * @param {string} cname The cookie name.
 * @param {string} cvalue The cookie value.
 * @param {number|undefined} exdays Number of days after which the cookie expires,
 *                                  or "undefined" to make the cookie expire at the end of the session.
 * @return {undefined}
 */
function setCookie(cname, cvalue, exdays) {
  let expires = "";
  if (exdays) {
    const d = new Date();
    d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
    expires = "expires=" + d.toUTCString() + ";";
  }
  document.cookie = cname + "=" + cvalue + ";" + expires + "path=/";
}

/**
 * Gets a cookie value.
 *
 * @see https://www.w3schools.com/js/js_cookies.asp
 *
 * @param {string} cname The cookie name.
 * @return {string|undefined} The cookie value or "undefined", if not set.
 */
function getCookie(cname) {
  const name = cname + "=";
  const ca = document.cookie.split(";");
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) == " ") {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return void 0;
}

/**
 * Unsets a cookie.
 *
 * @param {string} cname The cookie name.
 * @return {undefined}
 */
function unsetCookie(cname) {
  setCookie(cname, "", -365);
}

/**
 * Tests whether a DOM element is in viewport or not.
 *
 * @param {Element} elem The DOM element.
 * @return {boolean} True if it is in viewport, false otherwise.
 */
function isInViewport(elem) {
  const bounding = elem.getBoundingClientRect();
  return (
    bounding.top >= 0 &&
    bounding.left >= 0 &&
    bounding.bottom <=
      (window.innerHeight || document.documentElement.clientHeight) &&
    bounding.right <=
      (window.innerWidth || document.documentElement.clientWidth)
  );
}

/**
 * Tests if a DOM element is scrolled into the scrollable view of its parent scrollable container.
 *
 * @param {Element} elem The DOM element to test.
 * @param {Element} holder The DOM element of the scrollable container of the DOM element to test.
 * @param {number|Function} minPx Minimum number of pixels of the element's height which must be scrolled into the view
 *                                in order to consider the element to be scrolled into view.
 *                                If a function is given, it will receive the element's bounding client rect as the first argument
 *                                as well as the holder element's bounding client rect as the second argument and must return
 *                                the minimum number of pixels.
 * @return {boolean} True if the given element is scrolled into view, false otherwise.
 */
function isScrolledIntoView(el, holder, minPx = 1) {
  const elRect = el.getBoundingClientRect();
  const holderRect = holder.getBoundingClientRect();
  const { top, bottom, height } = elRect;

  const minPxNumberFn = () =>
    typeof minPx === "function" ? minPx(elRect, holderRect) : minPx;
  let bottomDiff;
  return top <= holderRect.top
    ? holderRect.top - top + minPxNumberFn() <= height
    : (bottomDiff = bottom - holderRect.bottom) < 0
    ? true
    : holderRect.bottom >= top && minPx
    ? holderRect.bottom - top >= minPxNumberFn()
    : bottomDiff <= height;
}

/**
 * Tests if a DOM element has a vertical scrollbar.
 *
 * @param {Element} elem The DOM element.
 * @return {boolean} True it has a vertical scrollbar, false otherwise.
 */
function hasVerticalScrollbar(elem) {
  const hasVerticalScrollbar = elem.scrollHeight > elem.clientHeight;
  return hasVerticalScrollbar;
}

/**
 * Tests if a DOM element has a horizontal scrollbar.
 *
 * @param {Element} elem The DOM element.
 * @return {boolean} True it has a horizontal scrollbar, false otherwise.
 */
function hasHorizontalScrollbar(elem) {
  const hasHorizontalScrollbar = elem.scrollWidth > elem.clientWidth;
  return hasHorizontalScrollbar;
}

/**
 * Generates a unique ID which can be used for an element.
 *
 * @param {string|undefined} [elementUniqueIdPrefix] Local unique ID prefix which overrides the prefix
 *                                                   set on the "config" configuration object.
 * @return {string} The element unique ID.
 */
function elementUniqueId(elementUniqueIdPrefix = void 0) {
  const uniqueElementIdSuffix = (0,_core__WEBPACK_IMPORTED_MODULE_0__.uniqueId)();
  return (
    (elementUniqueIdPrefix || _core__WEBPACK_IMPORTED_MODULE_0__.config.elementUniqueIdPrefix) +
    uniqueElementIdSuffix
  );
}

/**
 * Gets the computed style of an element.
 *
 * @param {Element} element DOM element.
 * @return {CSSStyleDeclaration} The computed style.
 */
function getElementComputedStyle(element) {
  return window.getComputedStyle(element);
}

/**
 * Gets element's inner dimensions (height and width without padding).
 *
 * @param {Element} element An element.
 * @return {Object} An object with "width" and "height" properties.
 */
function elementInnerDimensions(element) {
  const computedStyle = getElementComputedStyle(element);

  let elementHeight = element.clientHeight; // Height with padding.
  let elementWidth = element.clientWidth; // Width with padding

  elementHeight -=
    parseFloat(computedStyle.paddingTop) +
    parseFloat(computedStyle.paddingBottom);
  elementWidth -=
    parseFloat(computedStyle.paddingLeft) +
    parseFloat(computedStyle.paddingRight);
  return {
    width: elementWidth,
    height: elementHeight,
  };
}

/**
 * @type {HTMLTextAreaElement}
 */
let countTextareaLinesBuffer;

/**
 * Returns the number of lines in a textarea, including wrapped lines.
 *
 * @see https://stackoverflow.com/questions/28905965/textarea-how-to-count-wrapped-lines-rows#answer-45252226
 *
 * @param {HTMLTextAreaElement} textarea A textarea element. Note that the textarea should have an integer line height
 *                                       to avoid rounding errors.
 */
function countTextareaLines(textarea) {
  if (countTextareaLinesBuffer == null) {
    countTextareaLinesBuffer = document.createElement("textarea");
    countTextareaLinesBuffer.style.border = "none";
    countTextareaLinesBuffer.style.height = "0";
    countTextareaLinesBuffer.style.overflow = "hidden";
    countTextareaLinesBuffer.style.padding = "0";
    countTextareaLinesBuffer.style.position = "absolute";
    countTextareaLinesBuffer.style.left = "0";
    countTextareaLinesBuffer.style.top = "0";
    countTextareaLinesBuffer.style.zIndex = "-1";
    document.body.appendChild(countTextareaLinesBuffer);
  }

  const cs = window.getComputedStyle(textarea);
  const pl = parseInt(cs.paddingLeft);
  const pr = parseInt(cs.paddingRight);
  let lh = parseInt(cs.lineHeight);

  // `cs.lineHeight` may return 'normal', which means line height = font size.
  if (isNaN(lh)) lh = parseInt(cs.fontSize);

  // Copy content width.
  countTextareaLinesBuffer.style.width = textarea.clientWidth - pl - pr + "px";

  // Copy text properties.
  countTextareaLinesBuffer.style.font = cs.font;
  countTextareaLinesBuffer.style.letterSpacing = cs.letterSpacing;
  countTextareaLinesBuffer.style.whiteSpace = cs.whiteSpace;
  countTextareaLinesBuffer.style.wordBreak = cs.wordBreak;
  countTextareaLinesBuffer.style.wordSpacing = cs.wordSpacing;
  countTextareaLinesBuffer.style.wordWrap = cs.wordWrap;

  // Copy value.
  countTextareaLinesBuffer.value = textarea.value;

  let result = Math.floor(countTextareaLinesBuffer.scrollHeight / lh);
  if (result == 0) {
    result = 1;
  }
  return result;
}

/**
 * Checks if the scroll of an element is on the bottom.
 *
 * @param {Element} DOMNode Element.
 * @return {boolean} True if the scroll is on the bottom, false otherwise.
 */
function isScrollOnBottom(DOMNode) {
  const ret = DOMNode.scrollTop + DOMNode.offsetHeight >= DOMNode.scrollHeight;
  return ret;
}

/**
 * Returns the default browser's vertical scrollbar width.
 *
 * @return {Number} The scrollbar width.
 */
function getVerticalScrollBarWidth() {
  const scrollDiv = document.createElement("div");
  scrollDiv.className = "vertical-scrollbar-measure";

  const sheet = document.createElement("style");
  sheet.innerHTML =
    "div.vertical-scrollbar-measure { width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px; }";

  document.body.appendChild(sheet);
  document.body.appendChild(scrollDiv);

  const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;

  document.body.removeChild(scrollDiv);
  const sheetParent = sheet.parentNode;
  sheetParent.removeChild(sheet);

  return scrollbarWidth;
}

/**
 * Tests if an element with "text-overflow: ellipsis;" has the ellipsis active
 * and therefore its text is truncated.
 *
 * @param {Element} e The DOM element.
 * @return {boolean} True if ellipsis are present, false otherwise.
 */
function isEllipsisActive(e) {
  return e.offsetWidth < e.scrollWidth;
}

/**
 * A fallback function to copy a text to clipboard.
 *
 * @param {string} text The text to copy.
 * @param {Function} [onSuccess] An optional callback to execute on success.
 * @param {Function} [onFailure] An optional callback to execute on failure.
 * @return {undefined}
 */
function fallbackCopyTextToClipboard(text, onSuccess, onFailure) {
  const bodyScrollTop =
    document.documentElement.scrollTop || document.body.scrollTop;
  const textArea = document.createElement("textarea");
  textArea.value = text;
  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    const successful = document.execCommand("copy");
    if (successful) {
      onSuccess && onSuccess();
    } else {
      onFailure && onFailure();
    }
  } catch (err) {
    onFailure && onFailure(err);
  }

  (document.body.removeChild(textArea) &&
    document.documentElement.scrollTop &&
    (document.documentElement.scrollTop = bodyScrollTop)) ||
    (document.body.scrollTop = bodyScrollTop);
}

/**
 * Copies a text to clipboard.
 *
 * @param {string} text The text to copy.
 * @param {Function} [onSuccess] An optional callback to execute on success.
 * @param {Function} [onFailure] An optional callback to execute on failure.
 * @return {undefined}
 */
function copyTextToClipboard(text, onSuccess, onFailure) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text, onSuccess, onFailure);
    return;
  }
  navigator.clipboard.writeText(text).then(
    function () {
      onSuccess && onSuccess();
    },
    function (err) {
      onFailure && onFailure(err);
    }
  );
}

/**
 * Asynchronously invokes a callback multiple times, each in its own animation frame.
 *
 * @param {number} n The number of times the callback should be invoked.
 * @param {Function} callback The callback to invoke.
 * @return {*} The identifier of the first animation frame or "n" if it is falsy during the outermost call.
 */
const rAFLooper = (n, callback) =>
  n &&
  window.requestAnimationFrame(() => (callback(), rAFLooper(--n, callback)));

/**
 * Requests a predefined number of animation frames and executes a callback after.
 *
 * @param {number} count The number of animation frames to request before executing the callback.
 * @param {Function} callback The callback to execute after "count" animation frames have been requested.
 * @return {number} The identifier of the first animation frame.
 */
const nestedRAF = (count, callback) => {
  let c = count || 1;
  const innerCallback = () => {
    c--;
    if (!c) {
      callback();
      return;
    }
    window.requestAnimationFrame(innerCallback);
  };
  return window.requestAnimationFrame(innerCallback);
};

/**
 * Returns the raw contents of the URI fragment (i.e. everything after the hash ("#") character).
 *
 * @param {string} URIFragment The URI fragment.
 * @return {string} The raw contents of the URI fragment.
 */
function getRawURIFragment(URIFragment) {
  const fragment = (URIFragment || window.location.hash).replace(/^#/, "");
  return fragment;
}

/**
 * Returns the decoded contents of a URI fragment (i.e. everything after the hash ("#") character).
 *
 * @param {string} URIFragment The URI fragment.
 * @return {string} The contents of the URI fragment, decoded.
 */
function getDecodedURIFragment(URIFragment) {
  const fragment = decodeURIComponent(getRawURIFragment(URIFragment));
  return fragment;
}

/**
 * Appends an encoded JSON fragment to a URI.
 *
 * @param {string} URI The URI.
 * @param {*} data Data to encode in JSON format.
 */
function appendEncodedJSONFragmentToURI(URI, data) {
  return URI + "#" + encodeURIComponent(JSON.stringify(data));
}

/**
 * Returnes the decoded JSON data eventually stored in the URI fragment.
 *
 * @param {*} defaultData Default data to return if either the URI fragment is missing or
 *                        the content of the URI fragment is not a valid JSON-encoded string.
 * @return {*} The decoded JSON data or "defaultData".
 */
function getDecodedJSONFromFragmentURI(defaultData = null) {
  const fragment = window.location.hash;
  if (!(0,_core__WEBPACK_IMPORTED_MODULE_0__.isEmpty)(fragment)) {
    const decodedFragment = getDecodedURIFragment(fragment);
    if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isJSONString)(decodedFragment)) {
      return JSON.parse(decodedFragment);
    }
  }
  return defaultData;
}
/**
 * Parses a multidimensional query string and returns an object with the parsed args.
 *
 * @see https://stackoverflow.com/questions/8648892/convert-url-parameters-to-a-javascript-object#answer-44713056
 *
 * @param {string} str The query string.
 * @param {Object} [array] The base object to use (or a new object if omitted or falsy).
 * @return {Object} The object with the parsed data.
 */
function parseQueryStringArgsMultiDim(str, array) {
  if (!str) {
    str = window.location.search.substr(1);
  }
  let i,
    j,
    ct,
    p,
    lastObj,
    obj,
    undef,
    chr,
    tmp,
    key,
    value,
    postLeftBracketPos,
    keys,
    keysLen;
  const strArr = String(str).replace(/^&/, "").replace(/&$/, "").split("&"),
    sal = strArr.length,
    fixStr = function (str) {
      return decodeURIComponent(str.replace(/\+/g, "%20"));
    };

  if (!array) {
    array = {};
  }

  for (i = 0; i < sal; i++) {
    tmp = strArr[i].split("=");
    key = fixStr(tmp[0]);
    value = tmp.length < 2 ? "" : fixStr(tmp[1]);

    while (key.charAt(0) === " ") {
      key = key.slice(1);
    }
    if (key.indexOf("\x00") > -1) {
      key = key.slice(0, key.indexOf("\x00"));
    }
    if (key && key.charAt(0) !== "[") {
      keys = [];
      postLeftBracketPos = 0;
      for (j = 0; j < key.length; j++) {
        if (key.charAt(j) === "[" && !postLeftBracketPos) {
          postLeftBracketPos = j + 1;
        } else if (key.charAt(j) === "]") {
          if (postLeftBracketPos) {
            if (!keys.length) {
              keys.push(key.slice(0, postLeftBracketPos - 1));
            }
            keys.push(key.substr(postLeftBracketPos, j - postLeftBracketPos));
            postLeftBracketPos = 0;
            if (key.charAt(j + 1) !== "[") {
              break;
            }
          }
        }
      }
      if (!keys.length) {
        keys = [key];
      }
      for (j = 0; j < keys[0].length; j++) {
        chr = keys[0].charAt(j);
        if (chr === " " || chr === "." || chr === "[") {
          keys[0] = keys[0].substr(0, j) + "_" + keys[0].substr(j + 1);
        }
        if (chr === "[") {
          break;
        }
      }

      obj = array;
      for (j = 0, keysLen = keys.length; j < keysLen; j++) {
        key = keys[j].replace(/^['"]/, "").replace(/['"]$/, "");
        lastObj = obj;
        if ((key !== "" && key !== " ") || j === 0) {
          if (obj[key] === undef) {
            obj[key] = {};
          }
          obj = obj[key];
        } else {
          // To insert new dimension
          ct = -1;
          for (p in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, p)) {
              if (+p > ct && p.match(/^\d+$/g)) {
                ct = +p;
              }
            }
          }
          key = ct + 1;
        }
      }
      lastObj[key] = value;
    }
  }

  /* ===== */
  /*
   * This code converts the object properties to arrays if they are objects with consecutive integer keys
   * from 0 to n, where n is the number of properties of that object minus one
   * (i.e. it converts meaningful objects which are to be interpreted as arrays to arrays).
   */
  const fnNormalizeObjToArrayIfPropsAreConsecutiveIntsFrom0 = function (obj) {
    const keys = Object.keys(obj);
    const truthMap = {};
    for (let i = 0; i < keys.length; i++) {
      truthMap[i] = true;
    }

    const array = [];
    for (let i = 0; i < keys.length; i++) {
      const prop = keys[i] + "";
      if (!prop.match(/^[0-9]+$/)) {
        return obj;
      }
      const intProp = Number(prop);
      if (truthMap[intProp]) {
        array[intProp] = obj[prop];
        delete truthMap[intProp];
      } else {
        return obj;
      }
    }

    if (Object.keys(truthMap).length === 0) {
      return array;
    } else {
      return obj;
    }
  };

  const fnNormalizeToArrayIfNeeded = function fnNormalizeToArrayIfNeeded(obj) {
    for (const prop in obj) {
      if ((0,_core__WEBPACK_IMPORTED_MODULE_0__.isPlainObject)(obj[prop])) {
        obj[prop] = fnNormalizeObjToArrayIfPropsAreConsecutiveIntsFrom0(
          obj[prop]
        );
        fnNormalizeToArrayIfNeeded(obj[prop]);
      }
    }
  };
  /* /===== */

  fnNormalizeToArrayIfNeeded(array);

  return array;
}

/**
 * Gets the query string arguments of the current location in a multidimensional fashion
 * (multidimension-aware).
 *
 * @return {Object} An object representing the query string arguments.
 */
function getQueryStringArgsMultiDim() {
  const obj = {};
  parseQueryStringArgsMultiDim(location.search.substring(1), obj);
  return obj;
}

/**
 * Focuses an input without scrolling.
 *
 * @see https://stackoverflow.com/questions/4963053/focus-to-input-without-scrolling
 *
 * @param {Element} elem The DOM element.
 */
const cursorFocus = function (elem) {
  let x, y;
  // More sources for scroll x, y offset.
  if (typeof window.pageXOffset !== "undefined") {
    x = window.pageXOffset;
    y = window.pageYOffset;
  } else if (typeof window.scrollX !== "undefined") {
    x = window.scrollX;
    y = window.scrollY;
  } else if (
    document.documentElement &&
    typeof document.documentElement.scrollLeft !== "undefined"
  ) {
    x = document.documentElement.scrollLeft;
    y = document.documentElement.scrollTop;
  } else {
    x = document.body.scrollLeft;
    y = document.body.scrollTop;
  }

  elem.focus();

  if (typeof x !== "undefined") {
    window.scrollTo(x, y);
  }
};

/**
 * Detects wrapped elements.
 *
 * @param {string|Element[]} classNameOrElements A class name (with or without the leading dot) or the DOM elements to check.
 * @return {Element[]} The wrapped DOM elements.
 */
function detectWrapped(classNameOrElements) {
  let elements;
  if (typeof classNameOrElements === "string") {
    classNameOrElements = classNameOrElements.replace(/^\./, "");
    elements = document.getElementsByClassName(classNameOrElements);
  } else {
    elements = classNameOrElements;
  }
  const wrapped = [];
  let prev = {};
  let curr = {};
  for (let i = 0; i < elements.length; i++) {
    const element = elements[i];
    curr = element.getBoundingClientRect();
    if (prev && prev.top < curr.top) {
      wrapped.push(element);
    }
    prev = i === 0 ? curr : prev;
  }
  return wrapped;
}

/**
 * Gets the maximum nesting level of an element (or of the whole DOM if "document.body" is given as parameter).abs
 *
 * @param {Element} elem The DOM element from which to start identifying the maximum nesting level.
 * @return {number} The maximum nesting level, starting from 0 if the given element has no children.
 */
function maxNestingLevel(el) {
  if (!el.children) {
    return 0;
  }
  let max = -1;
  for (let i = 0; i < el.children.length; i++) {
    const nestingLevel = maxNestingLevel(el.children[i]);
    if (nestingLevel > max) {
      max = nestingLevel;
    }
  }
  return max + 1;
}

/**
 * @type {RegExp}
 */
const REGEXP_SCROLL_PARENT = /^(visible|hidden)/;

/**
 * Get the first scrollable ancestor of an element.
 *
 * @param {Element} el The element to use as the base from which to determine its first scrollable ancestor.
 * @return {Element} The first scrollable ancestor element scroll, or the document body.
 */
const getScrollableAncestor = el =>
  !(el instanceof HTMLElement) || typeof window.getComputedStyle !== "function"
    ? null
    : el.scrollHeight >= el.clientHeight &&
      !REGEXP_SCROLL_PARENT.test(
        window.getComputedStyle(el).overflowY || "visible"
      )
    ? el
    : getScrollableAncestor(el.parentElement) ||
      document.scrollingElement ||
      document.body;

/**
 * Smoothly scrolls to the top of a scrollable element or the browser's window.
 *
 * @param {Element} [el] The element. Defaults to "window".
 * @return {undefined}
 */
const smoothScrollToTop = (el = window) =>
  el.scroll({
    top: 0,
    behavior: "smooth",
  });

/**
 * Downloads a file without opening a new browser's tab.
 *
 * @see https://stackoverflow.com/questions/1066452/easiest-way-to-open-a-download-window-without-navigating-away-from-the-page#answer-43523297
 *
 * @param {string} fileURI The URI of the file to download.
 * @return {undefined}
 */
function downloadFile(fileURI) {
  var link = document.createElement("a");
  link.href = fileURI;
  link.download = fileURI.substr(fileURI.lastIndexOf("/") + 1);
  link.click();
}


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/global */
/******/ 	(() => {
/******/ 		__webpack_require__.g = (function() {
/******/ 			if (typeof globalThis === 'object') return globalThis;
/******/ 			try {
/******/ 				return this || new Function('return this')();
/******/ 			} catch (e) {
/******/ 				if (typeof window === 'object') return window;
/******/ 			}
/******/ 		})();
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "config": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.config),
/* harmony export */   "isObjectEmpty": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isObjectEmpty),
/* harmony export */   "isObject": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isObject),
/* harmony export */   "isPlainObject": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isPlainObject),
/* harmony export */   "isArray": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isArray),
/* harmony export */   "isEmpty": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isEmpty),
/* harmony export */   "isEmptyOr0": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isEmptyOr0),
/* harmony export */   "getGlobalObject": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.getGlobalObject),
/* harmony export */   "uniqueId": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.uniqueId),
/* harmony export */   "deepArrayCompare": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.deepArrayCompare),
/* harmony export */   "deepObjectCompare": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.deepObjectCompare),
/* harmony export */   "nestedObjectConstructValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedObjectConstructValue),
/* harmony export */   "cloneDeeplyJSON": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.cloneDeeplyJSON),
/* harmony export */   "isReferenceType": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isReferenceType),
/* harmony export */   "isPrimitiveType": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isPrimitiveType),
/* harmony export */   "hasCyclicReference": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.hasCyclicReference),
/* harmony export */   "typeToStr": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.typeToStr),
/* harmony export */   "cloneObjDeeply": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.cloneObjDeeply),
/* harmony export */   "deepObjectExtend": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.deepObjectExtend),
/* harmony export */   "deepObjectCloningExtend": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.deepObjectCloningExtend),
/* harmony export */   "extend": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.extend),
/* harmony export */   "extendDecorate": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.extendDecorate),
/* harmony export */   "shallowExtend": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.shallowExtend),
/* harmony export */   "includesTypeCoercion": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.includesTypeCoercion),
/* harmony export */   "nestedPropertyValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedPropertyValue),
/* harmony export */   "getNestedPropertyValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.getNestedPropertyValue),
/* harmony export */   "hasNestedPropertyValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.hasNestedPropertyValue),
/* harmony export */   "setNestedPropertyValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.setNestedPropertyValue),
/* harmony export */   "isUndefined": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isUndefined),
/* harmony export */   "isInt": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isInt),
/* harmony export */   "ctypeDigit": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.ctypeDigit),
/* harmony export */   "isIntegerOrIntegerStr": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isIntegerOrIntegerStr),
/* harmony export */   "isCallable": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isCallable),
/* harmony export */   "findIndex": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.findIndex),
/* harmony export */   "firstPropValue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.firstPropValue),
/* harmony export */   "isStrictlyTrue": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isStrictlyTrue),
/* harmony export */   "isTruthy": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isTruthy),
/* harmony export */   "allTruthy": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.allTruthy),
/* harmony export */   "allNotUndefined": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.allNotUndefined),
/* harmony export */   "isJSONString": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.isJSONString),
/* harmony export */   "noOpFn": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.noOpFn),
/* harmony export */   "is": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.is),
/* harmony export */   "shallowEqual": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.shallowEqual),
/* harmony export */   "objectPropEqual": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.objectPropEqual),
/* harmony export */   "partialShallowEqual": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.partialShallowEqual),
/* harmony export */   "shallowObjectDiff": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.shallowObjectDiff),
/* harmony export */   "nestedMapSet": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedMapSet),
/* harmony export */   "nestedMapHas": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedMapHas),
/* harmony export */   "nestedMapGet": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedMapGet),
/* harmony export */   "nestedTreeMapSet": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedTreeMapSet),
/* harmony export */   "nestedTreeMapHas": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedTreeMapHas),
/* harmony export */   "nestedTreeMapGet": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.nestedTreeMapGet),
/* harmony export */   "mapYield": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.mapYield),
/* harmony export */   "str": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.str),
/* harmony export */   "mapObject": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.mapObject),
/* harmony export */   "mapToObject": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.mapToObject),
/* harmony export */   "propSelection": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.propSelection),
/* harmony export */   "prototypeChainProperties": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.prototypeChainProperties),
/* harmony export */   "prop": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.prop),
/* harmony export */   "defineProperty": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.defineProperty),
/* harmony export */   "completeObjectAssign": () => (/* reexport safe */ _modules_core__WEBPACK_IMPORTED_MODULE_0__.completeObjectAssign),
/* harmony export */   "_": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__._),
/* harmony export */   "proceedCallingFn": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.proceedCallingFn),
/* harmony export */   "curry": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.curry),
/* harmony export */   "POJOCurry": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.POJOCurry),
/* harmony export */   "compose": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.compose),
/* harmony export */   "pipe": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.pipe),
/* harmony export */   "pick": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.pick),
/* harmony export */   "liftBinaryFn": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.liftBinaryFn),
/* harmony export */   "juxt": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.juxt),
/* harmony export */   "converge": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.converge),
/* harmony export */   "execIfPOJOHas": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.execIfPOJOHas),
/* harmony export */   "execWithExistentProps": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.execWithExistentProps),
/* harmony export */   "forGen": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.forGen),
/* harmony export */   "flatten": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.flatten),
/* harmony export */   "flattenDeep": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.flattenDeep),
/* harmony export */   "cartesianProduct": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.cartesianProduct),
/* harmony export */   "identityFn": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.identityFn),
/* harmony export */   "identityArgsFn": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.identityArgsFn),
/* harmony export */   "chain": () => (/* reexport safe */ _modules_fn__WEBPACK_IMPORTED_MODULE_1__.chain),
/* harmony export */   "stringHashArray": () => (/* reexport safe */ _modules_hash__WEBPACK_IMPORTED_MODULE_2__.stringHashArray),
/* harmony export */   "hashString": () => (/* reexport safe */ _modules_hash__WEBPACK_IMPORTED_MODULE_2__.hashString),
/* harmony export */   "onePassStringHash": () => (/* reexport safe */ _modules_hash__WEBPACK_IMPORTED_MODULE_2__.onePassStringHash),
/* harmony export */   "intSumHash": () => (/* reexport safe */ _modules_hash__WEBPACK_IMPORTED_MODULE_2__.intSumHash),
/* harmony export */   "timeout": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.timeout),
/* harmony export */   "minDelayPromise": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.minDelayPromise),
/* harmony export */   "maxDelayFallbackPromise": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.maxDelayFallbackPromise),
/* harmony export */   "applyAsync": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.applyAsync),
/* harmony export */   "composeAsync": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.composeAsync),
/* harmony export */   "asSoonAtLeastSomeFulfilled": () => (/* reexport safe */ _modules_promise__WEBPACK_IMPORTED_MODULE_3__.asSoonAtLeastSomeFulfilled),
/* harmony export */   "buildQueryString": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.buildQueryString),
/* harmony export */   "formData": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.formData),
/* harmony export */   "xhr": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.xhr),
/* harmony export */   "checkNetwork": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.checkNetwork),
/* harmony export */   "waitNetwork": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.waitNetwork),
/* harmony export */   "setCookie": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.setCookie),
/* harmony export */   "getCookie": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getCookie),
/* harmony export */   "unsetCookie": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.unsetCookie),
/* harmony export */   "isInViewport": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.isInViewport),
/* harmony export */   "isScrolledIntoView": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.isScrolledIntoView),
/* harmony export */   "hasVerticalScrollbar": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.hasVerticalScrollbar),
/* harmony export */   "hasHorizontalScrollbar": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.hasHorizontalScrollbar),
/* harmony export */   "elementUniqueId": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.elementUniqueId),
/* harmony export */   "getElementComputedStyle": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getElementComputedStyle),
/* harmony export */   "elementInnerDimensions": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.elementInnerDimensions),
/* harmony export */   "countTextareaLines": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.countTextareaLines),
/* harmony export */   "isScrollOnBottom": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.isScrollOnBottom),
/* harmony export */   "getVerticalScrollBarWidth": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getVerticalScrollBarWidth),
/* harmony export */   "isEllipsisActive": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.isEllipsisActive),
/* harmony export */   "copyTextToClipboard": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.copyTextToClipboard),
/* harmony export */   "rAFLooper": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.rAFLooper),
/* harmony export */   "nestedRAF": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.nestedRAF),
/* harmony export */   "getRawURIFragment": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getRawURIFragment),
/* harmony export */   "getDecodedURIFragment": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getDecodedURIFragment),
/* harmony export */   "appendEncodedJSONFragmentToURI": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.appendEncodedJSONFragmentToURI),
/* harmony export */   "getDecodedJSONFromFragmentURI": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getDecodedJSONFromFragmentURI),
/* harmony export */   "getQueryStringArgsMultiDim": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getQueryStringArgsMultiDim),
/* harmony export */   "cursorFocus": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.cursorFocus),
/* harmony export */   "parseQueryStringArgsMultiDim": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.parseQueryStringArgsMultiDim),
/* harmony export */   "detectWrapped": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.detectWrapped),
/* harmony export */   "maxNestingLevel": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.maxNestingLevel),
/* harmony export */   "getScrollableAncestor": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.getScrollableAncestor),
/* harmony export */   "smoothScrollToTop": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.smoothScrollToTop),
/* harmony export */   "downloadFile": () => (/* reexport safe */ _modules_web__WEBPACK_IMPORTED_MODULE_4__.downloadFile),
/* harmony export */   "randomInt": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomInt),
/* harmony export */   "randomFloat": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomFloat),
/* harmony export */   "randomStr": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomStr),
/* harmony export */   "randomString": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomString),
/* harmony export */   "randomDifferentFromValue": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomDifferentFromValue),
/* harmony export */   "randomArrayShuffle": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.randomArrayShuffle),
/* harmony export */   "uuid": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.uuid),
/* harmony export */   "noncanonicalUUID": () => (/* reexport safe */ _modules_rand__WEBPACK_IMPORTED_MODULE_5__.noncanonicalUUID),
/* harmony export */   "time": () => (/* reexport safe */ _modules_time__WEBPACK_IMPORTED_MODULE_6__.time),
/* harmony export */   "msToTime": () => (/* reexport safe */ _modules_time__WEBPACK_IMPORTED_MODULE_6__.msToTime),
/* harmony export */   "millisecToSec": () => (/* reexport safe */ _modules_time__WEBPACK_IMPORTED_MODULE_6__.millisecToSec),
/* harmony export */   "secondsToTimeString": () => (/* reexport safe */ _modules_time__WEBPACK_IMPORTED_MODULE_6__.secondsToTimeString),
/* harmony export */   "escapeRegExp": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.escapeRegExp),
/* harmony export */   "trimCharacterMask": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.trimCharacterMask),
/* harmony export */   "trimCharacterRegex": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.trimCharacterRegex),
/* harmony export */   "trim": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.trim),
/* harmony export */   "trimLeft": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.trimLeft),
/* harmony export */   "trimRight": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.trimRight),
/* harmony export */   "concatWithInnerOuterSeparators": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.concatWithInnerOuterSeparators),
/* harmony export */   "optionsValueLabel": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.optionsValueLabel),
/* harmony export */   "startsWith": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.startsWith),
/* harmony export */   "ucaseFirst": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.ucaseFirst),
/* harmony export */   "reverseString": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.reverseString),
/* harmony export */   "separateIntThousands": () => (/* reexport safe */ _modules_string__WEBPACK_IMPORTED_MODULE_7__.separateIntThousands),
/* harmony export */   "googleMapBestZoomLevelFromBounds": () => (/* reexport safe */ _modules_google__WEBPACK_IMPORTED_MODULE_8__.googleMapBestZoomLevelFromBounds),
/* harmony export */   "delay": () => (/* reexport safe */ _modules_callback__WEBPACK_IMPORTED_MODULE_9__.delay),
/* harmony export */   "debounce": () => (/* reexport safe */ _modules_callback__WEBPACK_IMPORTED_MODULE_9__.debounce),
/* harmony export */   "throttle": () => (/* reexport safe */ _modules_callback__WEBPACK_IMPORTED_MODULE_9__.throttle),
/* harmony export */   "basename": () => (/* reexport safe */ _modules_path__WEBPACK_IMPORTED_MODULE_10__.basename),
/* harmony export */   "pathinfo": () => (/* reexport safe */ _modules_path__WEBPACK_IMPORTED_MODULE_10__.pathinfo),
/* harmony export */   "filenameExtension": () => (/* reexport safe */ _modules_path__WEBPACK_IMPORTED_MODULE_10__.filenameExtension),
/* harmony export */   "dirname": () => (/* reexport safe */ _modules_path__WEBPACK_IMPORTED_MODULE_10__.dirname),
/* harmony export */   "b2d": () => (/* reexport safe */ _modules_convert__WEBPACK_IMPORTED_MODULE_11__.b2d),
/* harmony export */   "d2b": () => (/* reexport safe */ _modules_convert__WEBPACK_IMPORTED_MODULE_11__.d2b),
/* harmony export */   "turnNthBitOff": () => (/* reexport safe */ _modules_bitwise__WEBPACK_IMPORTED_MODULE_12__.turnNthBitOff),
/* harmony export */   "turnNthBitOn": () => (/* reexport safe */ _modules_bitwise__WEBPACK_IMPORTED_MODULE_12__.turnNthBitOn),
/* harmony export */   "toggleNthBit": () => (/* reexport safe */ _modules_bitwise__WEBPACK_IMPORTED_MODULE_12__.toggleNthBit),
/* harmony export */   "checkNthBitOn": () => (/* reexport safe */ _modules_bitwise__WEBPACK_IMPORTED_MODULE_12__.checkNthBitOn),
/* harmony export */   "getLuminance": () => (/* reexport safe */ _modules_color__WEBPACK_IMPORTED_MODULE_13__.getLuminance),
/* harmony export */   "intToRGBHexString": () => (/* reexport safe */ _modules_color__WEBPACK_IMPORTED_MODULE_13__.intToRGBHexString),
/* harmony export */   "colorFromString": () => (/* reexport safe */ _modules_color__WEBPACK_IMPORTED_MODULE_13__.colorFromString),
/* harmony export */   "yieldCombinationsWithoutRepetition": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.yieldCombinationsWithoutRepetition),
/* harmony export */   "uniqueProgressiveIncrementalCombinations": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.uniqueProgressiveIncrementalCombinations),
/* harmony export */   "yieldUniqueProgressiveIncrementalCombinations": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.yieldUniqueProgressiveIncrementalCombinations),
/* harmony export */   "yieldAllSubsequences": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.yieldAllSubsequences),
/* harmony export */   "yieldUniqueSubsequences": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.yieldUniqueSubsequences),
/* harmony export */   "yieldPermutations": () => (/* reexport safe */ _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__.yieldPermutations),
/* harmony export */   "round": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.round),
/* harmony export */   "sum": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.sum),
/* harmony export */   "intDiv": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.intDiv),
/* harmony export */   "isEven": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.isEven),
/* harmony export */   "isOdd": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.isOdd),
/* harmony export */   "proportion": () => (/* reexport safe */ _modules_math__WEBPACK_IMPORTED_MODULE_15__.proportion),
/* harmony export */   "unshiftArray": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.unshiftArray),
/* harmony export */   "cloneArray": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.cloneArray),
/* harmony export */   "arraySliceFromValueToValue": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.arraySliceFromValueToValue),
/* harmony export */   "areArrayItemsAllCoercibleToNumber": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.areArrayItemsAllCoercibleToNumber),
/* harmony export */   "arrayOrArrayLike": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.arrayOrArrayLike),
/* harmony export */   "lastOfArray": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.lastOfArray),
/* harmony export */   "firstOfArray": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.firstOfArray),
/* harmony export */   "arrayFindReverse": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.arrayFindReverse),
/* harmony export */   "arrayMax": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.arrayMax),
/* harmony export */   "arrayMin": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.arrayMin),
/* harmony export */   "sortNums": () => (/* reexport safe */ _modules_array__WEBPACK_IMPORTED_MODULE_16__.sortNums),
/* harmony export */   "objectMin": () => (/* reexport safe */ _modules_object__WEBPACK_IMPORTED_MODULE_17__.objectMin),
/* harmony export */   "mean": () => (/* reexport safe */ _modules_stats__WEBPACK_IMPORTED_MODULE_18__.mean),
/* harmony export */   "median": () => (/* reexport safe */ _modules_stats__WEBPACK_IMPORTED_MODULE_18__.median),
/* harmony export */   "minAbsDeviationFromValue": () => (/* reexport safe */ _modules_stats__WEBPACK_IMPORTED_MODULE_18__.minAbsDeviationFromValue),
/* harmony export */   "minAbsDeviationFromExcludedValue": () => (/* reexport safe */ _modules_stats__WEBPACK_IMPORTED_MODULE_18__.minAbsDeviationFromExcludedValue),
/* harmony export */   "clampLat": () => (/* reexport safe */ _modules_map_coordinates__WEBPACK_IMPORTED_MODULE_19__.clampLat),
/* harmony export */   "wrapLng": () => (/* reexport safe */ _modules_map_coordinates__WEBPACK_IMPORTED_MODULE_19__.wrapLng),
/* harmony export */   "normalizeLat": () => (/* reexport safe */ _modules_map_coordinates__WEBPACK_IMPORTED_MODULE_19__.normalizeLat),
/* harmony export */   "normalizeLng": () => (/* reexport safe */ _modules_map_coordinates__WEBPACK_IMPORTED_MODULE_19__.normalizeLng),
/* harmony export */   "xrange": () => (/* reexport safe */ _modules_iterator__WEBPACK_IMPORTED_MODULE_20__.xrange),
/* harmony export */   "isValidDate": () => (/* reexport safe */ _modules_date__WEBPACK_IMPORTED_MODULE_21__.isValidDate),
/* harmony export */   "isValidDateTimeStr": () => (/* reexport safe */ _modules_date__WEBPACK_IMPORTED_MODULE_21__.isValidDateTimeStr),
/* harmony export */   "utcDate": () => (/* reexport safe */ _modules_date__WEBPACK_IMPORTED_MODULE_21__.utcDate),
/* harmony export */   "filterInt": () => (/* reexport safe */ _modules_constraint__WEBPACK_IMPORTED_MODULE_22__.filterInt),
/* harmony export */   "filterFloat": () => (/* reexport safe */ _modules_constraint__WEBPACK_IMPORTED_MODULE_22__.filterFloat),
/* harmony export */   "isValidHttpUrl": () => (/* reexport safe */ _modules_validate__WEBPACK_IMPORTED_MODULE_23__.isValidHttpUrl)
/* harmony export */ });
/* harmony import */ var _modules_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/core */ "./src/modules/core/index.js");
/* harmony import */ var _modules_fn__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/fn */ "./src/modules/fn.js");
/* harmony import */ var _modules_hash__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/hash */ "./src/modules/hash.js");
/* harmony import */ var _modules_promise__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/promise */ "./src/modules/promise.js");
/* harmony import */ var _modules_web__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./modules/web */ "./src/modules/web.js");
/* harmony import */ var _modules_rand__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./modules/rand */ "./src/modules/rand.js");
/* harmony import */ var _modules_time__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./modules/time */ "./src/modules/time.js");
/* harmony import */ var _modules_string__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./modules/string */ "./src/modules/string.js");
/* harmony import */ var _modules_google__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./modules/google */ "./src/modules/google.js");
/* harmony import */ var _modules_callback__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./modules/callback */ "./src/modules/callback.js");
/* harmony import */ var _modules_path__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./modules/path */ "./src/modules/path.js");
/* harmony import */ var _modules_convert__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./modules/convert */ "./src/modules/convert.js");
/* harmony import */ var _modules_bitwise__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./modules/bitwise */ "./src/modules/bitwise.js");
/* harmony import */ var _modules_color__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./modules/color */ "./src/modules/color.js");
/* harmony import */ var _modules_combinatorics__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./modules/combinatorics */ "./src/modules/combinatorics.js");
/* harmony import */ var _modules_math__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./modules/math */ "./src/modules/math.js");
/* harmony import */ var _modules_array__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./modules/array */ "./src/modules/array.js");
/* harmony import */ var _modules_object__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./modules/object */ "./src/modules/object.js");
/* harmony import */ var _modules_stats__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./modules/stats */ "./src/modules/stats.js");
/* harmony import */ var _modules_map_coordinates__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./modules/map-coordinates */ "./src/modules/map-coordinates.js");
/* harmony import */ var _modules_iterator__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./modules/iterator */ "./src/modules/iterator.js");
/* harmony import */ var _modules_date__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./modules/date */ "./src/modules/date.js");
/* harmony import */ var _modules_constraint__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./modules/constraint */ "./src/modules/constraint.js");
/* harmony import */ var _modules_validate__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./modules/validate */ "./src/modules/validate.js");
/*
 * Copyright (c) 2022 Anton Bagdatyev (Tonix)
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * Public API exposed to client code.
 */


























})();

/******/ 	return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=js-utl.js.map