UNPKG

ng-shopping-cart

Version:

An Angular component library to create shopping carts

995 lines 51.6 kB
import { __extends, __spread } from 'tslib';
import { EventEmitter, Component, Input, Output, Inject, LOCALE_ID, ComponentFactoryResolver, Directive, NgModuleRef, ViewContainerRef, InjectionToken, Injectable, Pipe, NgModule } from '@angular/core';
import { CurrencyPipe, getLocaleCurrencyName, CommonModule } from '@angular/common';
import { HttpClient, HttpParams, HttpRequest, HttpClientModule } from '@angular/common/http';

function parseLocaleFormat(format) {
    if (!format) {
        throw new Error('Invalid format for currency. Expected a non empty string');
    }
    var res = { currencyCode: undefined, display: 'symbol', digitsInfo: undefined, locale: undefined };
    var props = ['currencyCode', 'display', 'digitsInfo', 'locale'];
    var parts = format.split(':');
    var partsLength = parts.length;
    if (partsLength > 4) {
        throw new Error("Invalid format for currency. Expected a value in the form " + props.join(':') + " and got " + format);
    }
    parts.forEach(function (p, idx) {
        var value = p;
        if (value === 'auto') {
            value = idx === 1 ? 'symbol' : undefined;
        }
        res[props[idx]] = value;
    });
    return res;
}
var CartService = /** @class */ (function () {
    function CartService() {
        this.localeFormat = parseLocaleFormat('auto');
        this.format = 'auto';
        this.onChange = new EventEmitter();
        this.onItemAdded = new EventEmitter();
        this.onItemRemoved = new EventEmitter();
        this.onItemsChanged = new EventEmitter();
        this.onTaxChange = new EventEmitter();
        this.onShippingChange = new EventEmitter();
    }
    CartService.prototype.getTax = function () {
        return this.cost() * (this.getTaxRate() / 100);
    };
    CartService.prototype.totalCost = function () {
        return this.cost() + this.getTax() + this.getShipping();
    };
    CartService.prototype.setLocaleFormat = function (format) {
        this.localeFormat = parseLocaleFormat(format);
        this.format = format;
        this.onChange.emit({ change: 'format', value: this.format });
    };
    CartService.prototype.getLocaleFormat = function (object) {
        if (object === void 0) { object = false; }
        return object ? this.localeFormat : this.format;
    };
    CartService.prototype.toObject = function () {
        return {
            taxRate: this.getTaxRate(),
            shipping: this.getShipping(),
            items: this.getItems()
        };
    };
    return CartService;
}());
var CartItem = /** @class */ (function () {
    function CartItem() {
    }
    CartItem.prototype.total = function () {
        return this.getPrice() * this.getQuantity();
    };
    return CartItem;
}());
var AddToCartComponent = /** @class */ (function () {
    function AddToCartComponent(cartService) {
        this.cartService = cartService;
        this._editorQuantity = 1;
        this.hasEditor = false;
        this.horizontalEditor = true;
        this.editorPrecedence = 'before';
        this.custom = false;
        this.buttonText = 'Add to cart';
        this.buttonClass = 'add-to-cart-button';
        this.type = 'button';
        this.position = 'left';
        this.dropdown = [
            { label: '1 item', value: 1 },
            { label: '2 items', value: 2 },
            { label: '5 items', value: 5 }
        ];
        this.change = new EventEmitter();
        this.added = new EventEmitter();
    }
    Object.defineProperty(AddToCartComponent.prototype, "editorQuantity", {
        get: function () {
            return this._editorQuantity;
        },
        set: function (value) {
            this._editorQuantity = value;
            this.change.emit(value);
        },
        enumerable: true,
        configurable: true
    });
    AddToCartComponent.prototype.ngOnInit = function () {
        this.computeClass();
    };
    AddToCartComponent.prototype.itemQuantity = function () {
        if (this.type === 'button') {
            if (this.quantity) {
                return this.quantity;
            }
            return this.item.getQuantity();
        }
        else {
            return this._editorQuantity;
        }
    };
    AddToCartComponent.prototype.ngOnChanges = function (changes) {
        if (changes['type']) {
            this.hasEditor = changes['type'].currentValue !== 'button';
            if (changes['type'].currentValue === 'dropdown' && this.dropdown.length) {
                var quantity_1 = this.itemQuantity();
                var match = this.dropdown.find(function (i) { return i.value === quantity_1; });
                if (!match) {
                    this._editorQuantity = this.dropdown[0].value;
                }
            }
        }
        if (changes['position']) {
            var pos = changes['position'].currentValue;
            this.horizontalEditor = pos === 'left' || pos === 'right';
            this.editorPrecedence = pos === 'left' || pos === 'top' ? 'before' : 'after';
        }
        this.computeClass();
    };
    AddToCartComponent.prototype.addToCart = function (evt) {
        evt.stopPropagation();
        if (this.item) {
            var quantity = this.itemQuantity();
            this.item.setQuantity(quantity);
            this.cartService.addItem(this.item);
            this.added.emit(this.item);
        }
    };
    AddToCartComponent.prototype.computeClass = function () {
        this.containerClass = [
            'add-to-cart-' + this.type,
            this.horizontalEditor ?
                'editor-position-horizontal' :
                'editor-position-vertical'
        ];
    };
    return AddToCartComponent;
}());
AddToCartComponent.decorators = [
    { type: Component, args: [{
                selector: 'add-to-cart',
                template: "<div class=\"add-to-cart\" [ngClass]=\"containerClass\">\n  <div class=\"add-to-cart-component\" [ngClass]=\"position\"\n       *ngIf=\"editorPrecedence === 'before' && hasEditor\">\n    <add-to-cart-editor [type]=\"type\" [dropdown]=\"dropdown\" [(value)]=\"editorQuantity\"></add-to-cart-editor>\n  </div>\n  <div class=\"cart-button-container\" (click)=\"addToCart($event)\">\n    <ng-container *ngIf=\"!custom\">\n      <button type=\"button\" [ngClass]=\"buttonClass\" [disabled]=\"!item\">\n        {{buttonText}}\n      </button>\n    </ng-container>\n    <ng-content *ngIf=\"custom\">\n    </ng-content>\n  </div>\n  <div class=\"add-to-cart-component\" [ngClass]=\"position\"\n       *ngIf=\"editorPrecedence === 'after' && hasEditor\">\n    <add-to-cart-editor [type]=\"type\" [dropdown]=\"dropdown\" [(value)]=\"editorQuantity\"></add-to-cart-editor>\n  </div>\n</div>\n",
            },] },
];
AddToCartComponent.ctorParameters = function () { return [
    { type: CartService, },
]; };
AddToCartComponent.propDecorators = {
    "custom": [{ type: Input },],
    "item": [{ type: Input },],
    "buttonText": [{ type: Input },],
    "buttonClass": [{ type: Input },],
    "type": [{ type: Input },],
    "position": [{ type: Input },],
    "dropdown": [{ type: Input },],
    "quantity": [{ type: Input },],
    "change": [{ type: Output },],
    "added": [{ type: Output },],
};
var CartCheckoutComponent = /** @class */ (function () {
    function CartCheckoutComponent(cartService, httpClient, locale) {
        this.cartService = cartService;
        this.httpClient = httpClient;
        this.locale = locale;
        this.empty = true;
        this.cost = 0;
        this.taxRate = 0;
        this.shipping = 0;
        this.currency = 'USD';
        this.paypalLocale = 'en';
        this.custom = false;
        this.buttonText = 'Checkout';
        this.buttonClass = 'cart-checkout-button';
        this.service = 'log';
        this.settings = null;
        this.checkout = new EventEmitter();
        this.error = new EventEmitter();
        this.getLocaleCurrencyName = getLocaleCurrencyName;
    }
    CartCheckoutComponent.prototype.ngOnInit = function () {
        var _this = this;
        this.updateCart(true);
        this._serviceSubscription = this.cartService
            .onChange
            .subscribe(function (evt) { return _this.updateCart(evt.change === 'format'); });
    };
    CartCheckoutComponent.prototype.updateCart = function (formatChange) {
        this.empty = this.cartService.isEmpty();
        this.cost = this.cartService.cost();
        this.taxRate = this.cartService.getTaxRate();
        this.shipping = this.cartService.getShipping();
        if (formatChange) {
            this.updateLocale();
        }
    };
    CartCheckoutComponent.prototype.updateLocale = function () {
        this.format = this.localeFormat ?
            parseLocaleFormat(this.localeFormat) : (this.cartService.getLocaleFormat(true));
        var loc = this.format.locale || this.locale;
        this.paypalLocale = loc.substring(0, 2);
        this.currency = this.format.currencyCode || this.getCurrency(loc);
    };
    CartCheckoutComponent.prototype.getCurrency = function (locale) {
        var currencyCode = this.getLocaleCurrencyName(locale);
        if (!currencyCode) {
            return 'USD';
        }
        if (currencyCode.length === 3) {
            return currencyCode;
        }
        var fmt = new CurrencyPipe(locale);
        var val = fmt.transform(0, undefined, 'code', '1.0-0', locale);
        var pre = val.startsWith('0');
        return val.substr(pre ? -3 : 0, 3);
    };
    CartCheckoutComponent.prototype.doCheckout = function () {
        var _this = this;
        var cart = this.cartService.toObject();
        switch (this.service) {
            case 'log':
                console.log(cart);
                this.checkout.emit(cart);
                break;
            case 'http':
                if (!this.settings) {
                    throw new Error('Missing settings configuration');
                }
                var verbs = ['POST', 'PUT', 'PATCH'];
                var _a = this.httpSettings, url = _a.url, _b = _a.method, method = _b === void 0 ? 'POST' : _b, options = _a.options, body = _a.body;
                var methodUpper = method.toUpperCase();
                if (verbs.indexOf(methodUpper) === -1) {
                    throw new Error("Invalid http verb found in method setting. Expected one of " + verbs.join(' ') + " and got " + method);
                }
                if (body) {
                    cart = typeof body === 'function' ? body(cart) : Object.assign({}, cart, body);
                }
                if (options && options.headers && options.headers.has('Content-Type')) {
                    var contentType = options.headers.get('Content-Type');
                    if (contentType.startsWith('application/x-www-form-urlencoded')) {
                        cart = new HttpParams({ fromObject: cart });
                    }
                }
                this.httpClient
                    .request(new HttpRequest(methodUpper, url, cart, options))
                    .toPromise()
                    .then(function (response) {
                    _this.checkout.emit(response);
                })
                    .catch(function (err) {
                    _this.error.emit(err);
                });
                break;
        }
    };
    CartCheckoutComponent.prototype.ngOnChanges = function (changes) {
        if (changes['settings'] && changes['settings'].currentValue) {
            var hasOwn = Object.prototype.hasOwnProperty;
            var value = changes['settings'].currentValue;
            if (hasOwn.call(value, 'business')) {
                this.paypalSettings = changes['settings'].currentValue;
            }
            if (hasOwn.call(value, 'url')) {
                this.httpSettings = changes['settings'].currentValue;
            }
        }
        if (changes['localeFormat']) {
            this.updateLocale();
        }
    };
    CartCheckoutComponent.prototype.ngOnDestroy = function () {
        this._serviceSubscription.unsubscribe();
    };
    return CartCheckoutComponent;
}());
CartCheckoutComponent.decorators = [
    { type: Component, args: [{
                selector: 'cart-checkout',
                template: "<ng-container *ngIf=\"service === 'log' || service === 'http'\">\n  <button [ngClass]=\"buttonClass\" [disabled]=\"empty\" *ngIf=\"!custom\" (click)=\"doCheckout()\">\n    {{buttonText}}\n  </button>\n  <span (click)=\"doCheckout()\" *ngIf=\"custom\">\n    <ng-content>\n    </ng-content>\n  </span>\n</ng-container>\n<ng-container *ngIf=\"service === 'paypal'\">\n  <form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\" target=\"_top\">\n    <input type=\"hidden\" name=\"cmd\" value=\"_xclick\"/>\n    <input type=\"hidden\" name=\"business\" value=\"{{paypalSettings.business}}\"/>\n    <input type=\"hidden\" name=\"lc\" value=\"{{paypalLocale}}\"/>\n    <input type=\"hidden\" name=\"item_name\" value=\"{{paypalSettings.itemName}}\" *ngIf=\"paypalSettings.itemName\"/>\n    <input type=\"hidden\" name=\"item_number\" value=\"{{paypalSettings.itemNumber}}\" *ngIf=\"paypalSettings.itemNumber\"/>\n    <input type=\"hidden\" name=\"amount\" value=\"{{cost}}\"/>\n    <input type=\"hidden\" name=\"currency_code\" value=\"{{currency}}\"/>\n    <input type=\"hidden\" name=\"tax_rate\" value=\"{{taxRate}}\"/>\n    <input type=\"hidden\" name=\"shipping\" value=\"{{shipping}}\"/>\n    <input type=\"hidden\" name=\"bn\" value=\"{{paypalSettings.serviceName + '_BuyNow_WPS_' + paypalSettings.country}}\"\n           *ngIf=\"paypalSettings.serviceName && paypalSettings.country\"/>\n    <input type=\"image\" src=\"https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif\" border=\"0\" name=\"submit\"\n           alt=\"PayPal - The safer, easier way to pay online!\"/>\n    <img alt=\"\" border=\"0\" src=\"https://www.paypalobjects.com/en_US/i/scr/pixel.gif\" width=\"1\" height=\"1\"/>\n  </form>\n</ng-container>\n",
            },] },
];
CartCheckoutComponent.ctorParameters = function () { return [
    { type: CartService, },
    { type: HttpClient, },
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
]; };
CartCheckoutComponent.propDecorators = {
    "custom": [{ type: Input },],
    "buttonText": [{ type: Input },],
    "buttonClass": [{ type: Input },],
    "service": [{ type: Input },],
    "settings": [{ type: Input },],
    "localeFormat": [{ type: Input },],
    "checkout": [{ type: Output },],
    "error": [{ type: Output },],
};
var CartSummaryComponent = /** @class */ (function () {
    function CartSummaryComponent(cartService) {
        this.cartService = cartService;
        this.noItemsText = 'No items';
        this.oneItemText = 'One item';
        this.manyItemsText = '# items';
        this.totalItems = 0;
        this.totalCost = 0;
    }
    CartSummaryComponent.prototype.updateItemsText = function () {
        var text = this.noItemsText;
        if (this.totalItems > 0) {
            text = this.totalItems === 1 ? this.oneItemText : this.manyItemsText;
        }
        this.itemsText = text.replace('#', this.totalItems.toString());
    };
    CartSummaryComponent.prototype.updateComponent = function () {
        this.totalItems = this.cartService.itemCount();
        this.totalCost = !this.cartService.isEmpty() ? this.cartService.totalCost() : 0;
        if (!this.localeFormat) {
            this.format = (this.cartService.getLocaleFormat(true));
        }
        this.updateItemsText();
    };
    CartSummaryComponent.prototype.ngOnInit = function () {
        var _this = this;
        this.updateComponent();
        this._serviceSubscription = this.cartService.onChange.subscribe(function () {
            _this.updateComponent();
        });
    };
    CartSummaryComponent.prototype.ngOnChanges = function (changes) {
        if (changes['localeFormat']) {
            this.format = this.localeFormat ?
                parseLocaleFormat(this.localeFormat) : (this.cartService.getLocaleFormat(true));
        }
        if (changes['noItemsText'] || changes['oneItemText'] || changes['manyItemsText']) {
            this.updateItemsText();
        }
    };
    CartSummaryComponent.prototype.ngOnDestroy = function () {
        this._serviceSubscription.unsubscribe();
    };
    return CartSummaryComponent;
}());
CartSummaryComponent.decorators = [
    { type: Component, args: [{
                selector: 'cart-summary',
                template: "<div class=\"cart-summary\">\n  <div class=\"cart-summary-icon\">\n    <svg *ngIf=\"!icon\" version=\"1.1\" class=\"summary-icon\" xmlns=\"http://www.w3.org/2000/svg\"\n         xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\">\n      <path stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" fill=\"none\" stroke-linejoin=\"round\"\n            d=\"M2,4 L6,4 L10,20 L21,20 L25,10 L8,10 M13,10 L13,20 M18,20 L18,10 M10,15 L23,15\"/>\n      <circle fill=\"currentColor\" cx=\"11\" cy=\"24\" r=\"2\"/>\n      <circle fill=\"currentColor\" cx=\"21\" cy=\"24\" r=\"2\"/>\n    </svg>\n    <img *ngIf=\"icon\" [src]=\"icon\" class=\"summary-icon\" alt=\"cart-summary-icon\">\n  </div>\n  <div class=\"cart-summary-contents\">\n    <div class=\"cart-summary-items\">\n      {{itemsText}}\n    </div>\n    <div class=\"cart-summary-cost\">\n      {{totalCost | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n    </div>\n  </div>\n</div>\n",
            },] },
];
CartSummaryComponent.ctorParameters = function () { return [
    { type: CartService, },
]; };
CartSummaryComponent.propDecorators = {
    "icon": [{ type: Input },],
    "noItemsText": [{ type: Input },],
    "oneItemText": [{ type: Input },],
    "manyItemsText": [{ type: Input },],
    "localeFormat": [{ type: Input },],
};
var AddToCartEditorComponent = /** @class */ (function () {
    function AddToCartEditorComponent() {
        this.type = 'text';
        this.value = 1;
        this.valueChange = new EventEmitter();
    }
    AddToCartEditorComponent.prototype.changeValue = function (value) {
        var val = parseFloat(value);
        this.valueChange.emit(Number.isNaN(val) ? 1 : val);
    };
    return AddToCartEditorComponent;
}());
AddToCartEditorComponent.decorators = [
    { type: Component, args: [{
                selector: 'add-to-cart-editor',
                template: "<ng-container *ngIf=\"type === 'dropdown'\">\n  <select class=\"add-to-cart-input\" #selectAmount (change)=\"changeValue(selectAmount.value)\">\n    <option [selected]=\"item.value === value\" *ngFor=\"let item of dropdown\" [value]=\"item.value\">{{item.label}}</option>\n  </select>\n</ng-container>\n<ng-container *ngIf=\"type === 'number' || type === 'text'\">\n  <input class=\"add-to-cart-input\" #inputAmount [type]=\"type\" (change)=\"changeValue(inputAmount.value)\" [value]=\"value\">\n</ng-container>\n",
            },] },
];
AddToCartEditorComponent.ctorParameters = function () { return []; };
AddToCartEditorComponent.propDecorators = {
    "type": [{ type: Input },],
    "dropdown": [{ type: Input },],
    "value": [{ type: Input },],
    "valueChange": [{ type: Output },],
};
var CartViewComponent = /** @class */ (function () {
    function CartViewComponent(cartService) {
        this.cartService = cartService;
        this.display = 'responsive-table';
        this.images = true;
        this.emptyText = 'Your cart is empty';
        this.customEmptyContent = false;
        this.nameHeaderText = 'Name';
        this.quantityHeaderText = 'Quantity';
        this.priceHeaderText = 'Price';
        this.totalHeaderText = 'Total';
        this.taxFooterText = 'Tax';
        this.shippingFooterText = 'Shipping';
        this.totalFooterText = 'Total';
        this.empty = true;
        this.taxRate = 0;
        this.tax = 0;
        this.shipping = 0;
        this.cost = 0;
    }
    CartViewComponent.prototype.update = function () {
        this.empty = this.cartService.isEmpty();
        this.items = this.cartService.getItems();
        this.taxRate = this.cartService.getTaxRate() / 100;
        this.tax = this.cartService.getTax();
        this.shipping = this.cartService.getShipping();
        this.cost = this.cartService.totalCost();
        if (!this.localeFormat) {
            this.format = (this.cartService.getLocaleFormat(true));
        }
    };
    CartViewComponent.prototype.increase = function (item) {
        item.setQuantity(item.getQuantity() + 1);
        this.cartService.addItem(item);
    };
    CartViewComponent.prototype.decrease = function (item) {
        if (item.getQuantity() > 1) {
            item.setQuantity(item.getQuantity() - 1);
            this.cartService.addItem(item);
        }
        else {
            this.cartService.removeItem(item.getId());
        }
    };
    CartViewComponent.prototype.ngOnInit = function () {
        var _this = this;
        this.update();
        this._serviceSubscription = this.cartService.onChange.subscribe(function () {
            _this.update();
        });
    };
    CartViewComponent.prototype.ngOnChanges = function (changes) {
        if (changes['localeFormat']) {
            this.format = this.localeFormat ?
                parseLocaleFormat(this.localeFormat) : (this.cartService.getLocaleFormat(true));
        }
    };
    CartViewComponent.prototype.ngOnDestroy = function () {
        this._serviceSubscription.unsubscribe();
    };
    return CartViewComponent;
}());
CartViewComponent.decorators = [
    { type: Component, args: [{
                selector: 'cart-view',
                template: "<ng-container *ngIf=\"empty\">\n  <div *ngIf=\"!customEmptyContent\" class=\"cart-view-empty\">\n    {{emptyText}}\n  </div>\n  <ng-content *ngIf=\"customEmptyContent\"></ng-content>\n</ng-container>\n<ng-container *ngIf=\"!empty\">\n  <ng-container *ngIf=\"display !== 'table'\">\n    <div *ngIf=\"!empty\" class=\"cart-view\" [ngClass]=\"display + '-display'\">\n      <div class=\"cart-list-view\" [ngClass]=\"{'no-images': !images}\">\n        <div class=\"cart-list-header\">\n          <div class=\"cart-list-header-value cart-list-image-header\">\n          </div>\n          <div class=\"cart-list-header-value cart-list-name-header\">\n            {{nameHeaderText}}\n          </div>\n          <div class=\"cart-list-header-value cart-list-quantity-header\">\n            {{quantityHeaderText}}\n          </div>\n          <div class=\"cart-list-header-value cart-list-price-header\">\n            {{priceHeaderText}}\n          </div>\n          <div class=\"cart-list-header-value cart-list-total-header\">\n            {{totalHeaderText}}\n          </div>\n        </div>\n        <div *ngFor=\"let cartItem of items\" class=\"cart-list-item\">\n          <div class=\"cart-list-value cart-list-image-value\"\n               [ngStyle]=\"{'background-image': 'url(' + cartItem.getImage() + ')'}\">\n          </div>\n          <div class=\"cart-list-value cart-list-name-value\">\n            {{cartItem.getName()}}\n          </div>\n          <div class=\"cart-list-value cart-list-quantity-value\">\n            <button type=\"button\" class=\"cart-increase-button\" (click)=\"increase(cartItem)\">\n              +\n            </button>\n            <span class=\"cart-list-quantity-content\">{{cartItem.getQuantity()}}</span>\n            <button type=\"button\" class=\"cart-decrease-button\" (click)=\"decrease(cartItem)\">\n              -\n            </button>\n          </div>\n          <div class=\"cart-list-value cart-list-price-value\">\n            {{cartItem.getPrice() | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n          </div>\n          <div class=\"cart-list-value cart-list-total-value\">\n            {{cartItem.total() | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n          </div>\n        </div>\n        <div class=\"cart-list-footer\">\n          <div class=\"cart-list-summary\">\n            <div class=\"cart-empty-summary\" *ngIf=\"images\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-tax-summary\">\n              {{taxFooterText}}: ({{taxRate | percent:format.digitsInfo:format.locale}})\n              {{tax | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n            </div>\n          </div>\n          <div class=\"cart-list-summary\">\n            <div class=\"cart-empty-summary\" *ngIf=\"images\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-shipping-summary\">\n              {{shippingFooterText}}:\n              {{shipping | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n            </div>\n          </div>\n          <div class=\"cart-list-summary\">\n            <div class=\"cart-empty-summary\" *ngIf=\"images\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-empty-summary\"></div>\n            <div class=\"cart-total-summary\">\n              {{totalFooterText}}:\n              {{cost | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </ng-container>\n  <ng-container *ngIf=\"display === 'table'\">\n    <table class=\"cart-view table-display\">\n      <thead class=\"cart-list-header\">\n      <tr>\n        <th class=\"cart-list-header-value cart-list-image-header\" *ngIf=\"images\"></th>\n        <th class=\"cart-list-header-value cart-list-name-header\">{{nameHeaderText}}</th>\n        <th class=\"cart-list-header-value cart-list-quantity-header\">{{quantityHeaderText}}</th>\n        <th class=\"cart-list-header-value cart-list-price-header\">{{priceHeaderText}}</th>\n        <th class=\"cart-list-header-value cart-list-total-header\">{{totalHeaderText}}</th>\n      </tr>\n      </thead>\n      <tbody>\n      <tr *ngFor=\"let cartItem of items\">\n        <td class=\"cart-list-value cart-list-image-value\" *ngIf=\"images\"\n            [ngStyle]=\"{'background-image': 'url(' + cartItem.getImage() + ')'}\">\n        </td>\n        <td class=\"cart-list-value cart-list-name-value\">{{cartItem.getName()}}</td>\n        <td class=\"cart-list-value cart-list-quantity-value\">\n          <button type=\"button\" class=\"cart-increase-button\" (click)=\"increase(cartItem)\">\n            +\n          </button>\n          <span class=\"cart-list-quantity-content\">{{cartItem.getQuantity()}}</span>\n          <button type=\"button\" class=\"cart-decrease-button\" (click)=\"decrease(cartItem)\">\n            -\n          </button>\n        </td>\n        <td class=\"cart-list-value cart-list-price-value\">\n          {{cartItem.getPrice() | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n        </td>\n        <td class=\"cart-list-value cart-list-total-value\">\n          {{cartItem.total() | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n        </td>\n      </tr>\n      </tbody>\n      <tfoot class=\"cart-list-footer\">\n      <tr class=\"cart-list-summary\">\n        <td [attr.colspan]=\"images ? 4 : 3\" class=\"cart-empty-summary\"></td>\n        <td class=\"cart-tax-summary\">\n          {{taxFooterText}}: ({{taxRate | percent:format.digitsInfo:format.locale}})\n          {{tax | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n        </td>\n      </tr>\n      <tr class=\"cart-list-summary\">\n        <td [attr.colspan]=\"images ? 4 : 3\" class=\"cart-empty-summary\"></td>\n        <td class=\"cart-shipping-summary\">\n          {{shippingFooterText}}:\n          {{shipping | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n        </td>\n      </tr>\n      <tr class=\"cart-list-summary\">\n        <td [attr.colspan]=\"images ? 4 : 3\" class=\"cart-empty-summary\"></td>\n        <td class=\"cart-total-summary\">\n          {{totalFooterText}}:\n          {{cost | currency:format.currencyCode:format.display:format.digitsInfo:format.locale}}\n        </td>\n      </tr>\n      </tfoot>\n    </table>\n  </ng-container>\n</ng-container>\n",
            },] },
];
CartViewComponent.ctorParameters = function () { return [
    { type: CartService, },
]; };
CartViewComponent.propDecorators = {
    "display": [{ type: Input },],
    "images": [{ type: Input },],
    "emptyText": [{ type: Input },],
    "customEmptyContent": [{ type: Input },],
    "nameHeaderText": [{ type: Input },],
    "quantityHeaderText": [{ type: Input },],
    "priceHeaderText": [{ type: Input },],
    "totalHeaderText": [{ type: Input },],
    "taxFooterText": [{ type: Input },],
    "shippingFooterText": [{ type: Input },],
    "totalFooterText": [{ type: Input },],
    "localeFormat": [{ type: Input },],
};
var CartShowcaseItemComponent = /** @class */ (function () {
    function CartShowcaseItemComponent() {
    }
    return CartShowcaseItemComponent;
}());
CartShowcaseItemComponent.decorators = [
    { type: Component, args: [{
                selector: 'cart-showcase-item',
                template: "<div class=\"showcase-item default-sc-item\" [ngStyle]=\"{'background-image': 'url(' + item.getImage() + ')'}\">\n  <div class=\"default-sc-description\">\n    <div class=\"default-sc-name\">\n      {{item.getName()}}\n    </div>\n    <div class=\"default-sc-price\">\n      {{item.getPrice() | cartCurrency:format}}\n    </div>\n  </div>\n</div>\n",
            },] },
];
CartShowcaseItemComponent.ctorParameters = function () { return []; };
var CartShowcaseComponent = /** @class */ (function () {
    function CartShowcaseComponent(cartService) {
        this.cartService = cartService;
        this.xsClass = 'sc-container-xs-12';
        this.sClass = 'sc-container-s-6';
        this.mClass = 'sc-container-m-4';
        this.lClass = 'sc-container-l-4';
        this.xlClass = 'sc-container-xl-3';
        this.ratioClass = 'sc-ratio-1-1';
        this.xsCols = 1;
        this.sCols = 2;
        this.mCols = 3;
        this.lCols = 3;
        this.xlCols = 4;
        this.columns = 12;
        this.itemComponent = CartShowcaseItemComponent;
        this.aspectRatio = '1:1';
    }
    CartShowcaseComponent.prototype.getColumnSize = function (value) {
        return Math.floor(this.columns / value);
    };
    CartShowcaseComponent.prototype.ngOnChanges = function (changes) {
        var columnProps = ['xsCols', 'sCols', 'mCols', 'lCols', 'xlCols'];
        var classPrefix = ['xs', 's', 'm', 'l', 'xl'];
        for (var i = 0; i < columnProps.length; i++) {
            var prop = columnProps[i];
            var colChanges = changes[prop];
            if (changes['columns'] || colChanges) {
                var prefix = classPrefix[i];
                var size = this.getColumnSize(this[prop]);
                this[prefix + "Class"] = "sc-container-" + prefix + "-" + size;
            }
        }
        if (changes['aspectRatio']) {
            var newRatio = changes['aspectRatio'].currentValue;
            var values = newRatio.split(':');
            if (values.length === 2) {
                this.ratioClass = "sc-ratio-" + values[0] + "-" + values[1];
            }
        }
        if (changes['localeFormat']) {
            this.format = this.localeFormat || (this.cartService.getLocaleFormat());
        }
    };
    CartShowcaseComponent.prototype.ngOnInit = function () {
        var _this = this;
        this.format = this.localeFormat || (this.cartService.getLocaleFormat());
        this._serviceSubscription = this.cartService.onChange.subscribe(function (evt) {
            if (evt.change === 'format' && !_this.localeFormat) {
                _this.format = (_this.cartService.getLocaleFormat());
            }
        });
    };
    CartShowcaseComponent.prototype.ngOnDestroy = function () {
        this._serviceSubscription.unsubscribe();
    };
    return CartShowcaseComponent;
}());
CartShowcaseComponent.decorators = [
    { type: Component, args: [{
                selector: 'cart-showcase',
                template: "<div class=\"cart-showcase\">\n  <div class=\"sc-item-container\" *ngFor=\"let carItem of items\"\n       [ngClass]=\"[xsClass, sClass, mClass, lClass, xlClass, ratioClass]\">\n    <div class=\"sc-item-wrapper\">\n      <ng-container\n        *cartShowcaseOutlet=\"itemComponent;item:carItem;format:format;injector:injector;ngModuleFactory:moduleFactory\">\n      </ng-container>\n    </div>\n  </div>\n</div>\n",
            },] },
];
CartShowcaseComponent.ctorParameters = function () { return [
    { type: CartService, },
]; };
CartShowcaseComponent.propDecorators = {
    "xsCols": [{ type: Input },],
    "sCols": [{ type: Input },],
    "mCols": [{ type: Input },],
    "lCols": [{ type: Input },],
    "xlCols": [{ type: Input },],
    "columns": [{ type: Input },],
    "items": [{ type: Input },],
    "itemComponent": [{ type: Input },],
    "injector": [{ type: Input },],
    "moduleFactory": [{ type: Input },],
    "aspectRatio": [{ type: Input },],
    "localeFormat": [{ type: Input },],
};
var ShowcaseOutletDirective = /** @class */ (function () {
    function ShowcaseOutletDirective(viewContainerRef) {
        this.viewContainerRef = viewContainerRef;
        this._componentRef = null;
        this._moduleRef = null;
    }
    ShowcaseOutletDirective.prototype.cleanModule = function () {
        if (this._moduleRef) {
            this._moduleRef.destroy();
        }
    };
    ShowcaseOutletDirective.prototype.ngOnChanges = function (changes) {
        var templateChange = Object.keys(changes).length !== 1 || !changes['cartShowcaseOutletFormat'];
        if (templateChange) {
            this.viewContainerRef.clear();
            this._componentRef = null;
            if (this.cartShowcaseOutlet) {
                var elInjector = this.cartShowcaseOutletInjector || this.viewContainerRef.parentInjector;
                if (changes['cartShowcaseOutletNgModuleFactory']) {
                    this.cleanModule();
                    if (this.cartShowcaseOutletNgModuleFactory) {
                        var parentModule = elInjector.get(NgModuleRef);
                        this._moduleRef = this.cartShowcaseOutletNgModuleFactory.create(parentModule.injector);
                    }
                    else {
                        this._moduleRef = null;
                    }
                }
                var componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver :
                    elInjector.get(ComponentFactoryResolver);
                var componentFactory = componentFactoryResolver.resolveComponentFactory(this.cartShowcaseOutlet);
                this._componentRef = this.viewContainerRef.createComponent(componentFactory, this.viewContainerRef.length, elInjector);
                var instance = this._componentRef.instance;
                instance.item = this.cartShowcaseOutletItem;
                instance.format = this.cartShowcaseOutletFormat;
            }
        }
        else {
            if (this._componentRef) {
                this._componentRef.instance.format = this.cartShowcaseOutletFormat;
            }
        }
    };
    ShowcaseOutletDirective.prototype.ngOnDestroy = function () {
        this.cleanModule();
    };
    return ShowcaseOutletDirective;
}());
ShowcaseOutletDirective.decorators = [
    { type: Directive, args: [{
                selector: '[cartShowcaseOutlet]',
            },] },
];
ShowcaseOutletDirective.ctorParameters = function () { return [
    { type: ViewContainerRef, },
]; };
ShowcaseOutletDirective.propDecorators = {
    "cartShowcaseOutlet": [{ type: Input },],
    "cartShowcaseOutletInjector": [{ type: Input },],
    "cartShowcaseOutletNgModuleFactory": [{ type: Input },],
    "cartShowcaseOutletItem": [{ type: Input },],
    "cartShowcaseOutletFormat": [{ type: Input },],
};
var CART_ITEM_CLASS = new InjectionToken('CartItemClass');
var CART_SERVICE_CONFIGURATION = new InjectionToken('CartServiceConfiguration');
var CART_SERVICE_TYPE = new InjectionToken('CartServiceType');
var MemoryCartService = /** @class */ (function (_super) {
    __extends(MemoryCartService, _super);
    function MemoryCartService() {
        var _this = _super.apply(this, __spread(arguments)) || this;
        _this._items = [];
        _this._taxRate = 0;
        _this._shipping = 0;
        return _this;
    }
    MemoryCartService.prototype._addItem = function (item) {
        var foundIdx = this._items.findIndex(function (i) { return i.getId() === item.getId(); });
        if (foundIdx === -1) {
            this._items.push(item);
        }
        else {
            this._items[foundIdx] = item;
        }
        this.onItemAdded.emit(item);
        this.onItemsChanged.emit(this._items.length);
        this.onChange.emit({ change: 'items', value: this.getItems() });
    };
    MemoryCartService.prototype._removeItem = function (id) {
        var idx = this._items.findIndex(function (i) { return i.getId() === id; });
        if (idx !== -1) {
            var removed = this._items.splice(idx, 1);
            this.onItemRemoved.emit(removed[0]);
            this.onItemsChanged.emit(this._items.length);
            this.onChange.emit({ change: 'items', value: this.getItems() });
        }
    };
    MemoryCartService.prototype.getItem = function (id) {
        return this._items.find(function (i) { return i.getId() === id; });
    };
    MemoryCartService.prototype.getItems = function () {
        return this._items.slice();
    };
    MemoryCartService.prototype.itemCount = function () {
        return this._items.length;
    };
    MemoryCartService.prototype.entries = function () {
        return this._items.reduce(function (curr, i) { return (curr + i.getQuantity()); }, 0);
    };
    MemoryCartService.prototype.addItem = function (item) {
        this._addItem(item);
    };
    MemoryCartService.prototype.removeItem = function (id) {
        this._removeItem(id);
    };
    MemoryCartService.prototype.cost = function () {
        return this._items.reduce(function (curr, i) { return (curr + i.getPrice() * i.getQuantity()); }, 0);
    };
    MemoryCartService.prototype.clear = function () {
        this._items = [];
        this.onItemsChanged.emit(this._items.length);
        this.onChange.emit({ change: 'items', value: this.getItems() });
    };
    MemoryCartService.prototype.getShipping = function () {
        return this._shipping;
    };
    MemoryCartService.prototype.setShipping = function (shipping) {
        this._shipping = shipping;
        this.onShippingChange.emit(this._shipping);
        this.onChange.emit({ change: 'shipping', value: this._shipping });
    };
    MemoryCartService.prototype.getTaxRate = function () {
        return this._taxRate;
    };
    MemoryCartService.prototype.setTaxRate = function (taxRate) {
        this._taxRate = taxRate;
        this.onTaxChange.emit(this._taxRate);
        this.onChange.emit({ change: 'taxRate', value: this._taxRate });
    };
    MemoryCartService.prototype.isEmpty = function () {
        return this._items.length === 0;
    };
    return MemoryCartService;
}(CartService));
MemoryCartService.decorators = [
    { type: Injectable },
];
MemoryCartService.ctorParameters = function () { return []; };
var BrowserStorageCartService = /** @class */ (function (_super) {
    __extends(BrowserStorageCartService, _super);
    function BrowserStorageCartService(itemClass, configuration) {
        var _this = _super.call(this) || this;
        _this.storageKey = configuration && configuration.storageKey ? configuration.storageKey : 'NgShoppingCart';
        _this.clearOnError = configuration && configuration.clearOnError !== undefined ? configuration.clearOnError : true;
        _this.itemClass = itemClass;
        return _this;
    }
    BrowserStorageCartService.prototype.resetStorage = function (error) {
        if (this.clearOnError || !error) {
            this.setTaxRate(0);
            this.setShipping(0);
            this.clear();
            this.save();
        }
        else {
            if (typeof error === 'string') {
                throw new Error(error);
            }
            throw error;
        }
    };
    BrowserStorageCartService.prototype.save = function () {
        this.storage.setItem(this.storageKey, JSON.stringify(this.toObject()));
    };
    BrowserStorageCartService.prototype.restore = function () {
        var _this = this;
        if (!this.storage.getItem(this.storageKey)) {
            this.resetStorage(false);
            return;
        }
        try {
            var sc = JSON.parse(this.storage.getItem(this.storageKey));
            if (!(sc.hasOwnProperty('items') && Array.isArray(sc.items) && sc.hasOwnProperty('taxRate') && sc.hasOwnProperty('shipping'))) {
                this.resetStorage('The object found under the key ' + this.storageKey + ' is not a valid cart object');
                return;
            }
            this._items = sc.items.map(function (i) {
                if (_this.itemClass.fromJSON) {
                    return _this.itemClass.fromJSON(i);
                }
                return new _this.itemClass(i);
            });
            this.setTaxRate(parseFloat(sc.taxRate));
            this.setShipping(parseFloat(sc.shipping));
        }
        catch (e) {
            this.resetStorage(e);
        }
    };
    BrowserStorageCartService.prototype.addItem = function (item) {
        _super.prototype.addItem.call(this, item);
        this.save();
    };
    BrowserStorageCartService.prototype.removeItem = function (id) {
        _super.prototype.removeItem.call(this, id);
        this.save();
    };
    BrowserStorageCartService.prototype.clear = function () {
        _super.prototype.clear.call(this);
        this.save();
    };
    BrowserStorageCartService.prototype.setShipping = function (shipping) {
        _super.prototype.setShipping.call(this, shipping);
        this.save();
    };
    BrowserStorageCartService.prototype.setTaxRate = function (tax) {
        _super.prototype.setTaxRate.call(this, tax);
        this.save();
    };
    return BrowserStorageCartService;
}(MemoryCartService));
BrowserStorageCartService.ctorParameters = function () { return [
    { type: CartItem, decorators: [{ type: Inject, args: [CART_ITEM_CLASS,] },] },
    { type: undefined, decorators: [{ type: Inject, args: [CART_SERVICE_CONFIGURATION,] },] },
]; };
var LocalStorageCartService = /** @class */ (function (_super) {
    __extends(LocalStorageCartService, _super);
    function LocalStorageCartService(itemClass, configuration) {
        var _this = _super.call(this, itemClass, configuration) || this;
        _this.storage = window.localStorage;
        _this.restore();
        return _this;
    }
    return LocalStorageCartService;
}(BrowserStorageCartService));
LocalStorageCartService.decorators = [
    { type: Injectable },
];
LocalStorageCartService.ctorParameters = function () { return [
    { type: undefined, decorators: [{ type: Inject, args: [CART_ITEM_CLASS,] },] },
    { type: undefined, decorators: [{ type: Inject, args: [CART_SERVICE_CONFIGURATION,] },] },
]; };
var SessionStorageCartService = /** @class */ (function (_super) {
    __extends(SessionStorageCartService, _super);
    function SessionStorageCartService(itemClass, configuration) {
        var _this = _super.call(this, itemClass, configuration) || this;
        _this.storage = window.sessionStorage;
        _this.restore();
        return _this;
    }
    return SessionStorageCartService;
}(BrowserStorageCartService));
SessionStorageCartService.decorators = [
    { type: Injectable },
];
SessionStorageCartService.ctorParameters = function () { return [
    { type: undefined, decorators: [{ type: Inject, args: [CART_ITEM_CLASS,] },] },
    { type: undefined, decorators: [{ type: Inject, args: [CART_SERVICE_CONFIGURATION,] },] },
]; };
var BaseCartItem = /** @class */ (function (_super) {
    __extends(BaseCartItem, _super);
    function BaseCartItem(itemData) {
        if (itemData === void 0) { itemData = {}; }
        var _this = _super.call(this) || this;
        _this.id = itemData.id || 0;
        _this.name = itemData.name || '';
        _this.price = itemData.price || 0;
        _this.image = itemData.image || '';
        _this.quantity = itemData.quantity || 1;
        _this.data = itemData.data || {};
        return _this;
    }
    BaseCartItem.prototype.getId = function () {
        return this.id;
    };
    BaseCartItem.prototype.setId = function (id) {
        this.id = id;
    };
    BaseCartItem.prototype.getName = function () {
        return this.name;
    };
    BaseCartItem.prototype.setName = function (name) {
        this.name = name;
    };
    BaseCartItem.prototype.getPrice = function () {
        return this.price;
    };
    BaseCartItem.prototype.setPrice = function (price) {
        this.price = price;
    };
    BaseCartItem.prototype.getQuantity = function () {
        return this.quantity;
    };
    BaseCartItem.prototype.setQuantity = function (quantity) {
        this.quantity = quantity;
    };
    BaseCartItem.prototype.getImage = function () {
        return this.image;
    };
    BaseCartItem.prototype.setImage = function (image) {
        this.image = image;
    };
    BaseCartItem.prototype.getData = function () {
        return this.data;
    };
    BaseCartItem.prototype.setData = function (data) {
        this.data = data;
    };
    return BaseCartItem;
}(CartItem));
function serviceFactory(serviceType, itemClass, configuration) {
    switch (serviceType) {
        case 'localStorage':
            return new LocalStorageCartService(itemClass, configuration);
        case 'sessionStorage':
            return new SessionStorageCartService(itemClass, configuration);
        default:
            return new MemoryCartService();
    }
}
function setupService(serviceType) {
    return {
        provide: CART_SERVICE_TYPE,
        useValue: serviceType || 'localStorage'
    };
}
function setItemClass(itemClass) {
    return {
        provide: CART_ITEM_CLASS,
        useValue: itemClass || BaseCartItem
    };
}
function setServiceConfiguration(serviceType, serviceOptions) {
    return {
        provide: CART_SERVICE_CONFIGURATION,
        useValue: serviceType !== 'memory' ? (!serviceOptions ? {
            storageKey: 'NgShoppingCart',
            clearOnError: true
        } : serviceOptions) : null
    };
}
var CartCurrencyPipe = /** @class */ (function () {
    function CartCurrencyPipe(_locale) {
        this._locale = _locale;
        this.currencyFormatter = new CurrencyPipe(this._locale);
    }
    CartCurrencyPipe.prototype.transform = function (value, format) {
        if (format === void 0) { format = 'auto'; }
        if (!value && value !== 0) {
            return null;
        }
        var _a = parseLocaleFormat(format), currencyCode = _a.currencyCode, display = _a.display, digitsInfo = _a.digitsInfo, locale = _a.locale;
        return this.currencyFormatter.transform(value, currencyCode, display, digitsInfo, locale);
    };
    return CartCurrencyPipe;
}());
CartCurrencyPipe.decorators = [
    { type: Pipe, args: [{ name: 'cartCurrency' },] },
];
CartCurrencyPipe.ctorParameters = function () { return [
    { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID,] },] },
]; };
var ShoppingCartModule = /** @class */ (function () {
    function ShoppingCartModule() {
    }
    ShoppingCartModule.forRoot = function (options) {
        if (options === void 0) { options = {}; }
        return {
            ngModule: ShoppingCartModule,
            providers: [
                setItemClass(options.itemType),
                setupService(options.serviceType),
                setServiceConfiguration(options.serviceType, options.serviceOptions),
                {
                    provide: CartService,
                    useFactory: serviceFactory,
                    deps: [CART_SERVICE_TYPE, CART_ITEM_CLASS, CART_SERVICE_CONFIGURATION]
                }
            ],
        };
    };
    ShoppingCartModule.forChild = function () {
        return {
            ngModule: ShoppingCartModule
        };
    };
    return ShoppingCartModule;
}());
ShoppingCartModule.decorators = [
    { type: NgModule, args: [{
                declarations: [
                    AddToCartEditorComponent,
                    AddToCartComponent,
                    CartCheckoutComponent,
                    CartSummaryComponent,
                    CartShowcaseComponent,
                    CartViewComponent,
                    ShowcaseOutletDirective,
                    CartShowcaseItemComponent,
                    CartCurrencyPipe,
                ],
                imports: [
                    CommonModule,
                    HttpClientModule,
                ],
                exports: [
                    AddToCartEditorComponent,
                    AddToCartComponent,
                    CartCheckoutComponent,
                    CartSummaryComponent,
                    CartShowcaseComponent,
                    CartViewComponent,
                    CartShowcaseItemComponent,
                    CartCurrencyPipe,
                    CommonModule,
                    HttpClientModule
                ],
                entryComponents: [CartShowcaseItemComponent],
            },] },
];
ShoppingCartModule.ctorParameters = function () { return []; };

export { AddToCartComponent, CartCheckoutComponent, CartSummaryComponent, CartShowcaseComponent, CartShowcaseItemComponent, CartViewComponent, CartCurrencyPipe, ShoppingCartModule, CART_ITEM_CLASS, CART_SERVICE_CONFIGURATION, CART_SERVICE_TYPE, CartService, MemoryCartService, LocalStorageCartService, SessionStorageCartService, CartItem, BaseCartItem, parseLocaleFormat, AddToCartEditorComponent as ɵa, ShowcaseOutletDirective as ɵb, serviceFactory as ɵc, setItemClass as ɵe, setServiceConfiguration as ɵf, setupService as ɵd, BrowserStorageCartService as ɵg };
//# sourceMappingURL=ng-shopping-cart.js.map