UNPKG

ngx-smart-popover

Version:

Simple popover control for your angular (v4+) applications using bootstrap4 with smart reflection logic when overflowing the viewport. This is a continuation of ngx-popover (https://github.com/pleerock/ngx-popover). If you want to use it without bootstrap

1,260 lines 53.4 kB
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common')) :
    typeof define === 'function' && define.amd ? define('ngx-smart-popover', ['exports', '@angular/core', '@angular/common'], factory) :
    (global = global || self, factory(global['ngx-smart-popover'] = {}, global.ng.core, global.ng.common));
}(this, function (exports, core, common) { 'use strict';

    /**
     * @fileoverview added by tsickle
     * Generated from: lib/popover.placement.ts
     * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
     */
    var PopoverPlacement = /** @class */ (function () {
        function PopoverPlacement() {
        }
        PopoverPlacement.Bottom = 'bottom';
        PopoverPlacement.BottomLeft = 'bottom-left';
        PopoverPlacement.BottomRight = 'bottom-right';
        PopoverPlacement.Left = 'left';
        PopoverPlacement.Right = 'right';
        PopoverPlacement.Top = 'top';
        PopoverPlacement.TopLeft = 'top-left';
        PopoverPlacement.TopRight = 'top-right';
        return PopoverPlacement;
    }());

    /**
     * @fileoverview added by tsickle
     * Generated from: lib/popover-content.component.ts
     * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
     */
    var PopoverContentComponent = /** @class */ (function () {
        // -------------------------------------------------------------------------
        // Constructor
        // -------------------------------------------------------------------------
        function PopoverContentComponent(element, cdr, renderer) {
            var _this = this;
            this.element = element;
            this.cdr = cdr;
            this.renderer = renderer;
            this.placement = PopoverPlacement.Top;
            this.animation = true;
            this.closeOnClickOutside = false;
            this.closeOnMouseOutside = false;
            this.appendToBody = false;
            this.size = 'small';
            this.onCloseFromOutside = new core.EventEmitter();
            this.top = -10000;
            this.left = -10000;
            this.isIn = false;
            this.opacity = 0;
            this.transitionEnabled = false;
            this.windowWidth = window.innerWidth;
            this.windowHeight = window.innerHeight;
            // -------------------------------------------------------------------------
            // Anonymous
            // -------------------------------------------------------------------------
            /**
             * Closes dropdown if user clicks outside of this directive.
             */
            this.onDocumentMouseDown = (/**
             * @param {?} event
             * @return {?}
             */
            function (event) {
                /** @type {?} */
                var element = _this.element.nativeElement;
                if (!element || !_this.popover) {
                    return;
                }
                if (element.contains(event.target) || _this.popover.getElement().contains(event.target)) {
                    return;
                }
                _this.onCloseFromOutside.emit(undefined);
            });
        }
        // -------------------------------------------------------------------------
        // Lifecycle callbacks
        // -------------------------------------------------------------------------
        // -------------------------------------------------------------------------
        // Lifecycle callbacks
        // -------------------------------------------------------------------------
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.ngAfterViewInit = 
        // -------------------------------------------------------------------------
        // Lifecycle callbacks
        // -------------------------------------------------------------------------
        /**
         * @return {?}
         */
        function () {
            var _this = this;
            if (this.closeOnClickOutside) {
                this.listenClickFunc = this.renderer.listen('document', 'mousedown', (/**
                 * @param {?} event
                 * @return {?}
                 */
                function (event) { return _this.onDocumentMouseDown(event); }));
            }
            if (this.closeOnMouseOutside) {
                this.listenMouseFunc = this.renderer.listen('document', 'mouseover', (/**
                 * @param {?} event
                 * @return {?}
                 */
                function (event) { return _this.onDocumentMouseDown(event); }));
            }
            // Always close on mobile touch event outside.
            this.listenTouchFunc = this.renderer.listen('document', 'touchstart', (/**
             * @param {?} event
             * @return {?}
             */
            function (event) { return _this.onDocumentMouseDown(event); }));
            this.show();
            this.cdr.detectChanges();
        };
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
        function () {
            if (this.closeOnClickOutside && this.listenClickFunc) {
                this.listenClickFunc();
            }
            if (this.closeOnMouseOutside && this.listenMouseFunc) {
                this.listenMouseFunc();
            }
            if (!!this.listenTouchFunc) {
                this.listenTouchFunc();
            }
        };
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        /**
         * @param {?} event
         * @return {?}
         */
        PopoverContentComponent.prototype.onResize = 
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        /**
         * @param {?} event
         * @return {?}
         */
        function (event) {
            this.windowWidth = window.innerWidth;
            this.windowHeight = window.innerHeight;
        };
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.updatePosition = /**
         * @return {?}
         */
        function () {
            // if visible, reposition
            if (this.opacity) {
                /** @type {?} */
                var p = this.positionElements(this.popover.getElement(), this.popoverDiv.nativeElement, this.placement);
                this.top = p.top;
                this.left = p.left;
            }
        };
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.show = /**
         * @return {?}
         */
        function () {
            if (!this.popover || !this.popover.getElement()) {
                return;
            }
            /** @type {?} */
            var p = this.positionElements(this.popover.getElement(), this.popoverDiv.nativeElement, this.placement);
            this.top = p.top;
            this.left = p.left;
            this.isIn = true;
            this.transitionEnabled = true;
            this.opacity = 1;
        };
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.hide = /**
         * @return {?}
         */
        function () {
            this.top = -10000;
            this.left = -10000;
            this.isIn = true;
            this.popover.hide();
        };
        /**
         * @return {?}
         */
        PopoverContentComponent.prototype.hideFromPopover = /**
         * @return {?}
         */
        function () {
            this.top = -10000;
            this.left = -10000;
            this.isIn = true;
            this.transitionEnabled = false;
            this.opacity = 0;
        };
        // -------------------------------------------------------------------------
        // Protected Methods
        // -------------------------------------------------------------------------
        // -------------------------------------------------------------------------
        // Protected Methods
        // -------------------------------------------------------------------------
        /**
         * @protected
         * @param {?} hostEl
         * @param {?} targetEl
         * @param {?} positionStr
         * @param {?=} appendToBody
         * @return {?}
         */
        PopoverContentComponent.prototype.positionElements = 
        // -------------------------------------------------------------------------
        // Protected Methods
        // -------------------------------------------------------------------------
        /**
         * @protected
         * @param {?} hostEl
         * @param {?} targetEl
         * @param {?} positionStr
         * @param {?=} appendToBody
         * @return {?}
         */
        function (hostEl, targetEl, positionStr, appendToBody) {
            if (appendToBody === void 0) { appendToBody = false; }
            /** @type {?} */
            var positionStrParts = ((/** @type {?} */ (positionStr))).split(' ');
            /** @type {?} */
            var pos0 = positionStrParts[0];
            /** @type {?} */
            var pos1 = positionStrParts[1] || 'center';
            /** @type {?} */
            var hostElPos = this.appendToBody || appendToBody ? this.offset(hostEl) : this.position(hostEl);
            /** @type {?} */
            var targetElWidth = targetEl.offsetWidth;
            /** @type {?} */
            var targetElHeight = targetEl.offsetHeight;
            this.effectivePlacement = pos0 = this.getEffectivePlacement(pos0, hostEl, targetEl);
            /** @type {?} */
            var shiftWidth = {
                center: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
                }),
                left: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.left;
                }),
                right: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.left + hostElPos.width;
                }),
                topOrBottomRight: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.left + hostElPos.width / 2;
                }),
                topOrBottomLeft: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.left - targetElWidth + hostElPos.width / 2;
                })
            };
            /** @type {?} */
            var shiftHeight = {
                center: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
                }),
                top: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.top;
                }),
                bottom: (/**
                 * @return {?}
                 */
                function () {
                    return hostElPos.top + hostElPos.height;
                })
            };
            /** @type {?} */
            var targetElPos;
            switch (pos0) {
                case PopoverPlacement.Right:
                    targetElPos = {
                        top: shiftHeight[pos1](),
                        left: shiftWidth[pos0]()
                    };
                    break;
                case PopoverPlacement.Left:
                    targetElPos = {
                        top: shiftHeight[pos1](),
                        left: hostElPos.left - targetElWidth
                    };
                    break;
                case PopoverPlacement.Bottom:
                    targetElPos = {
                        top: shiftHeight[pos0](),
                        left: shiftWidth[pos1]()
                    };
                    break;
                case PopoverPlacement.TopLeft:
                    targetElPos = {
                        top: hostElPos.top - targetElHeight,
                        left: shiftWidth['topOrBottomLeft']()
                    };
                    break;
                case PopoverPlacement.TopRight:
                    targetElPos = {
                        top: hostElPos.top - targetElHeight,
                        left: shiftWidth['topOrBottomRight']()
                    };
                    break;
                case PopoverPlacement.BottomLeft:
                    targetElPos = {
                        top: shiftHeight[PopoverPlacement.Bottom](),
                        left: shiftWidth['topOrBottomLeft']()
                    };
                    break;
                case PopoverPlacement.BottomRight:
                    targetElPos = {
                        top: shiftHeight[PopoverPlacement.Bottom](),
                        left: shiftWidth['topOrBottomRight']()
                    };
                    break;
                default:
                    targetElPos = {
                        top: hostElPos.top - targetElHeight,
                        left: shiftWidth[pos1]()
                    };
                    break;
            }
            return targetElPos;
        };
        /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        PopoverContentComponent.prototype.position = /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        function (nativeEl) {
            /** @type {?} */
            var offsetParentBCR = { top: 0, left: 0 };
            /** @type {?} */
            var elBCR = this.offset(nativeEl);
            /** @type {?} */
            var offsetParentEl = this.parentOffsetEl(nativeEl);
            if (offsetParentEl !== window.document) {
                offsetParentBCR = this.offset(offsetParentEl);
                offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
                offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
            }
            /** @type {?} */
            var boundingClientRect = nativeEl.getBoundingClientRect();
            return {
                width: boundingClientRect.width || nativeEl.offsetWidth,
                height: boundingClientRect.height || nativeEl.offsetHeight,
                top: elBCR.top - offsetParentBCR.top,
                left: elBCR.left - offsetParentBCR.left
            };
        };
        /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        PopoverContentComponent.prototype.offset = /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        function (nativeEl) {
            /** @type {?} */
            var boundingClientRect = nativeEl.getBoundingClientRect();
            return {
                width: boundingClientRect.width || nativeEl.offsetWidth,
                height: boundingClientRect.height || nativeEl.offsetHeight,
                top: boundingClientRect.top + (window.pageYOffset || window.document.documentElement.scrollTop),
                left: boundingClientRect.left + (window.pageXOffset || window.document.documentElement.scrollLeft)
            };
        };
        /**
         * @protected
         * @param {?} nativeEl
         * @param {?} cssProp
         * @return {?}
         */
        PopoverContentComponent.prototype.getStyle = /**
         * @protected
         * @param {?} nativeEl
         * @param {?} cssProp
         * @return {?}
         */
        function (nativeEl, cssProp) {
            if (((/** @type {?} */ (nativeEl))).currentStyle) { // IE
                return ((/** @type {?} */ (nativeEl))).currentStyle[cssProp];
            }
            if (window.getComputedStyle) {
                return ((/** @type {?} */ (window.getComputedStyle)))(nativeEl)[cssProp];
            }
            // finally try and get inline style
            return ((/** @type {?} */ (nativeEl.style)))[cssProp];
        };
        /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        PopoverContentComponent.prototype.isStaticPositioned = /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        function (nativeEl) {
            return (this.getStyle(nativeEl, 'position') || 'static') === 'static';
        };
        /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        PopoverContentComponent.prototype.parentOffsetEl = /**
         * @protected
         * @param {?} nativeEl
         * @return {?}
         */
        function (nativeEl) {
            /** @type {?} */
            var offsetParent = nativeEl.offsetParent || window.document;
            while (offsetParent && offsetParent !== window.document && this.isStaticPositioned(offsetParent)) {
                offsetParent = offsetParent.offsetParent;
            }
            return offsetParent || window.document;
        };
        // Check for overflow of the viewport and reflect the position if necessary.
        // Check for overflow of the viewport and reflect the position if necessary.
        /**
         * @protected
         * @param {?} placement
         * @param {?} hostElement
         * @param {?} targetElement
         * @return {?}
         */
        PopoverContentComponent.prototype.getEffectivePlacement = 
        // Check for overflow of the viewport and reflect the position if necessary.
        /**
         * @protected
         * @param {?} placement
         * @param {?} hostElement
         * @param {?} targetElement
         * @return {?}
         */
        function (placement, hostElement, targetElement) {
            /** @type {?} */
            var hostElBoundingRect = hostElement.getBoundingClientRect();
            /** @type {?} */
            var desiredPlacement = placement || PopoverPlacement.Top;
            // Determines if a popover overflows in a direction when in a specific position.
            /** @type {?} */
            var overflows = {
                positionTop: {
                    top: hostElBoundingRect.top - targetElement.offsetHeight < 0,
                    right: hostElBoundingRect.left + hostElBoundingRect.width / 2 + targetElement.offsetWidth / 2 > this.windowWidth,
                    left: hostElBoundingRect.left + hostElBoundingRect.width / 2 - targetElement.offsetWidth / 2 < 0
                },
                positionTopRight: {
                    top: hostElBoundingRect.top - targetElement.offsetHeight < 0,
                    right: hostElBoundingRect.right + targetElement.offsetWidth > this.windowWidth
                },
                positionRight: {
                    top: hostElBoundingRect.top + hostElBoundingRect.height / 2 - targetElement.offsetHeight / 2 < 0,
                    right: hostElBoundingRect.right + targetElement.offsetWidth > this.windowWidth,
                    bottom: hostElBoundingRect.top + hostElBoundingRect.height / 2 + targetElement.offsetHeight / 2 > this.windowHeight
                },
                positionBottomRight: {
                    right: hostElBoundingRect.right + targetElement.offsetWidth > this.windowWidth,
                    bottom: hostElBoundingRect.bottom + targetElement.offsetHeight > this.windowHeight
                },
                positionBottom: {
                    right: hostElBoundingRect.left + hostElBoundingRect.width / 2 + targetElement.offsetWidth / 2 > this.windowWidth,
                    bottom: hostElBoundingRect.bottom + targetElement.offsetHeight > this.windowHeight,
                    left: hostElBoundingRect.left + hostElBoundingRect.width / 2 - targetElement.offsetWidth / 2 < 0
                },
                positionBottomLeft: {
                    bottom: hostElBoundingRect.bottom + targetElement.offsetHeight > this.windowHeight,
                    left: hostElBoundingRect.left - targetElement.offsetWidth < 0
                },
                positionLeft: {
                    left: hostElBoundingRect.left < targetElement.offsetWidth,
                    top: hostElBoundingRect.top + hostElBoundingRect.height / 2 - targetElement.offsetHeight / 2 < 0,
                    bottom: hostElBoundingRect.top + hostElBoundingRect.height / 2 + targetElement.offsetHeight / 2 > this.windowHeight
                },
                positionTopLeft: {
                    top: hostElBoundingRect.top - targetElement.offsetHeight < 0,
                    left: hostElBoundingRect.left - targetElement.offsetWidth < 0
                }
            };
            if (desiredPlacement === PopoverPlacement.Top) {
                // If it overflows on the top AND left, go to bottom-right.
                if (overflows.positionTop.top && overflows.positionTop.left) {
                    return PopoverPlacement.BottomRight;
                    // If it overflows on the top AND right, go to bottom-left.
                }
                else if (overflows.positionTop.top && overflows.positionTop.right) {
                    return PopoverPlacement.BottomLeft;
                    // If it only overflows on the top, go to bottom.
                }
                else if (overflows.positionTop.top) {
                    return PopoverPlacement.Bottom;
                    // If it only overflows to the right, go to top-left.
                }
                else if (overflows.positionTop.right) {
                    return PopoverPlacement.TopLeft;
                    // If it only overflows to the left, go to top-right.
                }
                else if (overflows.positionTop.left) {
                    return PopoverPlacement.TopRight;
                }
                else {
                    return PopoverPlacement.Top;
                }
            }
            if (desiredPlacement === PopoverPlacement.TopRight) {
                // If it overflows on the top AND the right, try in the order: bottom, Bottom-left, left.
                if (overflows.positionTopRight.top && overflows.positionTopRight.right) {
                    if (overflows.positionBottom.bottom) {
                        return PopoverPlacement.Left;
                    }
                    else if (overflows.positionBottom.right) {
                        return PopoverPlacement.BottomLeft;
                    }
                    else {
                        return PopoverPlacement.Bottom;
                    }
                    // If it only overflows on the top, try in the order: right, bottom-right.
                }
                else if (overflows.positionTopRight.top) {
                    if (overflows.positionRight.top) {
                        return PopoverPlacement.BottomRight;
                    }
                    else {
                        return PopoverPlacement.Right;
                    }
                    // If it only overflows on the right, try in the order: top, top-left.
                }
                else if (overflows.positionTopRight.right) {
                    if (overflows.positionTop.right) {
                        return PopoverPlacement.TopLeft;
                    }
                    else {
                        return PopoverPlacement.Top;
                    }
                }
                else {
                    return PopoverPlacement.TopRight;
                }
            }
            if (desiredPlacement === PopoverPlacement.Right) {
                // If it overflows on the right AND the top, try in the order: bottom-right, bottom, bottom-left.
                if (overflows.positionRight.right && overflows.positionRight.top) {
                    if (overflows.positionBottomRight.right && overflows.positionBottom.right) {
                        return PopoverPlacement.BottomLeft;
                    }
                    else if (overflows.positionBottomRight.right) {
                        return PopoverPlacement.Bottom;
                    }
                    else {
                        return PopoverPlacement.BottomRight;
                    }
                    // If it overflows on the right AND the bottom, try in the order: top-right, top, top-left.
                }
                else if (overflows.positionRight.right && overflows.positionRight.bottom) {
                    if (overflows.positionTopRight.right && overflows.positionTop.right) {
                        return PopoverPlacement.TopLeft;
                    }
                    else if (overflows.positionTopRight.right) {
                        return PopoverPlacement.Top;
                    }
                    else {
                        return PopoverPlacement.TopRight;
                    }
                    // If it only overflows on the right, try all top positions from right to left, then try all bottom positions right to left.
                }
                else if (overflows.positionRight.right) {
                    if (overflows.positionTop.top) {
                        if (overflows.positionBottom.right) {
                            return PopoverPlacement.BottomLeft;
                        }
                        else if (overflows.positionBottomRight.right) {
                            return PopoverPlacement.Bottom;
                        }
                        else {
                            return PopoverPlacement.BottomRight;
                        }
                    }
                    else {
                        if (overflows.positionTop.right) {
                            return PopoverPlacement.TopLeft;
                        }
                        else if (overflows.positionTopRight.right) {
                            return PopoverPlacement.Top;
                        }
                        else {
                            return PopoverPlacement.TopRight;
                        }
                    }
                    // If it only over flows on the top, go bottom-right.
                }
                else if (overflows.positionRight.top) {
                    return PopoverPlacement.BottomRight;
                    // If it only overflows on the bottom, go top-right.
                }
                else if (overflows.positionRight.bottom) {
                    return PopoverPlacement.TopRight;
                }
                else {
                    return PopoverPlacement.Right;
                }
            }
            if (desiredPlacement === PopoverPlacement.BottomRight) {
                // If it overflows on the bottom AND the right, try in the order: top, top-left, left.
                if (overflows.positionBottomRight.bottom && overflows.positionBottomRight.right) {
                    if (overflows.positionTop.top) {
                        return PopoverPlacement.Left;
                    }
                    else if (overflows.positionTop.right) {
                        return PopoverPlacement.TopLeft;
                    }
                    else {
                        return PopoverPlacement.Top;
                    }
                    // If it only overflows on the bottom, try in the order: right, top-right.
                }
                else if (overflows.positionBottomRight.bottom) {
                    if (overflows.positionRight.bottom) {
                        return PopoverPlacement.TopRight;
                    }
                    else {
                        return PopoverPlacement.Right;
                    }
                    // If it only overflows on the right, try in the order: bottom, bottom-left.
                }
                else if (overflows.positionBottomRight.right) {
                    if (overflows.positionBottom.right) {
                        return PopoverPlacement.BottomLeft;
                    }
                    else {
                        return PopoverPlacement.Bottom;
                    }
                }
                else {
                    return PopoverPlacement.BottomRight;
                }
            }
            if (desiredPlacement === PopoverPlacement.Bottom) {
                // If it overflows on the bottom AND left, go to top-right.
                if (overflows.positionBottom.bottom && overflows.positionBottom.left) {
                    return PopoverPlacement.TopRight;
                    // If it overflows on the bottom AND right, go to top-left.
                }
                else if (overflows.positionBottom.bottom && overflows.positionBottom.right) {
                    return PopoverPlacement.TopLeft;
                    // If it only overflows on the bottom, go to top.
                }
                else if (overflows.positionBottom.bottom) {
                    return PopoverPlacement.Top;
                    // If it only overflows to the right, go to bottom-left.
                }
                else if (overflows.positionBottom.right) {
                    return PopoverPlacement.BottomLeft;
                    // If it only overflows to the left, go to bottom-right.
                }
                else if (overflows.positionBottom.left) {
                    return PopoverPlacement.BottomRight;
                }
                else {
                    return PopoverPlacement.Bottom;
                }
            }
            if (desiredPlacement === PopoverPlacement.BottomLeft) {
                // If it overflows on the bottom AND the left, try in the order: top, top-right, right.
                if (overflows.positionBottomLeft.bottom && overflows.positionBottomLeft.left) {
                    if (overflows.positionTop.top) {
                        return PopoverPlacement.Right;
                    }
                    else if (overflows.positionTop.left) {
                        return PopoverPlacement.TopRight;
                    }
                    else {
                        return PopoverPlacement.Top;
                    }
                    // If it only overflows on the bottom, try in the order: left, top-left.
                }
                else if (overflows.positionBottomLeft.bottom) {
                    if (overflows.positionLeft.bottom) {
                        return PopoverPlacement.TopLeft;
                    }
                    else {
                        return PopoverPlacement.Left;
                    }
                    // If it only overflows on the left, try in the order: bottom, bottom-right.
                }
                else if (overflows.positionBottomLeft.left) {
                    if (overflows.positionBottom.left) {
                        return PopoverPlacement.BottomRight;
                    }
                    else {
                        return PopoverPlacement.Bottom;
                    }
                }
                else {
                    return PopoverPlacement.BottomLeft;
                }
            }
            if (desiredPlacement === PopoverPlacement.Left) {
                // If it overflows on the left AND the top, try in the order: bottom-left, bottom, bottom-right.
                if (overflows.positionLeft.left && overflows.positionLeft.top) {
                    if (overflows.positionBottomLeft.left && overflows.positionBottom.left) {
                        return PopoverPlacement.BottomRight;
                    }
                    else if (overflows.positionBottomRight.right) {
                        return PopoverPlacement.Bottom;
                    }
                    else {
                        return PopoverPlacement.BottomLeft;
                    }
                    // If it overflows on the left AND the bottom, try in the order: top-left, top, top-right.
                }
                else if (overflows.positionLeft.left && overflows.positionLeft.bottom) {
                    if (overflows.positionTopLeft.left && overflows.positionTop.left) {
                        return PopoverPlacement.TopRight;
                    }
                    else if (overflows.positionTopLeft.left) {
                        return PopoverPlacement.Top;
                    }
                    else {
                        return PopoverPlacement.TopLeft;
                    }
                    // If it only overflows on the left, try all top positions from left to right, then try all bottom positions left to right.
                }
                else if (overflows.positionLeft.left) {
                    if (overflows.positionTop.top) {
                        if (overflows.positionBottom.left) {
                            return PopoverPlacement.BottomRight;
                        }
                        else if (overflows.positionBottomLeft.left) {
                            return PopoverPlacement.Bottom;
                        }
                        else {
                            return PopoverPlacement.BottomLeft;
                        }
                    }
                    else {
                        if (overflows.positionTop.left) {
                            return PopoverPlacement.TopRight;
                        }
                        else if (overflows.positionTopLeft.left) {
                            return PopoverPlacement.Top;
                        }
                        else {
                            return PopoverPlacement.TopLeft;
                        }
                    }
                    // If it only over flows on the top, go bottom-left.
                }
                else if (overflows.positionLeft.top) {
                    return PopoverPlacement.BottomLeft;
                    // If it only overflows on the bottom, go top-left.
                }
                else if (overflows.positionLeft.bottom) {
                    return PopoverPlacement.TopLeft;
                }
                else {
                    return PopoverPlacement.Left;
                }
            }
            if (desiredPlacement === PopoverPlacement.TopLeft) {
                // If it overflows on the top AND the left, try in the order: bottom, Bottom-right, right.
                if (overflows.positionTopLeft.top && overflows.positionTopLeft.left) {
                    if (overflows.positionBottom.bottom) {
                        return PopoverPlacement.Right;
                    }
                    else if (overflows.positionBottom.left) {
                        return PopoverPlacement.BottomRight;
                    }
                    else {
                        return PopoverPlacement.Bottom;
                    }
                    // If it only overflows on the top, try in the order: left, bottom-left.
                }
                else if (overflows.positionTopLeft.top) {
                    if (overflows.positionLeft.top) {
                        return PopoverPlacement.BottomLeft;
                    }
                    else {
                        return PopoverPlacement.Left;
                    }
                    // If it only overflows on the left, try in the order: top, top-right.
                }
                else if (overflows.positionTopLeft.left) {
                    if (overflows.positionTop.left) {
                        return PopoverPlacement.TopRight;
                    }
                    else {
                        return PopoverPlacement.Top;
                    }
                }
                else {
                    return PopoverPlacement.TopLeft;
                }
            }
            return desiredPlacement;
        };
        PopoverContentComponent.decorators = [
            { type: core.Component, args: [{
                        selector: 'popover-content',
                        template: "\n        <div #popoverDiv\n            class=\"bs-popover-{{ effectivePlacement }} popover-content popover {{ parentClass }}\"\n            [ngClass]=\"{\n                'sm': size === 'small',\n                'md-sm': size === 'medium-small',\n                'md': size === 'medium',\n                'lg': size === 'large',\n                'in': isIn\n            }\"\n            [style.top.px]=\"top\"\n            [style.left.px]=\"left\"\n            [style.transition]=\"(transitionEnabled ? '0.15s opacity' : '')\"\n            [style.opacity]=\"opacity\"\n            [style.display]=\"'block'\"\n            [attr.aria-hidden]=\"opacity === 0\"\n            role=\"popover\">\n                <div [hidden]=\"!closeOnMouseOutside\" class=\"virtual-area\"></div>\n                <div class=\"arrow\"></div>\n                <div class=\"popover-header\" [hidden]=\"!title\">{{ title }}</div>\n                <div class=\"popover-body\">\n                    <ng-content></ng-content>\n                    {{ content }}\n                </div>\n        </div>\n    "
                    }] }
        ];
        /** @nocollapse */
        PopoverContentComponent.ctorParameters = function () { return [
            { type: core.ElementRef },
            { type: core.ChangeDetectorRef },
            { type: core.Renderer2 }
        ]; };
        PopoverContentComponent.propDecorators = {
            content: [{ type: core.Input }],
            placement: [{ type: core.Input }],
            title: [{ type: core.Input }],
            parentClass: [{ type: core.Input }],
            animation: [{ type: core.Input }],
            closeOnClickOutside: [{ type: core.Input }],
            closeOnMouseOutside: [{ type: core.Input }],
            appendToBody: [{ type: core.Input }],
            size: [{ type: core.Input }],
            popoverDiv: [{ type: core.ViewChild, args: ['popoverDiv', { static: true },] }],
            onResize: [{ type: core.HostListener, args: ['window:resize', ['$event'],] }]
        };
        return PopoverContentComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * Generated from: lib/popover.directive.ts
     * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
     */
    /**
     * \@group Basic Toolkit
     * \@component Popover Directive
     */
    var PopoverDirective = /** @class */ (function () {
        // -------------------------------------------------------------------------
        // Constructor
        // -------------------------------------------------------------------------
        function PopoverDirective(viewContainerRef, cdr, resolver, appRef, injector) {
            this.viewContainerRef = viewContainerRef;
            this.cdr = cdr;
            this.resolver = resolver;
            this.appRef = appRef;
            this.injector = injector;
            // -------------------------------------------------------------------------
            // Properties
            // -------------------------------------------------------------------------
            this.popoverContentComponent = PopoverContentComponent;
            this.popoverOnHover = true;
            this.popoverDismissTimeout = 0;
            this.onShown = new core.EventEmitter();
            this.onHidden = new core.EventEmitter();
        }
        // -------------------------------------------------------------------------
        // Event listeners
        // -------------------------------------------------------------------------
        // -------------------------------------------------------------------------
        // Event listeners
        // -------------------------------------------------------------------------
        /**
         * @param {?} evt
         * @return {?}
         */
        PopoverDirective.prototype.showOrHideOnClick = 
        // -------------------------------------------------------------------------
        // Event listeners
        // -------------------------------------------------------------------------
        /**
         * @param {?} evt
         * @return {?}
         */
        function (evt) {
            if (this.popoverOnHover) {
                return;
            }
            if (this.popoverDisabled) {
                return;
            }
            evt.stopImmediatePropagation();
            this.toggle();
        };
        /**
         * @param {?} evt
         * @return {?}
         */
        PopoverDirective.prototype.showOrHideOnTouch = /**
         * @param {?} evt
         * @return {?}
         */
        function (evt) {
            evt.stopImmediatePropagation();
            if (!this.popoverOnHover) {
                return;
            }
            if (this.popoverDisabled) {
                return;
            }
            this.toggle();
        };
        /**
         * @return {?}
         */
        PopoverDirective.prototype.showOnHover = /**
         * @return {?}
         */
        function () {
            if (!this.popoverOnHover) {
                return;
            }
            if (this.popoverDisabled) {
                return;
            }
            this.show();
        };
        /**
         * @return {?}
         */
        PopoverDirective.prototype.hideOnHover = /**
         * @return {?}
         */
        function () {
            if (this.popoverCloseOnMouseOutside) {
                return; // don't do anything since we do not control this
            }
            if (!this.popoverOnHover) {
                return;
            }
            if (this.popoverDisabled) {
                return;
            }
            this.hide();
        };
        /**
         * @param {?} changes
         * @return {?}
         */
        PopoverDirective.prototype.ngOnChanges = /**
         * @param {?} changes
         * @return {?}
         */
        function (changes) {
            if (changes['popoverDisabled']) {
                if (changes['popoverDisabled'].currentValue) {
                    this.hide();
                }
            }
        };
        /**
         * @protected
         * @param {?} component
         * @return {?}
         */
        PopoverDirective.prototype.createComponent = /**
         * @protected
         * @param {?} component
         * @return {?}
         */
        function (component) {
            /** @type {?} */
            var factory = this.resolver.resolveComponentFactory(component);
            // Create a component reference from the component
            /** @type {?} */
            var componentRef = this.appendToBody
                ? factory.create(this.injector)
                : this.viewContainerRef.createComponent(factory);
            if (this.appendToBody) {
                // Attach component to the appRef so that it's inside the ng component tree
                this.appRef.attachView(componentRef.hostView);
                // Get DOM element from component
                /** @type {?} */
                var domElem = (/** @type {?} */ (((/** @type {?} */ (componentRef.hostView)))
                    .rootNodes[0]));
                // Append DOM element to the body
                document.body.appendChild(domElem);
            }
            return componentRef;
        };
        /**
         * @protected
         * @param {?} componentRef
         * @return {?}
         */
        PopoverDirective.prototype.removeComponent = /**
         * @protected
         * @param {?} componentRef
         * @return {?}
         */
        function (componentRef) {
            if (this.popover) {
                if (this.appendToBody) {
                    this.appRef.detachView(componentRef.hostView);
                }
                componentRef.destroy();
            }
        };
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        /**
         * @return {?}
         */
        PopoverDirective.prototype.toggle = 
        // -------------------------------------------------------------------------
        // Public Methods
        // -------------------------------------------------------------------------
        /**
         * @return {?}
         */
        function () {
            if (!this.visible) {
                this.show();
            }
            else {
                this.hide();
            }
        };
        /**
         * @return {?}
         */
        PopoverDirective.prototype.show = /**
         * @return {?}
         */
        function () {
            var _this = this;
            if (this.visible) {
                return;
            }
            this.visible = true;
            if (typeof this.content === 'string') {
                if (!this.visible) {
                    return;
                }
                this.popover = this.createComponent(this.popoverContentComponent);
                /** @type {?} */
                var popover = (/** @type {?} */ (this.popover.instance));
                popover.popover = this;
                popover.content = (/** @type {?} */ (this.content));
                if (this.popoverPlacement !== undefined) {
                    popover.placement = this.popoverPlacement;
                }
                if (this.popoverAnimation !== undefined) {
                    popover.animation = this.popoverAnimation;
                }
                if (this.popoverTitle !== undefined) {
                    popover.title = this.popoverTitle;
                }
                if (this.popoverCloseOnClickOutside !== undefined) {
                    popover.closeOnClickOutside = this.popoverCloseOnClickOutside;
                }
                if (this.popoverCloseOnMouseOutside !== undefined) {
                    popover.closeOnMouseOutside = this.popoverCloseOnMouseOutside;
                }
                if (this.popoverSize) {
                    popover.size = this.popoverSize;
                }
                popover.appendToBody = this.appendToBody;
                popover.onCloseFromOutside.subscribe((/**
                 * @return {?}
                 */
                function () { return _this.hide(); }));
                // if dismissTimeout option is set, then this popover will be dismissed in dismissTimeout time
                if (this.popoverDismissTimeout > 0) {
                    setTimeout((/**
                     * @return {?}
                     */
                    function () { return _this.hide(); }), this.popoverDismissTimeout);
                }
            }
            else {
                /** @type {?} */
                var popover = (/** @type {?} */ (this.content));
                popover.popover = this;
                if (this.popoverPlacement !== undefined) {
                    popover.placement = this.popoverPlacement;
                }
                if (this.popoverAnimation !== undefined) {
                    popover.animation = this.popoverAnimation;
                }
                if (this.popoverTitle !== undefined) {
                    popover.title = this.popoverTitle;
                }
                if (this.popoverCloseOnClickOutside !== undefined) {
                    popover.closeOnClickOutside = this.popoverCloseOnClickOutside;
                }
                if (this.popoverCloseOnMouseOutside !== undefined) {
                    popover.closeOnMouseOutside = this.popoverCloseOnMouseOutside;
                }
                if (this.popoverSize) {
                    popover.size = this.popoverSize;
                }
                popover.appendToBody = this.appendToBody;
                popover.onCloseFromOutside.subscribe((/**
                 * @return {?}
                 */
                function () { return _this.hide(); }));
                // if dismissTimeout option is set, then this popover will be dismissed in dismissTimeout time
                if (this.popoverDismissTimeout > 0) {
                    setTimeout((/**
                     * @return {?}
                     */
                    function () { return _this.hide(); }), this.popoverDismissTimeout);
                }
                popover.show();
            }
            this.cdr.detectChanges();
            this.onShown.emit(this);
        };
        /**
         * @return {?}
         */
        PopoverDirective.prototype.hide = /**
         * @return {?}
         */
        function () {
            if (!this.visible) {
                return;
            }
            this.visible = false;
            this.removeComponent(this.popover);
            if (this.content instanceof PopoverContentComponent) {
                ((/** @type {?} */ (this.content))).hideFromPopover();
            }
            this.cdr.detectChanges();
            this.onHidden.emit(this);
        };
        /**
         * @return {?}
         */
        PopoverDirective.prototype.getElement = /**
         * @return {?}
         */
        function () {
            return this.viewContainerRef.element.nativeElement;
        };
        PopoverDirective.decorators = [
            { type: core.Directive, args: [{
                        selector: '[popover]',
                        exportAs: 'popover'
                    },] }
        ];
        /** @nocollapse */
        PopoverDirective.ctorParameters = function () { return [
            { type: core.ViewContainerRef },
            { type: core.ChangeDetectorRef },
            { type: core.ComponentFactoryResolver },
            { type: core.ApplicationRef },
            { type: core.Injector }
        ]; };
        PopoverDirective.propDecorators = {
            content: [{ type: core.Input, args: ['popover',] }],
            popoverSize: [{ type: core.Input }],
            popoverDisabled: [{ type: core.Input }],
            popoverAnimation: [{ type: core.Input }],
            popoverPlacement: [{ type: core.Input }],
            popoverTitle: [{ type: core.Input }],
            popoverOnHover: [{ type: core.Input }],
            popoverCloseOnClickOutside: [{ type: core.Input }],
            popoverCloseOnMouseOutside: [{ type: core.Input }],
            popoverDismissTimeout: [{ type: core.Input }],
            appendToBody: [{ type: core.Input }],
            onShown: [{ type: core.Output }],
            onHidden: [{ type: core.Output }],
            showOrHideOnClick: [{ type: core.HostListener, args: ['click', ['$event'],] }],
            showOrHideOnTouch: [{ type: core.HostListener, args: ['touchend', ['$event'],] }],
            showOnHover: [{ type: core.HostListener, args: ['focusin',] }, { type: core.HostListener, args: ['mouseenter',] }],
            hideOnHover: [{ type: core.HostListener, args: ['focusout',] }, { type: core.HostListener, args: ['mouseleave',] }]
        };
        return PopoverDirective;
    }());

    /**
     * @fileoverview added by tsickle
     * Generated from: lib/popover.module.ts
     * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
     */
    var PopoverModule = /** @class */ (function () {
        function PopoverModule() {
        }
        PopoverModule.decorators = [
            { type: core.NgModule, args: [{
                        declarations: [
                            PopoverDirective,
                            PopoverContentComponent
                        ],
                        imports: [
                            common.CommonModule,
                        ],
                        exports: [
                            PopoverContentComponent,
                            PopoverDirective
                        ],
                        entryComponents: [
                            PopoverContentComponent
                        ]
                    },] }
        ];
        return PopoverModule;
    }());

    exports.PopoverContentComponent = PopoverContentComponent;
    exports.PopoverDirective = PopoverDirective;
    exports.PopoverModule = PopoverModule;
    exports.PopoverPlacement = PopoverPlacement;

    Object.defineProperty(exports, '__esModule', { value: true });

}));
//# sourceMappingURL=ngx-smart-popover.umd.js.map