ng-payment-card
Version:
Customizable component with zero external dependencies.
688 lines (670 loc) • 80.5 kB
JavaScript
(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\"> </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