UNPKG

ng-payment-card

Version:

Customizable component with zero external dependencies.

688 lines (670 loc) 80.5 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('ng-payment-card', ['exports', '@angular/core', '@angular/forms', '@angular/common'], factory) : (factory((global['ng-payment-card'] = {}),global.ng.core,global.ng.forms,global.ng.common)); }(this, (function (exports,core,forms,common) { 'use strict'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * Collection of validation methods */ var CardValidator = /** @class */ (function () { function CardValidator() { } /** * Check if control contains numbers only */ /** * Check if control contains numbers only * @param {?} abstractCtrl * @return {?} */ CardValidator.numbersOnly = /** * Check if control contains numbers only * @param {?} abstractCtrl * @return {?} */ function (abstractCtrl) { /** @type {?} */ var ccNum = abstractCtrl.value; /** @type {?} */ var NUMBERS_ONLY = new RegExp(/^[0-9]+$/); return !NUMBERS_ONLY.test(ccNum) ? CardValidator.NUMBERS_ONLY_ERR : null; }; /** * Check checksum number in card number using Luhn algorithm */ /** * Check checksum number in card number using Luhn algorithm * @param {?} abstractCtr * @return {?} */ CardValidator.checksum = /** * Check checksum number in card number using Luhn algorithm * @param {?} abstractCtr * @return {?} */ function (abstractCtr) { /** @type {?} */ var ccNumber = abstractCtr.value; /** @type {?} */ var luhnArray = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]; /** @type {?} */ var length = ccNumber ? ccNumber.length : 0; /** @type {?} */ var sum = 0; /** @type {?} */ var shouldMultiply = true; while (length) { /** @type {?} */ var val = parseInt(ccNumber.charAt(--length), 10); sum += (shouldMultiply = !shouldMultiply) ? luhnArray[val] : val; } return !(sum && sum % 10 === 0) ? CardValidator.CHECKSUM_INVALID : null; }; /** * Check validity of the card */ /** * Check validity of the card * @param {?} formGroup * @return {?} */ CardValidator.expiration = /** * Check validity of the card * @param {?} formGroup * @return {?} */ function (formGroup) { /** @type {?} */ var expirationMonth = Number(formGroup.get('expirationMonth').value); /** @type {?} */ var expirationYear = Number(formGroup.get('expirationYear').value); /** @type {?} */ var expirationDate = new Date(expirationYear, expirationMonth + 1, 0); return new Date().getTime() > expirationDate.getTime() ? CardValidator.CARD_EXPIRED : null; }; /** * Custom error for alphanumeric input */ CardValidator.NUMBERS_ONLY_ERR = { numbersOnly: true, }; /** * Custom error for invalid checksum */ CardValidator.CHECKSUM_INVALID = { checksum: true, }; /** * Custom error for expired card */ CardValidator.CARD_EXPIRED = { expiration: true, }; return CardValidator; }()); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ function __values(o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @enum {string} */ var CardType = { AMERICAN_EXPRESS: 'American Express', DINERS: 'Diners', DINERS_CARTE_BLANCHE: 'Diners Carte Blanche', DISCOVER_CLUB: 'Discover Club', CHINA_UNIONPAY: 'China UnionPay', JCB: 'JCB', LASER: 'Laser', MAESTRO: 'Maestro', MASTERCARD: 'Mastercard', VISA_ELECTRON: 'Visa Electron', VISA: 'VISA', }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @type {?} */ var CARD_TYPES = new Map(); CARD_TYPES.set(CardType.AMERICAN_EXPRESS, new RegExp('^3[47]')); CARD_TYPES.set(CardType.DINERS, new RegExp('^36')); CARD_TYPES.set(CardType.DINERS_CARTE_BLANCHE, new RegExp('^30[0-5]')); CARD_TYPES.set(CardType.DISCOVER_CLUB, new RegExp('^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)')); CARD_TYPES.set(CardType.CHINA_UNIONPAY, new RegExp('^(62[0-9]{14,17})$')); CARD_TYPES.set(CardType.JCB, new RegExp('^35(2[89]|[3-8][0-9])')); CARD_TYPES.set(CardType.LASER, new RegExp('^(6304|6706|6709|6771)[0-9]{12,15}$')); CARD_TYPES.set(CardType.MAESTRO, new RegExp('^(50|5[6-8]|6)[0-9]{12,19}$')); CARD_TYPES.set(CardType.MASTERCARD, new RegExp('^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$')); CARD_TYPES.set(CardType.VISA_ELECTRON, new RegExp('^(4026|417500|4508|4844|491([37]))')); CARD_TYPES.set(CardType.VISA, new RegExp('^4')); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @enum {string} */ var Month = { JANUARY: '01', FEBRUARY: '02', MARCH: '03', APRIL: '04', MAY: '05', JUNE: '06', JULY: '07', AUGUST: '08', SEPTEMBER: '09', OCTOBER: '10', NOVEMBER: '11', DECEMBER: '12', }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var PaymentCardService = /** @class */ (function () { function PaymentCardService() { } /** * Return card type based on card number */ /** * Return card type based on card number * @param {?} ccNum * @return {?} */ PaymentCardService.getCardType = /** * Return card type based on card number * @param {?} ccNum * @return {?} */ function (ccNum) { var e_1, _a; try { for (var _b = __values(Array.from(PaymentCardService.cardTypes.entries())), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = __read(_c.value, 2), key = _d[0], val = _d[1]; if (ccNum .split(new RegExp('[ \\-]')) .join('') .match(val)) { return key; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } return null; }; /** * Return months in numerical format */ /** * Return months in numerical format * @return {?} */ PaymentCardService.getMonths = /** * Return months in numerical format * @return {?} */ function () { var e_2, _a; /** @type {?} */ var months = []; try { for (var _b = __values(Object.keys(Month)), _c = _b.next(); !_c.done; _c = _b.next()) { var key = _c.value; months.push(Month[key]); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } return months; }; /** * Return years based on current year */ /** * Return years based on current year * @return {?} */ PaymentCardService.getYears = /** * Return years based on current year * @return {?} */ function () { /** @type {?} */ var years = []; /** @type {?} */ var year = new Date().getFullYear(); for (var i = -2; i < 5; i++) { years.push(year + i); } return years; }; /** * Collection of card types */ PaymentCardService.cardTypes = CARD_TYPES; PaymentCardService.decorators = [ { type: core.Injectable } ]; return PaymentCardService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * NgPaymentCard without any dependencies other then ReactiveFormsModule */ var PaymentCardComponent = /** @class */ (function () { function PaymentCardComponent(_ccService, _fb) { this._ccService = _ccService; this._fb = _fb; /** * List of months */ this.months = []; /** * List of years */ this.years = []; /** * Validation message for missing payment card number */ this.ccNumMissingTxt = 'Card number is required'; /** * Validation message for too short payment card number */ this.ccNumTooShortTxt = 'Card number is too short'; /** * Validation message for too long payment card number */ this.ccNumTooLongTxt = 'Card number is too long'; /** * Validation message for payment card number that contains characters other than digits */ this.ccNumContainsLettersTxt = 'Card number can contain digits only'; /** * Validation message for invalid payment card number (Luhn's validation) */ this.ccNumChecksumInvalidTxt = 'Provided card number is invalid'; /** * Validation message for missing card holder name */ this.cardHolderMissingTxt = 'Card holder name is required'; /** * Validation message for too long card holder name */ this.cardHolderTooLongTxt = 'Card holder name is too long'; /** * Validation message for missing expiration month */ this.expirationMonthMissingTxt = 'Expiration month is required'; /** * Validation message for missing expiration year */ this.expirationYearMissingTxt = 'Expiration year is required'; /** * Validation message for missing CCV number */ this.ccvMissingTxt = 'CCV number is required'; /** * Validation message for too short CCV number */ this.ccvNumTooShortTxt = 'CCV number is too short'; /** * Validation message for too long CCV number */ this.ccvNumTooLongTxt = 'CCV number is too long'; /** * Validation message for incorrect CCV number containing characters other than digits */ this.ccvContainsLettersTxt = 'CCV number can contain digits only'; /** * Validation message for expired card */ this.cardExpiredTxt = 'Card has expired'; /** * Switch validation of the payment card number */ this.validateCCNum = true; /** * Switch validation of the payment card holder */ this.validateCardHolder = true; /** * Switch validation of the payment card expiration month */ this.validateExpirationMonth = true; /** * Switch validation of the payment card expiration year */ this.validateExpirationYear = true; /** * Switch validation of the payment card expiration */ this.validateCardExpiration = true; /** * Switch validation of the payment card CCV number */ this.validateCCV = true; /** * EventEmitter for payment card object */ this.formSaved = new core.EventEmitter(); } /** * @return {?} */ PaymentCardComponent.prototype.ngOnInit = /** * @return {?} */ function () { this.buildForm(); this.assignDateValues(); }; /** * Populate months and years */ /** * Populate months and years * @return {?} */ PaymentCardComponent.prototype.assignDateValues = /** * Populate months and years * @return {?} */ function () { this.months = PaymentCardService.getMonths(); this.years = PaymentCardService.getYears(); }; /** * Build reactive form */ /** * Build reactive form * @return {?} */ PaymentCardComponent.prototype.buildForm = /** * Build reactive form * @return {?} */ function () { this.ccForm = this._fb.group({ cardNumber: [ '', forms.Validators.compose([ forms.Validators.required, forms.Validators.minLength(12), forms.Validators.maxLength(19), CardValidator.numbersOnly, CardValidator.checksum, ]), ], cardHolder: ['', forms.Validators.compose([forms.Validators.required, forms.Validators.maxLength(22)])], expirationMonth: ['', forms.Validators.required], expirationYear: ['', forms.Validators.required], ccv: [ '', forms.Validators.compose([ forms.Validators.required, forms.Validators.minLength(3), forms.Validators.maxLength(4), CardValidator.numbersOnly, ]), ], }, { validator: CardValidator.expiration, }); }; /** * Returns payment card type based on payment card number */ /** * Returns payment card type based on payment card number * @param {?} ccNum * @return {?} */ PaymentCardComponent.prototype.getCardType = /** * Returns payment card type based on payment card number * @param {?} ccNum * @return {?} */ function (ccNum) { return PaymentCardService.getCardType(ccNum); }; /** * Callback function that emits payment card details after user clicks submit, or press enter */ /** * Callback function that emits payment card details after user clicks submit, or press enter * @return {?} */ PaymentCardComponent.prototype.emitSavedCard = /** * Callback function that emits payment card details after user clicks submit, or press enter * @return {?} */ function () { /** @type {?} */ var cardDetails = ( /** @type {?} */(this.ccForm.value)); this.formSaved.emit(cardDetails); }; PaymentCardComponent.decorators = [ { type: core.Component, args: [{ selector: 'ng-payment-card', template: "<section class=\"cc-wrapper\">\r\n <div class=\"cc-box\">\r\n <div #ccBoxFlip class=\"cc-box--flip\">\r\n <div class=\"cc-box__front\">\r\n <div class=\"cc-box__logo\">\r\n <p>{{getCardType(ccNumber.value) | uppercase}}</p>\r\n </div>\r\n <div class=\"cc-box__element\">\r\n <label class=\"cc-form__label\" for=\"cc-card-number-display\"></label>\r\n <input class=\"cc-form__input cc-form__input--transparent cc-form__input--embosed\" id=\"cc-card-number-display\"\r\n aria-label=\"Payment card number\" disabled=\"disabled\"\r\n [value]=\"ccForm.get('cardNumber').value | paymentCardNumber\">\r\n </div>\r\n <div class=\"cc-box__element\">\r\n <label class=\"cc-form__label\" for=\"cc-holder-display\">CARD HOLDER</label>\r\n <input class=\"cc-form__input cc-form__input--transparent cc-form__input--embosed\" id=\"cc-holder-display\"\r\n aria-label=\"Card holder\" disabled=\"disabled\" [value]=\"ccForm.get('cardHolder').value | uppercase\">\r\n </div>\r\n <div class=\"cc-box__element\">\r\n <label class=\"cc-form__label\" for=\"cc-valid-date-display\">VALID THRU</label>\r\n <input class=\"cc-form__input cc-form__input--left-align cc-form__input--transparent cc-form__input--embosed\"\r\n id=\"cc-valid-date-display\" aria-label=\"Card holder\" disabled=\"disabled\"\r\n [value]=\"ccForm.get('expirationMonth').value + '/' + ccForm.get('expirationYear').value | validThru\">\r\n </div>\r\n <div class=\"cc-box__chip\"></div>\r\n </div>\r\n <div class=\"cc-box__back\">\r\n <div class=\"cc-box__strip\">&nbsp;</div>\r\n <div class=\"cc-box__element\">\r\n <input class=\"cc-form__input cc-form__input--cursive cc-form__input--right-align\" id=\"cc-ccv-display\"\r\n aria-label=\"CCV\" disabled=\"disabled\"\r\n [value]=\"'CCV: ' + ccForm.get('ccv').value\" title=\"CCV\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <form class=\"cc-form\" [formGroup]=\"ccForm\" autocomplete=\"off\">\r\n <div class=\"cc-form__wrapper--long\">\r\n <label for=\"cc-number\" class=\"cc-form__label cc-form__label--first\">Card number</label>\r\n <input #ccNumber class=\"cc-form__input\" id=\"cc-number\" aria-label=\"Card number\"\r\n type=\"text\" title=\"Card number\" maxlength=\"19\" formControlName=\"cardNumber\"\r\n (focus)=\"ccBoxFlip.classList.remove('hover')\">\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCNum && ccForm.get('cardNumber').touched && ccForm.get('cardNumber').hasError('required')\">\r\n {{ccNumMissingTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCNum && ccForm.get('cardNumber').touched && ccForm.get('cardNumber').hasError('minlength')\">\r\n {{ccNumTooShortTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCNum && ccForm.get('cardNumber').touched && ccForm.get('cardNumber').hasError('maxlength')\">\r\n {{ccNumTooLongTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCNum && ccForm.get('cardNumber').touched && ccForm.get('cardNumber').hasError('numbersOnly')\">\r\n {{ccNumContainsLettersTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCNum && ccForm.get('cardNumber').touched && ccForm.get('cardNumber').hasError('checksum')\">\r\n {{ccNumChecksumInvalidTxt}}\r\n </div>\r\n </div>\r\n <div class=\"cc-form__wrapper--long\">\r\n <label for=\"cc-holder-name\" class=\"cc-form__label\">Card Holder name</label>\r\n <input class=\"cc-form__input\" id=\"cc-holder-name\" aria-label=\"Card holder name\" type=\"text\"\r\n title=\"Card holder name\" maxlength=\"22\" formControlName=\"cardHolder\"\r\n (focus)=\"ccBoxFlip.classList.remove('hover')\">\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCardHolder && ccForm.get('cardHolder').touched &&\r\n ccForm.get('cardHolder').hasError('required')\">\r\n {{cardHolderMissingTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCardHolder && ccForm.get('cardHolder').touched &&\r\n ccForm.get('cardHolder').hasError('maxlength')\">\r\n {{cardHolderTooLongTxt}}\r\n </div>\r\n </div>\r\n <div class=\"cc-form--inline\">\r\n <div class=\"cc-form__wrapper cc-form__wrapper--short\">\r\n <label for=\"cc-expiration-month\" class=\"cc-form__label\">Expiration month</label>\r\n <select id=\"cc-expiration-month\" class=\"cc-form__select\" aria-label=\"Expiration month\"\r\n formControlName=\"expirationMonth\">\r\n <option *ngFor=\"let month of months\" value=\"{{month}}\"\r\n (click)=\"ccBoxFlip.classList.remove('hover')\">{{month}}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"cc-form__wrapper cc-form__wrapper--short\">\r\n <label for=\"cc-expiration-year\" class=\"cc-form__label\">Expiration year</label>\r\n <select id=\"cc-expiration-year\" class=\"cc-form__select\" aria-label=\"Expiration year\"\r\n formControlName=\"expirationYear\">\r\n <option *ngFor=\"let year of years\" value=\"{{year}}\"\r\n (click)=\"ccBoxFlip.classList.remove('hover')\">{{year}}\r\n </option>\r\n </select>\r\n </div>\r\n <div class=\"cc-form__wrapper cc-form__wrapper--short cc-form__wrapper--last\">\r\n <label for=\"cc-ccv\" class=\"cc-form__label\">ccv</label>\r\n <input class=\"cc-form__input cc-form__input--short\" id=\"cc-ccv\" aria-label=\"CCV\" type=\"text\" title=\"CCV\"\r\n minlength=\"3\" maxlength=\"4\" formControlName=\"ccv\" (focus)=\"ccBoxFlip.classList.add('hover')\">\r\n </div>\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateExpirationMonth && ccForm.get('expirationMonth').touched &&\r\n ccForm.get('expirationMonth').hasError('required')\">\r\n {{expirationMonthMissingTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateExpirationMonth && ccForm.get('expirationYear').touched &&\r\n ccForm.get('expirationYear').hasError('required')\">\r\n {{expirationYearMissingTxt}}\r\n </div>\r\n <div class=\"cc-form__error\" *ngIf=\"validateCardExpiration && ccForm.get('expirationMonth').touched &&\r\n ccForm.get('expirationYear').touched && ccForm.hasError('expiration')\">\r\n {{cardExpiredTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCV && ccForm.get('ccv').touched && ccForm.get('ccv').hasError('required')\">\r\n {{ccvMissingTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCV && ccForm.get('ccv').touched && ccForm.get('ccv').hasError('minlength')\">\r\n {{ccvNumTooShortTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCV && ccForm.get('ccv').touched && ccForm.get('ccv').hasError('maxlength')\">\r\n {{ccvNumTooLongTxt}}\r\n </div>\r\n <div class=\"cc-form__error\"\r\n *ngIf=\"validateCCV && ccForm.get('ccv').touched && ccForm.get('ccv').hasError('numbersOnly')\">\r\n {{ccvContainsLettersTxt}}\r\n </div>\r\n <button type=\"submit\" class=\"cc-form__button cc-form__button--ripple\" aria-label=\"submit\" (click)=\"emitSavedCard()\"\r\n (keydown.enter)=\"emitSavedCard()\">Submit\r\n </button>\r\n </form>\r\n</section>\r\n", encapsulation: core.ViewEncapsulation.None, styles: ["@import url(https://fonts.googleapis.com/css?family=Inconsolata);.cc-form{align-items:center;display:flex;flex-flow:column;flex-wrap:wrap;height:100%;justify-content:center;width:100%}.cc-form--inline{align-items:inherit;display:inherit;flex-flow:row;flex-wrap:inherit;height:100%;justify-content:flex-end;margin-bottom:5%;width:100%}@media only screen and (max-width:1279px){.cc-form--inline{align-items:inherit;display:inherit;flex-flow:row;flex-wrap:inherit;height:100%;justify-content:flex-end;margin-bottom:5%;width:100%}}@media only screen and (max-width:599px){.cc-form--inline{align-items:center;display:inherit;flex-flow:column;flex-wrap:wrap;height:100%;justify-content:center;width:100%}}input[type=number]{-moz-appearance:textfield}input::-webkit-inner-spin-button,input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}@media only screen and (max-width:1919px){.cc-form__wrapper{margin-right:5%;margin-top:5%}.cc-form__wrapper--long{width:60%}.cc-form__wrapper--short{width:15%}.cc-form__wrapper--last{margin-left:5%;margin-right:20%;margin-top:30px}}@media only screen and (max-width:1279px){.cc-form__wrapper{margin-right:5%;margin-top:5%}.cc-form__wrapper--long{width:60%}.cc-form__wrapper--short{width:15%}.cc-form__wrapper--last{margin-left:5%;margin-right:20%}}@media only screen and (max-width:599px){.cc-form__wrapper{margin-right:0;margin-top:0}.cc-form__wrapper--long,.cc-form__wrapper--short{width:80%}.cc-form__wrapper--last{margin-left:0;margin-right:0}}.cc-form__label{color:rgba(0,0,0,.6);display:block;font-family:Inconsolata,Serif,serif;font-size:.7em;font-weight:400;letter-spacing:1px;line-height:10px;margin-bottom:5px;margin-top:5%;text-align:left;text-shadow:none;text-transform:uppercase;width:100%}.cc-form__label--first{margin-top:20%}.cc-form__select{-webkit-appearance:listbox;-moz-appearance:listbox;appearance:listbox}.cc-form__input,.cc-form__select{border:1px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:inset 0 1px 4px rgba(0,0,0,.2);color:#333;display:block;font-size:1.2em;height:38px;margin:0;outline:0;padding:0;text-align:left;width:100%}.cc-form__input--transparent{background:0 0;border:none;border-radius:0;box-shadow:none}.cc-form__input--embosed{color:#fff;font-family:Inconsolata,monospace;font-size:2vw;text-shadow:0 2px 1px rgba(0,0,0,.3)}@media only screen and (max-width:1279px){.cc-form__input--embosed{font-size:2.5vw}}@media only screen and (max-width:599px){.cc-form__input--embosed{font-size:3vw}}.cc-form__input--cursive{font-size:.7em;font-style:italic;left:0;margin:0 auto;position:absolute}.cc-form__input--right-align{padding-right:5%;text-align:right}.cc-form__input--left-align{text-align:left}.cc-form__input:focus,.cc-form__select:focus{border-color:#41acf4}.cc-form__error{color:#ff5b5f;font-size:.7em}.cc-form__button{background:#41acf4;border:0;border-radius:3px;color:#fff;cursor:pointer;margin-bottom:5%;margin-top:1%;outline:0;overflow:hidden;padding:1%;position:relative;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap;width:60%}.cc-form__button:hover{box-shadow:0 6px 8px -3px rgba(0,0,0,.3)}.cc-form__button:focus{background:#0e91ea}.cc-form__button--ripple{overflow:hidden;position:relative}.cc-form__button--ripple:after{background:rgba(255,255,255,.3);border-radius:80%;content:'';display:block;height:120px;left:50%;margin-left:-50%;margin-top:-60px;position:absolute;top:50%;-webkit-transform:scale(0);transform:scale(0);width:100%}.cc-form__button--ripple:not(:active):after{-webkit-animation:2s ease-out button-ripple;animation:2s ease-out button-ripple}@-webkit-keyframes button-ripple{0%{-webkit-transform:scale(0);transform:scale(0)}20%{-webkit-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(1);transform:scale(1)}}@keyframes button-ripple{0%{-webkit-transform:scale(0);transform:scale(0)}20%{-webkit-transform:scale(1);transform:scale(1)}100%{opacity:0;-webkit-transform:scale(1);transform:scale(1)}}.cc-wrapper{background-color:#fff;border-radius:20px;height:100%;margin:0;padding:0;width:100%}.cc-box{height:100px;margin:0 auto;padding:0;position:relative;-webkit-transform:translateY(-100%);transform:translateY(-100%);width:70%;z-index:1}@media only screen and (max-width:1279px){.cc-box{-webkit-transform:translateY(-115%);transform:translateY(-115%)}}@media only screen and (max-width:599px){.cc-box{-webkit-transform:translateY(-130%);transform:translateY(-130%)}}.cc-box--flip{-webkit-transform-style:preserve-3d;transform-style:preserve-3d;transition:.6s}.cc-box--flip.hover,.cc-box--flip:hover{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.cc-box__element{padding:0;width:80%}.cc-box__logo{align-items:center;color:#fff;display:flex;flex-flow:row nowrap;font-size:1.2em;font-style:italic;font-weight:700;justify-content:flex-end;margin-right:10%;width:100%}.cc-box__strip{background:linear-gradient(135deg,#404040,#1a1a1a);font-size:1.7em;margin:0;padding:0;position:relative;-webkit-transform:translateY(-90%);transform:translateY(-90%);width:100%}.cc-box__back,.cc-box__front{align-items:center;-webkit-backface-visibility:hidden;backface-visibility:hidden;background:linear-gradient(135deg,#bd6772,#53223f);border-radius:15px;display:flex;flex-direction:column;flex-flow:column nowrap;height:250px;justify-content:center;left:0;position:absolute;top:0;width:100%}.cc-box__front{-webkit-transform:rotateY(0);transform:rotateY(0)}.cc-box__back{-webkit-transform:rotateY(180deg);transform:rotateY(180deg)}.ng-invalid.ng-touched{border-color:#ff5b5f}.ng-valid.ng-touched{border-color:#b2b2b2}"] }] } ]; /** @nocollapse */ PaymentCardComponent.ctorParameters = function () { return [ { type: PaymentCardService }, { type: forms.FormBuilder } ]; }; PaymentCardComponent.propDecorators = { ccNumMissingTxt: [{ type: core.Input }], ccNumTooShortTxt: [{ type: core.Input }], ccNumTooLongTxt: [{ type: core.Input }], ccNumContainsLettersTxt: [{ type: core.Input }], ccNumChecksumInvalidTxt: [{ type: core.Input }], cardHolderMissingTxt: [{ type: core.Input }], cardHolderTooLongTxt: [{ type: core.Input }], expirationMonthMissingTxt: [{ type: core.Input }], expirationYearMissingTxt: [{ type: core.Input }], ccvMissingTxt: [{ type: core.Input }], ccvNumTooShortTxt: [{ type: core.Input }], ccvNumTooLongTxt: [{ type: core.Input }], ccvContainsLettersTxt: [{ type: core.Input }], cardExpiredTxt: [{ type: core.Input }], validateCCNum: [{ type: core.Input }], validateCardHolder: [{ type: core.Input }], validateExpirationMonth: [{ type: core.Input }], validateExpirationYear: [{ type: core.Input }], validateCardExpiration: [{ type: core.Input }], validateCCV: [{ type: core.Input }], formSaved: [{ type: core.Output }] }; return PaymentCardComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var PaymentCardNumberPipe = /** @class */ (function () { function PaymentCardNumberPipe() { } /** * Transform card number to card format for known numbers */ /** * Transform card number to card format for known numbers * @param {?} value * @return {?} */ PaymentCardNumberPipe.prototype.transform = /** * Transform card number to card format for known numbers * @param {?} value * @return {?} */ function (value) { switch (value.length) { case 15: value = value.replace(/\b(\d{4})/, '$1-'); value = value.replace(/-(\d{6})/, '-$1-'); return value; case 16: return value.match(/.{4}/g).join('-'); default: return value; } }; PaymentCardNumberPipe.decorators = [ { type: core.Pipe, args: [{ name: 'paymentCardNumber', },] } ]; return PaymentCardNumberPipe; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var ValidThruPipe = /** @class */ (function () { function ValidThruPipe() { } /** * Transform month and year into card format */ /** * Transform month and year into card format * @param {?} value * @return {?} */ ValidThruPipe.prototype.transform = /** * Transform month and year into card format * @param {?} value * @return {?} */ function (value) { return value && value.length === 7 ? value.substr(0, 3) + value.substr(5) : '/'; }; ValidThruPipe.decorators = [ { type: core.Pipe, args: [{ name: 'validThru', },] } ]; return ValidThruPipe; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * Monolithic module that is being bundled and published. * Depends only on ReactiveFormsModule and CommonModule. */ var NgPaymentCardModule = /** @class */ (function () { function NgPaymentCardModule() { } NgPaymentCardModule.decorators = [ { type: core.NgModule, args: [{ imports: [forms.ReactiveFormsModule, common.CommonModule], declarations: [PaymentCardComponent, PaymentCardNumberPipe, ValidThruPipe], providers: [PaymentCardService], exports: [PaymentCardComponent], },] } ]; return NgPaymentCardModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ exports.PaymentCardComponent = PaymentCardComponent; exports.NgPaymentCardModule = NgPaymentCardModule; exports.ɵb = PaymentCardNumberPipe; exports.ɵc = ValidThruPipe; exports.ɵa = PaymentCardService; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctcGF5bWVudC1jYXJkLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmctcGF5bWVudC1jYXJkL2xpYi92YWxpZGF0b3IvY2FyZC12YWxpZGF0b3IudHMiLCJub2RlX21vZHVsZXMvdHNsaWIvdHNsaWIuZXM2LmpzIiwibmc6Ly9uZy1wYXltZW50LWNhcmQvbGliL2RvbWFpbi9jYXJkLXR5cGUuZW51bS50cyIsIm5nOi8vbmctcGF5bWVudC1jYXJkL2xpYi9kb21haW4vY2FyZC10eXBlcy50cyIsIm5nOi8vbmctcGF5bWVudC1jYXJkL2xpYi9kb21haW4vbW9udGguZW51bS50cyIsIm5nOi8vbmctcGF5bWVudC1jYXJkL2xpYi9zZXJ2aWNlL3BheW1lbnQtY2FyZC5zZXJ2aWNlLnRzIiwibmc6Ly9uZy1wYXltZW50LWNhcmQvbGliL3BheW1lbnQtY2FyZC5jb21wb25lbnQudHMiLCJuZzovL25nLXBheW1lbnQtY2FyZC9saWIvcGlwZS9wYXltZW50LWNhcmQtbnVtYmVyL3BheW1lbnQtY2FyZC1udW1iZXIucGlwZS50cyIsIm5nOi8vbmctcGF5bWVudC1jYXJkL2xpYi9waXBlL3ZhbGlkLXRocnUvdmFsaWQtdGhydS5waXBlLnRzIiwibmc6Ly9uZy1wYXltZW50LWNhcmQvbGliL25nLXBheW1lbnQtY2FyZC5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRpb25FcnJvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbi8qKlxuICogQ29sbGVjdGlvbiBvZiB2YWxpZGF0aW9uIG1ldGhvZHNcbiAqL1xuZXhwb3J0IGNsYXNzIENhcmRWYWxpZGF0b3Ige1xuICAvKipcbiAgICogQ3VzdG9tIGVycm9yIGZvciBhbHBoYW51bWVyaWMgaW5wdXRcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIE5VTUJFUlNfT05MWV9FUlI6IFZhbGlkYXRpb25FcnJvcnMgPSB7XG4gICAgbnVtYmVyc09ubHk6IHRydWUsXG4gIH07XG5cbiAgLyoqXG4gICAqIEN1c3RvbSBlcnJvciBmb3IgaW52YWxpZCBjaGVja3N1bVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgQ0hFQ0tTVU1fSU5WQUxJRDogVmFsaWRhdGlvbkVycm9ycyA9IHtcbiAgICBjaGVja3N1bTogdHJ1ZSxcbiAgfTtcblxuICAvKipcbiAgICogQ3VzdG9tIGVycm9yIGZvciBleHBpcmVkIGNhcmRcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIENBUkRfRVhQSVJFRDogVmFsaWRhdGlvbkVycm9ycyA9IHtcbiAgICBleHBpcmF0aW9uOiB0cnVlLFxuICB9O1xuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBjb250cm9sIGNvbnRhaW5zIG51bWJlcnMgb25seVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBudW1iZXJzT25seShhYnN0cmFjdEN0cmw6IEFic3RyYWN0Q29udHJvbCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcbiAgICBjb25zdCBjY051bTogc3RyaW5nID0gYWJzdHJhY3RDdHJsLnZhbHVlO1xuICAgIGNvbnN0IE5VTUJFUlNfT05MWTogUmVnRXhwID0gbmV3IFJlZ0V4cCgvXlswLTldKyQvKTtcbiAgICByZXR1cm4gIU5VTUJFUlNfT05MWS50ZXN0KGNjTnVtKSA/IENhcmRWYWxpZGF0b3IuTlVNQkVSU19PTkxZX0VSUiA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgY2hlY2tzdW0gbnVtYmVyIGluIGNhcmQgbnVtYmVyIHVzaW5nIEx1aG4gYWxnb3JpdGhtXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNoZWNrc3VtKGFic3RyYWN0Q3RyOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgY29uc3QgY2NOdW1iZXI6IHN0cmluZyA9IGFic3RyYWN0Q3RyLnZhbHVlO1xuICAgIGNvbnN0IGx1aG5BcnJheTogQXJyYXk8bnVtYmVyPiA9IFswLCAyLCA0LCA2LCA4LCAxLCAzLCA1LCA3LCA5XTtcbiAgICBsZXQgbGVuZ3RoOiBudW1iZXIgPSBjY051bWJlciA/IGNjTnVtYmVyLmxlbmd0aCA6IDA7XG4gICAgbGV0IHN1bSA9IDA7XG4gICAgbGV0IHNob3VsZE11bHRpcGx5ID0gdHJ1ZTtcblxuICAgIHdoaWxlIChsZW5ndGgpIHtcbiAgICAgIGNvbnN0IHZhbDogbnVtYmVyID0gcGFyc2VJbnQoY2NOdW1iZXIuY2hhckF0KC0tbGVuZ3RoKSwgMTApO1xuICAgICAgc3VtICs9IChzaG91bGRNdWx0aXBseSA9ICFzaG91bGRNdWx0aXBseSkgPyBsdWhuQXJyYXlbdmFsXSA6IHZhbDtcbiAgICB9XG4gICAgcmV0dXJuICEoc3VtICYmIHN1bSAlIDEwID09PSAwKSA/IENhcmRWYWxpZGF0b3IuQ0hFQ0tTVU1fSU5WQUxJRCA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgdmFsaWRpdHkgb2YgdGhlIGNhcmRcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZXhwaXJhdGlvbihmb3JtR3JvdXA6IEZvcm1Hcm91cCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcbiAgICBjb25zdCBleHBpcmF0aW9uTW9udGg6IG51bWJlciA9IE51bWJlcihmb3JtR3JvdXAuZ2V0KCdleHBpcmF0aW9uTW9udGgnKS52YWx1ZSk7XG4gICAgY29uc3QgZXhwaXJhdGlvblllYXI6IG51bWJlciA9IE51bWJlcihmb3JtR3JvdXAuZ2V0KCdleHBpcmF0aW9uWWVhcicpLnZhbHVlKTtcbiAgICBjb25zdCBleHBpcmF0aW9uRGF0ZTogRGF0ZSA9IG5ldyBEYXRlKGV4cGlyYXRpb25ZZWFyLCBleHBpcmF0aW9uTW9udGggKyAxLCAwKTtcbiAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCkgPiBleHBpcmF0aW9uRGF0ZS5nZXRUaW1lKCkgPyBDYXJkVmFsaWRhdG9yLkNBUkRfRVhQSVJFRCA6IG51bGw7XG4gIH1cbn1cbiIsIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlXHJcbnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlXHJcbkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG5USElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXHJcbktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRURcclxuV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSxcclxuTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC5cclxuXHJcblNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xyXG5hbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gZnVuY3Rpb24oKSB7XHJcbiAgICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgICAgIGZvciAodmFyIHMsIGkgPSAxLCBuID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IG47IGkrKykge1xyXG4gICAgICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdDtcclxuICAgIH1cclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMClcclxuICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA6IGMgPiAzID8gZCh0YXJnZXQsIGtleSwgcikgOiBkKHRhcmdldCwga2V5KSkgfHwgcjtcclxuICAgIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQsIGtleSkgeyBkZWNvcmF0b3IodGFyZ2V0LCBrZXksIHBhcmFtSW5kZXgpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QubWV0YWRhdGEgPT09IFwiZnVuY3Rpb25cIikgcmV0dXJuIFJlZmxlY3QubWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xyXG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XHJcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxyXG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZShyZXN1bHQudmFsdWUpOyB9KS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XHJcbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XHJcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xyXG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcclxuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XHJcbiAgICAgICAgd2hpbGUgKF8pIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcclxuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBleHBvcnRzKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmICghZXhwb3J0cy5oYXNPd25Qcm9wZXJ0eShwKSkgZXhwb3J0c1twXSA9IG1