simple-phone-mask
Version:
A lightweight and customizable phone number input mask with country flags and selection.
141 lines (128 loc) • 24.8 kB
JavaScript
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["SimplePhoneMask"] = factory();
else
root["SimplePhoneMask"] = factory();
})(this, function() {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/country-data.js":
/*!*****************************!*\
!*** ./src/country-data.js ***!
\*****************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ countryData: function() { return /* binding */ countryData; }\n/* harmony export */ });\nconst countryData = {\n UA: {\n name: 'Ukraine',\n phoneCode: '+380',\n flag: 'https://flagcdn.com/ua.svg',\n mask: '(__) ___-__-__'\n },\n US: {\n name: 'United States',\n phoneCode: '+1',\n flag: 'https://flagcdn.com/us.svg',\n mask: '(___) ___-____'\n },\n GB: {\n name: 'United Kingdom',\n phoneCode: '+44',\n flag: 'https://flagcdn.com/gb.svg',\n mask: '____ ______'\n },\n DE: {\n name: 'Germany',\n phoneCode: '+49',\n flag: 'https://flagcdn.com/de.svg',\n mask: '(__) ____ ____'\n },\n FR: {\n name: 'France',\n phoneCode: '+33',\n flag: 'https://flagcdn.com/fr.svg',\n mask: '_ __ __ __ __'\n },\n PL: {\n name: 'Poland',\n phoneCode: '+48',\n flag: 'https://flagcdn.com/pl.svg',\n mask: '___-___-___'\n },\n IT: {\n name: 'Italy',\n phoneCode: '+39',\n flag: 'https://flagcdn.com/it.svg',\n mask: '(___) ____-____'\n },\n ES: {\n name: 'Spain',\n phoneCode: '+34',\n flag: 'https://flagcdn.com/es.svg',\n mask: '(___) ___-___'\n },\n NL: {\n name: 'Netherlands',\n phoneCode: '+31',\n flag: 'https://flagcdn.com/nl.svg',\n mask: '__ ________'\n },\n CZ: {\n name: 'Czech Republic',\n phoneCode: '+420',\n flag: 'https://flagcdn.com/cz.svg',\n mask: '___-___-___'\n },\n RU: {\n name: 'Russia',\n phoneCode: '+7',\n flag: 'https://flagcdn.com/ru.svg',\n mask: '(___) ___-__-__'\n },\n CN: {\n name: 'China',\n phoneCode: '+86',\n flag: 'https://flagcdn.com/cn.svg',\n mask: '(___) ____-____'\n },\n JP: {\n name: 'Japan',\n phoneCode: '+81',\n flag: 'https://flagcdn.com/jp.svg',\n mask: '(__) ____-____'\n },\n KR: {\n name: 'South Korea',\n phoneCode: '+82',\n flag: 'https://flagcdn.com/kr.svg',\n mask: '(__) ____-____'\n },\n IN: {\n name: 'India',\n phoneCode: '+91',\n flag: 'https://flagcdn.com/in.svg',\n mask: '(___) ___-____'\n },\n BR: {\n name: 'Brazil',\n phoneCode: '+55',\n flag: 'https://flagcdn.com/br.svg',\n mask: '(___) ____-____'\n },\n MX: {\n name: 'Mexico',\n phoneCode: '+52',\n flag: 'https://flagcdn.com/mx.svg',\n mask: '(___) ___-____'\n },\n AU: {\n name: 'Australia',\n phoneCode: '+61',\n flag: 'https://flagcdn.com/au.svg',\n mask: '_ ____ ____'\n },\n NZ: {\n name: 'New Zealand',\n phoneCode: '+64',\n flag: 'https://flagcdn.com/nz.svg',\n mask: '_ ___ ____'\n },\n CA: {\n name: 'Canada',\n phoneCode: '+1',\n flag: 'https://flagcdn.com/ca.svg',\n mask: '(___) ___-____'\n },\n IE: {\n name: 'Ireland',\n phoneCode: '+353',\n flag: 'https://flagcdn.com/ie.svg',\n mask: '(__) ___-____'\n },\n SE: {\n name: 'Sweden',\n phoneCode: '+46',\n flag: 'https://flagcdn.com/se.svg',\n mask: '(__) ___-____'\n },\n NO: {\n name: 'Norway',\n phoneCode: '+47',\n flag: 'https://flagcdn.com/no.svg',\n mask: '__ __ __ __'\n },\n DK: {\n name: 'Denmark',\n phoneCode: '+45',\n flag: 'https://flagcdn.com/dk.svg',\n mask: '__ __ __ __'\n },\n FI: {\n name: 'Finland',\n phoneCode: '+358',\n flag: 'https://flagcdn.com/fi.svg',\n mask: '(__) ___-____'\n },\n AT: {\n name: 'Austria',\n phoneCode: '+43',\n flag: 'https://flagcdn.com/at.svg',\n mask: '(__) ___-____'\n },\n CH: {\n name: 'Switzerland',\n phoneCode: '+41',\n flag: 'https://flagcdn.com/ch.svg',\n mask: '(__) ___-____'\n },\n BE: {\n name: 'Belgium',\n phoneCode: '+32',\n flag: 'https://flagcdn.com/be.svg',\n mask: '(__) ___-____'\n },\n PT: {\n name: 'Portugal',\n phoneCode: '+351',\n flag: 'https://flagcdn.com/pt.svg',\n mask: '___-___-___'\n },\n GR: {\n name: 'Greece',\n phoneCode: '+30',\n flag: 'https://flagcdn.com/gr.svg',\n mask: '(___) ___-____'\n },\n HU: {\n name: 'Hungary',\n phoneCode: '+36',\n flag: 'https://flagcdn.com/hu.svg',\n mask: '(__) ___-____'\n },\n RO: {\n name: 'Romania',\n phoneCode: '+40',\n flag: 'https://flagcdn.com/ro.svg',\n mask: '(__) ___-____'\n },\n BG: {\n name: 'Bulgaria',\n phoneCode: '+359',\n flag: 'https://flagcdn.com/bg.svg',\n mask: '(__) ___-____'\n },\n HR: {\n name: 'Croatia',\n phoneCode: '+385',\n flag: 'https://flagcdn.com/hr.svg',\n mask: '(__) ___-____'\n },\n RS: {\n name: 'Serbia',\n phoneCode: '+381',\n flag: 'https://flagcdn.com/rs.svg',\n mask: '(__) ___-____'\n },\n SK: {\n name: 'Slovakia',\n phoneCode: '+421',\n flag: 'https://flagcdn.com/sk.svg',\n mask: '(__) ___-____'\n },\n SI: {\n name: 'Slovenia',\n phoneCode: '+386',\n flag: 'https://flagcdn.com/si.svg',\n mask: '(__) ___-____'\n },\n IL: {\n name: 'Israel',\n phoneCode: '+972',\n flag: 'https://flagcdn.com/il.svg',\n mask: '___-___-____'\n },\n TR: {\n name: 'Turkey',\n phoneCode: '+90',\n flag: 'https://flagcdn.com/tr.svg',\n mask: '(___) ___-____'\n },\n AE: {\n name: 'United Arab Emirates',\n phoneCode: '+971',\n flag: 'https://flagcdn.com/ae.svg',\n mask: '(__) ___-____'\n },\n SA: {\n name: 'Saudi Arabia',\n phoneCode: '+966',\n flag: 'https://flagcdn.com/sa.svg',\n mask: '(__) ___-____'\n },\n EG: {\n name: 'Egypt',\n phoneCode: '+20',\n flag: 'https://flagcdn.com/eg.svg',\n mask: '(___) ___-____'\n },\n ZA: {\n name: 'South Africa',\n phoneCode: '+27',\n flag: 'https://flagcdn.com/za.svg',\n mask: '(__) ___-____'\n },\n SG: {\n name: 'Singapore',\n phoneCode: '+65',\n flag: 'https://flagcdn.com/sg.svg',\n mask: '____-____'\n },\n MY: {\n name: 'Malaysia',\n phoneCode: '+60',\n flag: 'https://flagcdn.com/my.svg',\n mask: '(__) ___-____'\n },\n TH: {\n name: 'Thailand',\n phoneCode: '+66',\n flag: 'https://flagcdn.com/th.svg',\n mask: '(__) ___-____'\n },\n VN: {\n name: 'Vietnam',\n phoneCode: '+84',\n flag: 'https://flagcdn.com/vn.svg',\n mask: '(___) ____-___'\n },\n PH: {\n name: 'Philippines',\n phoneCode: '+63',\n flag: 'https://flagcdn.com/ph.svg',\n mask: '(___) ___-____'\n },\n ID: {\n name: 'Indonesia',\n phoneCode: '+62',\n flag: 'https://flagcdn.com/id.svg',\n mask: '(___) ___-____'\n },\n AR: {\n name: 'Argentina',\n phoneCode: '+54',\n flag: 'https://flagcdn.com/ar.svg',\n mask: '(___) ___-____'\n },\n CL: {\n name: 'Chile',\n phoneCode: '+56',\n flag: 'https://flagcdn.com/cl.svg',\n mask: '(__) ___-____'\n },\n CO: {\n name: 'Colombia',\n phoneCode: '+57',\n flag: 'https://flagcdn.com/co.svg',\n mask: '(___) ___-____'\n },\n PE: {\n name: 'Peru',\n phoneCode: '+51',\n flag: 'https://flagcdn.com/pe.svg',\n mask: '(___) ___-____'\n }\n};\n\n//# sourceURL=webpack://SimplePhoneMask/./src/country-data.js?");
/***/ }),
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _simple_phone_mask__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./simple-phone-mask */ \"./src/simple-phone-mask.js\");\n/* harmony import */ var _simple_phone_mask_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./simple-phone-mask.css */ \"./src/simple-phone-mask.css\");\n\n\n__webpack_require__.g.SimplePhoneMask = _simple_phone_mask__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\n/* harmony default export */ __webpack_exports__[\"default\"] = (_simple_phone_mask__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n\n//# sourceURL=webpack://SimplePhoneMask/./src/index.js?");
/***/ }),
/***/ "./src/simple-phone-mask.js":
/*!**********************************!*\
!*** ./src/simple-phone-mask.js ***!
\**********************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _simple_phone_mask_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./simple-phone-mask.css */ \"./src/simple-phone-mask.css\");\n/* harmony import */ var _country_data__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./country-data */ \"./src/country-data.js\");\n\n\n\n/**\n * Class representing a phone number mask\n */\nclass SimplePhoneMask {\n /**\n * Create a phone mask\n * @param {string} selector - CSS selector for input elements\n * @param {Object} options - Configuration options\n * @param {string} [options.countryCode=\"UA\"] - Country code (e.g., 'UA', 'US', 'GB') or phone code (e.g., '+380', '+1', '+44')\n * @param {string} [options.maskPattern=null] - Custom mask pattern (overrides default country mask)\n * @param {boolean} [options.showFlag=true] - Show country flag\n * @param {boolean} [options.allowCountrySelect=true] - Allow country selection from dropdown\n * @param {boolean} [options.detectIP=false] - Detect country by IP\n */\n constructor(selector) {\n let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n this.selector = selector;\n\n // Normalize options with defaults\n const defaultOptions = {\n countryCode: 'UA',\n maskPattern: null,\n showFlag: true,\n allowCountrySelect: true,\n detectIP: false\n };\n this.options = {\n ...defaultOptions,\n ...options\n };\n\n // Get country data\n let country;\n if (this.options.countryCode.startsWith('+')) {\n // Find country by phone code\n const phoneCode = this.options.countryCode;\n country = Object.values(_country_data__WEBPACK_IMPORTED_MODULE_1__.countryData).find(c => c.phoneCode === phoneCode);\n } else {\n // Find country by country code\n country = _country_data__WEBPACK_IMPORTED_MODULE_1__.countryData[this.options.countryCode.toUpperCase()];\n }\n if (!country) {\n // console.error(`Invalid country code: ${this.options.countryCode}`);\n country = _country_data__WEBPACK_IMPORTED_MODULE_1__.countryData.UA; // Default to Ukraine\n }\n this.countryCode = country.phoneCode.replace('+', '');\n this.maskPattern = this.options.maskPattern || country.mask;\n this.prefixLength = this.countryCode.length + 1; // +1 for + symbol\n this.currentCountry = country;\n\n // Bind methods to preserve context\n this.createMask = this.createMask.bind(this);\n this.handleClick = this.handleClick.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleSelect = this.handleSelect.bind(this);\n this.handleCountrySelect = this.handleCountrySelect.bind(this);\n this.createDropdown = this.createDropdown.bind(this);\n this.initialize();\n }\n\n /**\n * Set cursor position in input element\n * @param {number} pos - Cursor position\n * @param {HTMLElement} elem - Input element\n * @param {boolean} [setFocus=false] - Whether to set focus on element\n */\n setCursorPosition(pos, elem) {\n let setFocus = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n if (setFocus) {\n elem.focus();\n }\n if (elem.setSelectionRange) {\n elem.setSelectionRange(pos, pos);\n } else if (elem.createTextRange) {\n let range = elem.createTextRange();\n range.collapse(true);\n range.moveEnd('character', pos);\n range.moveStart('character', pos);\n range.select();\n }\n }\n\n /**\n * Handle cursor position on click\n * @param {Event} e - Click event\n */\n handleClick(e) {\n const input = e.target;\n if (input.selectionStart < this.prefixLength + 1) {\n // Set focus to true only for click events\n this.setCursorPosition(this.prefixLength + 1, input, true);\n }\n }\n\n /**\n * Handle keyboard navigation\n * @param {KeyboardEvent} event - Keyboard event\n */\n handleKeyDown(event) {\n const input = event.target;\n const cursorPosition = input.selectionStart;\n if ((event.key === 'Backspace' || event.key === 'ArrowLeft' || event.key === 'ArrowUp') && cursorPosition <= this.prefixLength) {\n event.preventDefault();\n // Set focus to true for keyboard navigation\n this.setCursorPosition(this.prefixLength + 1, input, true);\n }\n\n // Prevent cursor from moving up when more than one digit is entered\n const digitsEntered = input.value.replace(/\\D/g, '').length - this.countryCode.length;\n if (event.key === 'ArrowUp' && digitsEntered > 1) {\n event.preventDefault();\n }\n\n // Ensure the mask is applied correctly and the cursor stays within the allowed range\n // This is crucial for maintaining the correct mask format and preventing the cursor from moving outside the allowed range\n }\n\n /**\n * Handle text selection\n * @param {Event} e - Select event\n */\n handleSelect(e) {\n const input = e.target;\n if (input.selectionStart < this.prefixLength + 1) {\n // Set focus to true only for select events\n this.setCursorPosition(this.prefixLength + 1, input, true);\n }\n }\n\n /**\n * Create mask for input value\n * @param {Event} event - Input event\n */\n createMask(event) {\n const input = event.target;\n const matrix = '+' + this.countryCode + ' ' + this.maskPattern;\n let i = 0;\n const def = matrix.replace(/\\D/g, '');\n let val = input.value.replace(/\\D/g, '');\n\n // Remove temporary protection of country code for debugging\n // if (!input.value.startsWith(\"+\" + this.countryCode)) {\n // val = def;\n // }\n\n input.value = matrix.replace(/./g, function (a) {\n if (/[_\\d]/.test(a) && i < val.length) {\n return val.charAt(i++);\n } else if (i >= val.length) {\n return '';\n } else {\n return a;\n }\n });\n if (event.type === 'blur') {\n if (input.value.length <= this.prefixLength + 1) {\n input.value = '+' + this.countryCode;\n }\n } else {\n this.setCursorPosition(input.value.length, input);\n }\n }\n\n /**\n * Create country selector dropdown\n * @param {HTMLElement} input - Input element\n */\n createDropdown(input) {\n if (!this.options.showFlag) return;\n const wrapper = document.createElement('div');\n wrapper.className = 'spm-wrapper';\n input.parentNode.insertBefore(wrapper, input);\n wrapper.appendChild(input);\n input.className += ' spm-input';\n const flagButton = document.createElement('div');\n flagButton.className = `spm-flag-button ${this.options.allowCountrySelect ? 'spm-flag-button--selectable' : 'spm-flag-button--non-selectable'}`;\n flagButton.innerHTML = `<img class=\"spm-flag-image\" src=\"${this.currentCountry.flag}\" alt=\"${this.currentCountry.name}\">`;\n wrapper.appendChild(flagButton);\n if (this.options.allowCountrySelect) {\n const dropdown = document.createElement('div');\n dropdown.className = 'spm-dropdown';\n Object.entries(_country_data__WEBPACK_IMPORTED_MODULE_1__.countryData).forEach(_ref => {\n let [code, country] = _ref;\n const option = document.createElement('div');\n option.className = 'spm-dropdown-option';\n option.innerHTML = `\n <img class=\"spm-flag-image\" src=\"${country.flag}\" alt=\"${country.name}\">\n <span class=\"spm-country-name\">${country.name}</span>\n <span class=\"spm-country-code\">${country.phoneCode}</span>\n `;\n option.addEventListener('click', () => this.handleCountrySelect(country, code, input));\n dropdown.appendChild(option);\n });\n wrapper.appendChild(dropdown);\n flagButton.addEventListener('click', () => {\n dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none';\n });\n document.addEventListener('click', e => {\n if (!wrapper.contains(e.target)) {\n dropdown.style.display = 'none';\n }\n });\n }\n }\n\n /**\n * Handle country selection from dropdown\n * @param {Object} country - Country data object\n * @param {string} code - Country code\n * @param {HTMLElement} input - Input element\n */\n handleCountrySelect(country, code, input) {\n this.countryCode = country.phoneCode.replace('+', '');\n this.maskPattern = this.options.maskPattern || country.mask;\n this.prefixLength = this.countryCode.length + 1;\n this.currentCountry = country;\n const flagButton = input.parentNode.querySelector('.spm-flag-button');\n flagButton.innerHTML = `<img class=\"spm-flag-image\" src=\"${country.flag}\" alt=\"${country.name}\">`;\n const dropdown = input.parentNode.querySelector('.spm-dropdown');\n dropdown.style.display = 'none';\n input.value = '+' + this.countryCode;\n this.createMask({\n type: 'input',\n target: input\n });\n }\n\n /**\n * Initialize mask for all matching inputs\n */\n async initialize() {\n if (this.options.detectIP) {\n try {\n const countryCode = await this.detectCountryByIP();\n this.options.countryCode = countryCode;\n\n // Update country data after IP detection\n const country = _country_data__WEBPACK_IMPORTED_MODULE_1__.countryData[countryCode];\n if (country) {\n this.countryCode = country.phoneCode.replace('+', '');\n this.maskPattern = this.options.maskPattern || country.mask;\n this.prefixLength = this.countryCode.length + 1;\n this.currentCountry = country;\n }\n } catch (error) {\n console.error('Failed to detect country by IP:', error);\n }\n }\n\n // Initialize inputs\n let inputs = document.querySelectorAll(this.selector);\n inputs.forEach(input => {\n if (this.options.showFlag) {\n this.createDropdown(input);\n }\n input.addEventListener('input', this.createMask);\n input.addEventListener('focus', this.createMask);\n input.addEventListener('blur', this.createMask);\n input.addEventListener('click', this.handleClick);\n input.addEventListener('keydown', this.handleKeyDown);\n input.addEventListener('select', this.handleSelect);\n input.value = '+' + this.countryCode;\n // Remove focus trigger\n this.createMask({\n type: 'input',\n target: input\n });\n });\n }\n\n /**\n * Detect country by IP\n * @returns {Promise<string>} - Country code\n */\n async detectCountryByIP() {\n try {\n const response = await fetch('https://ipapi.co/json/', {\n cache: 'no-store' // Disable caching\n });\n const data = await response.json();\n return data.country_code;\n } catch (error) {\n console.error('Error detecting country by IP:', error);\n return this.options.countryCode;\n }\n }\n\n /**\n * Destroy mask and remove all event listeners\n */\n destroy() {\n let inputs = document.querySelectorAll(this.selector);\n inputs.forEach(input => {\n input.removeEventListener('input', this.createMask);\n input.removeEventListener('focus', this.createMask);\n input.removeEventListener('blur', this.createMask);\n input.removeEventListener('click', this.handleClick);\n input.removeEventListener('keydown', this.handleKeyDown);\n input.removeEventListener('select', this.handleSelect);\n });\n }\n}\n\n// Export for use in modules\n/* harmony default export */ __webpack_exports__[\"default\"] = (SimplePhoneMask);\n\n//# sourceURL=webpack://SimplePhoneMask/./src/simple-phone-mask.js?");
/***/ }),
/***/ "./src/simple-phone-mask.css":
/*!***********************************!*\
!*** ./src/simple-phone-mask.css ***!
\***********************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n// extracted by mini-css-extract-plugin\n\n\n//# sourceURL=webpack://SimplePhoneMask/./src/simple-phone-mask.css?");
/***/ })
/******/ });
/************************************************************************/
/******/ // 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 */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(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 */
/******/ !function() {
/******/ __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 */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module can't be inlined because the eval devtool is used.
/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
/******/ __webpack_exports__ = __webpack_exports__["default"];
/******/
/******/ return __webpack_exports__;
/******/ })()
;
});