UNPKG

libphonenumber-js

Version:

A simpler (and smaller) rewrite of Google Android's libphonenumber library in javascript

451 lines (373 loc) 16.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _metadata = _interopRequireDefault(require("./metadata")); var _PhoneNumber = _interopRequireDefault(require("./PhoneNumber")); var _AsYouTypeState = _interopRequireDefault(require("./AsYouTypeState")); var _AsYouTypeFormatter = _interopRequireWildcard(require("./AsYouTypeFormatter")); var _AsYouTypeParser = _interopRequireWildcard(require("./AsYouTypeParser")); var _getCountryByCallingCode = _interopRequireDefault(require("./helpers/getCountryByCallingCode")); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj["default"] = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var USE_NON_GEOGRAPHIC_COUNTRY_CODE = false; var AsYouType = /*#__PURE__*/ function () { /** * @param {(string|object)?} [optionsOrDefaultCountry] - The default country used for parsing non-international phone numbers. Can also be an `options` object. * @param {Object} metadata */ function AsYouType(optionsOrDefaultCountry, metadata) { _classCallCheck(this, AsYouType); this.metadata = new _metadata["default"](metadata); var _this$getCountryAndCa = this.getCountryAndCallingCode(optionsOrDefaultCountry), _this$getCountryAndCa2 = _slicedToArray(_this$getCountryAndCa, 2), defaultCountry = _this$getCountryAndCa2[0], defaultCallingCode = _this$getCountryAndCa2[1]; this.defaultCountry = defaultCountry; this.defaultCallingCode = defaultCallingCode; this.reset(); } _createClass(AsYouType, [{ key: "getCountryAndCallingCode", value: function getCountryAndCallingCode(optionsOrDefaultCountry) { // Set `defaultCountry` and `defaultCallingCode` options. var defaultCountry; var defaultCallingCode; // Turns out `null` also has type "object". Weird. if (optionsOrDefaultCountry) { if (_typeof(optionsOrDefaultCountry) === 'object') { defaultCountry = optionsOrDefaultCountry.defaultCountry; defaultCallingCode = optionsOrDefaultCountry.defaultCallingCode; } else { defaultCountry = optionsOrDefaultCountry; } } if (defaultCountry && !this.metadata.hasCountry(defaultCountry)) { defaultCountry = undefined; } if (defaultCallingCode) { /* istanbul ignore if */ if (USE_NON_GEOGRAPHIC_COUNTRY_CODE) { if (this.metadata.isNonGeographicCallingCode(defaultCallingCode)) { defaultCountry = '001'; } } } return [defaultCountry, defaultCallingCode]; } /** * Inputs "next" phone number characters. * @param {string} text * @return {string} Formatted phone number characters that have been input so far. */ }, { key: "input", value: function input(text) { var _this$parser$input = this.parser.input(text, this.state), digits = _this$parser$input.digits, justLeadingPlus = _this$parser$input.justLeadingPlus; if (justLeadingPlus) { this.formattedOutput = '+'; } else if (digits) { this.determineTheCountryIfNeeded(); // Match the available formats by the currently available leading digits. if (this.state.nationalSignificantNumber) { this.formatter.narrowDownMatchingFormats(this.state); } var formattedNationalNumber; if (this.metadata.hasSelectedNumberingPlan()) { formattedNationalNumber = this.formatter.format(digits, this.state); } if (formattedNationalNumber === undefined) { // See if another national (significant) number could be re-extracted. if (this.parser.reExtractNationalSignificantNumber(this.state)) { this.determineTheCountryIfNeeded(); // If it could, then re-try formatting the new national (significant) number. var nationalDigits = this.state.getNationalDigits(); if (nationalDigits) { formattedNationalNumber = this.formatter.format(nationalDigits, this.state); } } } this.formattedOutput = formattedNationalNumber ? this.getFullNumber(formattedNationalNumber) : this.getNonFormattedNumber(); } return this.formattedOutput; } }, { key: "reset", value: function reset() { var _this = this; this.state = new _AsYouTypeState["default"]({ onCountryChange: function onCountryChange(country) { // Before version `1.6.0`, the official `AsYouType` formatter API // included the `.country` property of an `AsYouType` instance. // Since that property (along with the others) have been moved to // `this.state`, `this.country` property is emulated for compatibility // with the old versions. _this.country = country; }, onCallingCodeChange: function onCallingCodeChange(country, callingCode) { _this.metadata.selectNumberingPlan(country, callingCode); _this.formatter.reset(_this.metadata.numberingPlan, _this.state); _this.parser.reset(_this.metadata.numberingPlan); } }); this.formatter = new _AsYouTypeFormatter["default"]({ state: this.state, metadata: this.metadata }); this.parser = new _AsYouTypeParser["default"]({ defaultCountry: this.defaultCountry, defaultCallingCode: this.defaultCallingCode, metadata: this.metadata, state: this.state, onNationalSignificantNumberChange: function onNationalSignificantNumberChange() { _this.determineTheCountryIfNeeded(); _this.formatter.reset(_this.metadata.numberingPlan, _this.state); } }); this.state.reset(this.defaultCountry, this.defaultCallingCode); this.formattedOutput = ''; return this; } /** * Returns `true` if the phone number is being input in international format. * In other words, returns `true` if and only if the parsed phone number starts with a `"+"`. * @return {boolean} */ }, { key: "isInternational", value: function isInternational() { return this.state.international; } /** * Returns the "country calling code" part of the phone number. * Returns `undefined` if the number is not being input in international format. * Returns "country calling code" for "non-geographic" phone numbering plans too. * @return {string} [callingCode] */ }, { key: "getCallingCode", value: function getCallingCode() { return this.state.callingCode; } // A legacy alias. }, { key: "getCountryCallingCode", value: function getCountryCallingCode() { return this.getCallingCode(); } /** * Returns a two-letter country code of the phone number. * Returns `undefined` for "non-geographic" phone numbering plans. * Returns `undefined` if no phone number has been input yet. * @return {string} [country] */ }, { key: "getCountry", value: function getCountry() { var _this$state = this.state, digits = _this$state.digits, country = _this$state.country; // If no digits have been input yet, // then `this.country` is the `defaultCountry`. // Won't return the `defaultCountry` in such case. if (!digits) { return; } var countryCode = country; /* istanbul ignore if */ if (USE_NON_GEOGRAPHIC_COUNTRY_CODE) { // `AsYouType.getCountry()` returns `undefined` // for "non-geographic" phone numbering plans. if (countryCode === '001') { countryCode = undefined; } } return countryCode; } }, { key: "determineTheCountryIfNeeded", value: function determineTheCountryIfNeeded() { // Suppose a user enters a phone number in international format, // and there're several countries corresponding to that country calling code, // and a country has been derived from the number, and then // a user enters one more digit and the number is no longer // valid for the derived country, so the country should be re-derived // on every new digit in those cases. // // If the phone number is being input in national format, // then it could be a case when `defaultCountry` wasn't specified // when creating `AsYouType` instance, and just `defaultCallingCode` was specified, // and that "calling code" could correspond to a "non-geographic entity", // or there could be several countries corresponding to that country calling code. // In those cases, `this.country` is `undefined` and should be derived // from the number. Again, if country calling code is ambiguous, then // `this.country` should be re-derived with each new digit. // if (!this.state.country || this.isCountryCallingCodeAmbiguous()) { this.determineTheCountry(); } } // Prepends `+CountryCode ` in case of an international phone number }, { key: "getFullNumber", value: function getFullNumber(formattedNationalNumber) { var _this2 = this; if (this.isInternational()) { var prefix = function prefix(text) { return _this2.formatter.getInternationalPrefixBeforeCountryCallingCode(_this2.state, { spacing: text ? true : false }) + text; }; var callingCode = this.state.callingCode; if (!callingCode) { return prefix("".concat(this.state.getDigitsWithoutInternationalPrefix())); } if (!formattedNationalNumber) { return prefix(callingCode); } return prefix("".concat(callingCode, " ").concat(formattedNationalNumber)); } return formattedNationalNumber; } }, { key: "getNonFormattedNationalNumberWithPrefix", value: function getNonFormattedNationalNumberWithPrefix() { var _this$state2 = this.state, nationalSignificantNumber = _this$state2.nationalSignificantNumber, complexPrefixBeforeNationalSignificantNumber = _this$state2.complexPrefixBeforeNationalSignificantNumber, nationalPrefix = _this$state2.nationalPrefix; var number = nationalSignificantNumber; var prefix = complexPrefixBeforeNationalSignificantNumber || nationalPrefix; if (prefix) { number = prefix + number; } return number; } }, { key: "getNonFormattedNumber", value: function getNonFormattedNumber() { var nationalSignificantNumberMatchesInput = this.state.nationalSignificantNumberMatchesInput; return this.getFullNumber(nationalSignificantNumberMatchesInput ? this.getNonFormattedNationalNumberWithPrefix() : this.state.getNationalDigits()); } }, { key: "getNonFormattedTemplate", value: function getNonFormattedTemplate() { var number = this.getNonFormattedNumber(); if (number) { return number.replace(/[\+\d]/g, _AsYouTypeFormatter.DIGIT_PLACEHOLDER); } } }, { key: "isCountryCallingCodeAmbiguous", value: function isCountryCallingCodeAmbiguous() { var callingCode = this.state.callingCode; var countryCodes = this.metadata.getCountryCodesForCallingCode(callingCode); return countryCodes && countryCodes.length > 1; } // Determines the country of the phone number // entered so far based on the country phone code // and the national phone number. }, { key: "determineTheCountry", value: function determineTheCountry() { this.state.setCountry((0, _getCountryByCallingCode["default"])(this.isInternational() ? this.state.callingCode : this.defaultCallingCode, this.state.nationalSignificantNumber, this.metadata)); } /** * Returns an instance of `PhoneNumber` class. * Will return `undefined` if no national (significant) number * digits have been entered so far, or if no `defaultCountry` has been * set and the user enters a phone number not in international format. */ }, { key: "getNumber", value: function getNumber() { var _this$state3 = this.state, nationalSignificantNumber = _this$state3.nationalSignificantNumber, carrierCode = _this$state3.carrierCode; if (this.isInternational()) { if (!this.state.callingCode) { return; } } else { if (!this.state.country && !this.defaultCallingCode) { return; } } if (!nationalSignificantNumber) { return; } var countryCode = this.getCountry(); var callingCode = this.getCountryCallingCode() || this.defaultCallingCode; var phoneNumber = new _PhoneNumber["default"](countryCode || callingCode, nationalSignificantNumber, this.metadata.metadata); if (carrierCode) { phoneNumber.carrierCode = carrierCode; } // Phone number extensions are not supported by "As You Type" formatter. return phoneNumber; } /** * Returns `true` if the phone number is "possible". * Is just a shortcut for `PhoneNumber.isPossible()`. * @return {boolean} */ }, { key: "isPossible", value: function isPossible() { var phoneNumber = this.getNumber(); if (!phoneNumber) { return false; } return phoneNumber.isPossible(); } /** * Returns `true` if the phone number is "valid". * Is just a shortcut for `PhoneNumber.isValid()`. * @return {boolean} */ }, { key: "isValid", value: function isValid() { var phoneNumber = this.getNumber(); if (!phoneNumber) { return false; } return phoneNumber.isValid(); } /** * @deprecated * This method is used in `react-phone-number-input/source/input-control.js` * in versions before `3.0.16`. */ }, { key: "getNationalNumber", value: function getNationalNumber() { return this.state.nationalSignificantNumber; } /** * Returns the phone number characters entered by the user. * @return {string} */ }, { key: "getChars", value: function getChars() { return (this.state.international ? '+' : '') + this.state.digits; } /** * Returns the template for the formatted phone number. * @return {string} */ }, { key: "getTemplate", value: function getTemplate() { return this.formatter.getTemplate(this.state) || this.getNonFormattedTemplate() || ''; } }]); return AsYouType; }(); exports["default"] = AsYouType; //# sourceMappingURL=AsYouType.js.map