"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var Utilities_1 = require("../Utilities");
var RectangleEdge;
(function (RectangleEdge) {
    RectangleEdge[RectangleEdge["top"] = 1] = "top";
    RectangleEdge[RectangleEdge["bottom"] = -1] = "bottom";
    RectangleEdge[RectangleEdge["left"] = 2] = "left";
    RectangleEdge[RectangleEdge["right"] = -2] = "right";
})(RectangleEdge = exports.RectangleEdge || (exports.RectangleEdge = {}));
var Position;
(function (Position) {
    Position[Position["top"] = 0] = "top";
    Position[Position["bottom"] = 1] = "bottom";
    Position[Position["start"] = 2] = "start";
    Position[Position["end"] = 3] = "end";
})(Position = exports.Position || (exports.Position = {}));
var SLIDE_ANIMATIONS = (_a = {},
    _a[RectangleEdge.top] = 'slideUpIn20',
    _a[RectangleEdge.bottom] = 'slideDownIn20',
    _a[RectangleEdge.left] = 'slideLeftIn20',
    _a[RectangleEdge.right] = 'slideRightIn20',
    _a);
var Rectangle = (function (_super) {
    tslib_1.__extends(Rectangle, _super);
    function Rectangle() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Rectangle;
}(Utilities_1.Rectangle));
exports.Rectangle = Rectangle;
function _createPositionData(targetEdge, alignmentEdge, isAuto) {
    return {
        targetEdge: targetEdge,
        alignmentEdge: alignmentEdge,
        isAuto: isAuto
    };
}
// Currently the beakPercent is set to 50 for all positions meaning that it should tend to the center of the target
var DirectionalDictionary = (_b = {},
    _b[0 /* topLeftEdge */] = _createPositionData(RectangleEdge.top, RectangleEdge.left),
    _b[1 /* topCenter */] = _createPositionData(RectangleEdge.top),
    _b[2 /* topRightEdge */] = _createPositionData(RectangleEdge.top, RectangleEdge.right),
    _b[3 /* topAutoEdge */] = _createPositionData(RectangleEdge.top, undefined, true),
    _b[4 /* bottomLeftEdge */] = _createPositionData(RectangleEdge.bottom, RectangleEdge.left),
    _b[5 /* bottomCenter */] = _createPositionData(RectangleEdge.bottom),
    _b[6 /* bottomRightEdge */] = _createPositionData(RectangleEdge.bottom, RectangleEdge.right),
    _b[7 /* bottomAutoEdge */] = _createPositionData(RectangleEdge.bottom, undefined, true),
    _b[8 /* leftTopEdge */] = _createPositionData(RectangleEdge.left, RectangleEdge.top),
    _b[9 /* leftCenter */] = _createPositionData(RectangleEdge.left),
    _b[10 /* leftBottomEdge */] = _createPositionData(RectangleEdge.left, RectangleEdge.bottom),
    _b[11 /* rightTopEdge */] = _createPositionData(RectangleEdge.right, RectangleEdge.top),
    _b[12 /* rightCenter */] = _createPositionData(RectangleEdge.right),
    _b[13 /* rightBottomEdge */] = _createPositionData(RectangleEdge.right, RectangleEdge.bottom),
    _b);
var positioningFunctions;
(function (positioningFunctions) {
    function _isRectangleWithinBounds(rect, boundingRect) {
        if (rect.top < boundingRect.top) {
            return false;
        }
        if (rect.bottom > boundingRect.bottom) {
            return false;
        }
        if (rect.left < boundingRect.left) {
            return false;
        }
        if (rect.right > boundingRect.right) {
            return false;
        }
        return true;
    }
    /**
     * Gets all of the edges of a rectangle that are outside of the given bounds.
     * If there are no out of bounds edges it returns an empty array.
     */
    function _getOutOfBoundsEdges(rect, boundingRect) {
        var outOfBounds = new Array();
        if (rect.top < boundingRect.top) {
            outOfBounds.push(RectangleEdge.top);
        }
        if (rect.bottom > boundingRect.bottom) {
            outOfBounds.push(RectangleEdge.bottom);
        }
        if (rect.left < boundingRect.left) {
            outOfBounds.push(RectangleEdge.left);
        }
        if (rect.right > boundingRect.right) {
            outOfBounds.push(RectangleEdge.right);
        }
        return outOfBounds;
    }
    function _getEdgeValue(rect, edge) {
        return rect[RectangleEdge[edge]];
    }
    function _setEdgeValue(rect, edge, value) {
        rect[RectangleEdge[edge]] = value;
        return rect;
    }
    /**
     * Returns the middle value of an edge. Only returns 1 value rather than xy coordinates as
     * the itself already contains the other coordinate.
     * For instance, a bottom edge's current value is it's y coordinate, so the number returned is the x.
     *
     * @param {Rectangle} rect
     * @param {RectangleEdge} edge
     * @returns {number}
     */
    function _getCenterValue(rect, edge) {
        var edges = _getFlankingEdges(edge);
        return (_getEdgeValue(rect, edges.firstEdge) + _getEdgeValue(rect, edges.secondEdge)) / 2;
    }
    /**
     * Flips the value depending on the edge.
     * If the edge is a "positive" edge, Top or Left, then the value should stay as it is.
     * If the edge is a "negative" edge, Bottom or Right, then the value should be flipped.
     * This is to account for the fact that the coordinates are effectively reveserved in certain cases for the "negative" edges.
     * For example, when testing to see if a bottom edge 1 is within the bounds of another bottom edge 2.
     * If edge 1 is greater than edge 2 then it is out of bounds. This is reversed for top edge 1 and top edge 2.
     * If top edge 1 is less than edge 2 then it is out of bounds.
     *
     *
     * @param {RectangleEdge} edge
     * @param {number} value
     * @returns {number}
     */
    function _getRelativeEdgeValue(edge, value) {
        if (edge > 0) {
            return value;
        }
        else {
            return value * -1;
        }
    }
    function _getRelativeRectEdgeValue(edge, rect) {
        return _getRelativeEdgeValue(edge, _getEdgeValue(rect, edge));
    }
    function _getRelativeEdgeDifference(rect, hostRect, edge) {
        var edgeDifference = _getEdgeValue(rect, edge) - _getEdgeValue(hostRect, edge);
        return _getRelativeEdgeValue(edge, edgeDifference);
    }
    /**
     * Moves the edge of a rectangle to the value given. It only moves the edge in a linear direction based on that edge.
     * For example, if it's a bottom edge it will only change y coordinates.
     *
     * @param {Rectangle} rect
     * @param {RectangleEdge} edge
     * @param {number} newValue
     * @returns {Rectangle}
     */
    function _moveEdge(rect, edge, newValue) {
        var difference = _getEdgeValue(rect, edge) - newValue;
        rect = _setEdgeValue(rect, edge, newValue);
        rect = _setEdgeValue(rect, edge * -1, _getEdgeValue(rect, edge * -1) - difference);
        return rect;
    }
    /**
     * Aligns the edge on the passed in rect to the target. If there is a gap then it will have that space between the two.
     *
     * @param {Rectangle} rect
     * @param {Rectangle} target
     * @param {RectangleEdge} edge
     * @param {number} [gap=0]
     * @returns {Rectangle}
     */
    function _alignEdges(rect, target, edge, gap) {
        if (gap === void 0) { gap = 0; }
        return _moveEdge(rect, edge, _getEdgeValue(target, edge) + _getRelativeEdgeValue(edge, gap));
    }
    /**
     * Aligns the targetEdge on the passed in target to the rects corresponding opposite edge.
     * For instance if targetEdge is bottom, then the rects top will be moved to match it.
     *
     * @param {Rectangle} rect
     * @param {Rectangle} target
     * @param {RectangleEdge} targetEdge
     * @param {number} [gap=0]
     * @returns {Rectangle}
     */
    function _alignOppositeEdges(rect, target, targetEdge, gap) {
        if (gap === void 0) { gap = 0; }
        var oppositeEdge = targetEdge * -1;
        var adjustedGap = _getRelativeEdgeValue(oppositeEdge, gap);
        return _moveEdge(rect, targetEdge * -1, _getEdgeValue(target, targetEdge) + adjustedGap);
    }
    /**
     * Tests to see if the given edge is within the bounds of the given rectangle.
     *
     * @param {Rectangle} rect
     * @param {Rectangle} bounds
     * @param {RectangleEdge} edge
     * @returns {boolean}
     */
    function _isEdgeInBounds(rect, bounds, edge) {
        var adjustedRectValue = _getRelativeRectEdgeValue(edge, rect);
        // The adjusted value must be reversed to determine if it is within the bounds.
        // Take these two examples:
        // Top is out of bounds with -4 as value. Top is not reversed in _getRelativeRectEdgeValue. -4 * -1 = 4
        // 4 is not less than the bounds of 0, so it must be out of bounds.
        // Bottom is out of bounds with 5 as value, bounds bottom is 4. Bottom is reversed in _getRelaitveRectEdgeValue.
        // Bottom is now -5. Bottom * -1 is now 5. 5 is greater than bounds bottom of 4, so it must be out of bounds.
        return adjustedRectValue * -1 < _getEdgeValue(bounds, edge);
    }
    /**
     * Attempts to move the rectangle through various sides of the target to find a place to fit.
     * If no fit is found, the original position should be returned.
     *
     * @param {Rectangle} rect
     * @param {Rectangle} target
     * @param {Rectangle} bounding
     * @param {IPositionData} positionData
     * @param {number} [gap=0]
     * @returns {ICallout}
     */
    function _flipToFit(rect, target, bounding, positionData, gap) {
        if (gap === void 0) { gap = 0; }
        var directions = [RectangleEdge.left, RectangleEdge.right, RectangleEdge.bottom, RectangleEdge.top];
        var currentEstimate = rect;
        var currentEdge = positionData.targetEdge;
        var currentAlignment = positionData.alignmentEdge;
        // Keep switching sides until one is found with enough space. If all sides don't fit then return the unmodified callout.
        for (var i = 0; i < 4; i++) {
            if (!_isEdgeInBounds(currentEstimate, bounding, currentEdge)) {
                directions.splice(directions.indexOf(currentEdge), 1);
                if (directions.indexOf(currentEdge * -1) > -1) {
                    currentEdge = currentEdge * -1;
                }
                else {
                    currentAlignment = currentEdge;
                    currentEdge = directions.slice(-1)[0];
                }
                currentEstimate = _estimatePosition(rect, target, { targetEdge: currentEdge, alignmentEdge: currentAlignment }, gap);
            }
            else {
                return {
                    calloutRectangle: currentEstimate,
                    targetEdge: currentEdge,
                    alignmentEdge: currentAlignment
                };
            }
        }
        return {
            calloutRectangle: rect,
            targetEdge: positionData.targetEdge,
            alignmentEdge: currentAlignment
        };
    }
    /**
     * Adjusts a callout rectangle to fit within the bounds given. If directionalHintFixed or covertarget is passed in
     * then the callout will not flip sides on the target. They will, however, be nudged to fit within the bounds given.
     *
     * @param {Rectangle} callout
     * @param {Rectangle} target
     * @param {Rectangle} bounding
     * @param {IPositionData} positionData
     * @param {number} [gap=0]
     * @param {boolean} [directionalHintFixed]
     * @param {boolean} [coverTarget]
     * @returns {ICallout}
     */
    function _adjustFitWithinBounds(callout, target, bounding, positionData, gap, directionalHintFixed, coverTarget) {
        if (gap === void 0) { gap = 0; }
        var alignmentEdge = positionData.alignmentEdge;
        var calloutEstimate = {
            calloutRectangle: callout,
            targetEdge: positionData.targetEdge,
            alignmentEdge: alignmentEdge
        };
        if (!directionalHintFixed && !coverTarget) {
            calloutEstimate = _flipToFit(callout, target, bounding, positionData, gap);
        }
        var outOfBounds = _getOutOfBoundsEdges(callout, bounding);
        for (var _i = 0, outOfBounds_1 = outOfBounds; _i < outOfBounds_1.length; _i++) {
            var direction = outOfBounds_1[_i];
            calloutEstimate.calloutRectangle = _alignEdges(calloutEstimate.calloutRectangle, bounding, direction);
        }
        return calloutEstimate;
    }
    /**
     * Moves the middle point on an edge to the point given.
     * Only moves in one direction. For instance if a bottom edge is passed in, then
     * the bottom edge will be moved in the x axis to match the point.
     *
     * @param {Rectangle} rect
     * @param {RectangleEdge} edge
     * @param {number} point
     * @returns
     */
    function centerEdgeToPoint(rect, edge, point) {
        var firstEdge = _getFlankingEdges(edge).firstEdge;
        var calloutMiddle = _getCenterValue(rect, edge);
        var distanceToMiddle = calloutMiddle - _getEdgeValue(rect, firstEdge);
        return _moveEdge(rect, firstEdge, point - distanceToMiddle);
    }
    /**
     * Moves the callout rectangle to be appropriately positioned relative to a given target.
     * Does not flip or adjust the callout.
     *
     * @param {Rectangle} callout
     * @param {Rectangle} target
     * @param {IPositionData} positionData
     * @param {number} [gap=0]
     * @param {boolean} [coverTarget]
     * @returns {Rectangle}
     */
    function _estimatePosition(callout, target, positionData, gap, coverTarget) {
        if (gap === void 0) { gap = 0; }
        var estimatedCalloutPosition;
        var alignmentEdge = positionData.alignmentEdge, targetEdge = positionData.targetEdge;
        var calloutEdge = coverTarget ? targetEdge : targetEdge * -1;
        estimatedCalloutPosition = coverTarget ? _alignEdges(callout, target, targetEdge, gap) :
            _alignOppositeEdges(callout, target, targetEdge, gap);
        // if no alignment edge is provided it's supposed to be centered.
        if (!alignmentEdge) {
            var targetMiddlePoint = _getCenterValue(target, targetEdge);
            estimatedCalloutPosition = centerEdgeToPoint(estimatedCalloutPosition, calloutEdge, targetMiddlePoint);
        }
        else {
            estimatedCalloutPosition = _alignEdges(estimatedCalloutPosition, target, alignmentEdge);
        }
        return estimatedCalloutPosition;
    }
    /**
     * Returns the non-opposite edges of the target edge.
     * For instance if bottom is passed in then left and right will be returned.
     *
     * @param {RectangleEdge} edge
     * @returns {{ firstEdge: RectangleEdge, secondEdge: RectangleEdge }}
     */
    function _getFlankingEdges(edge) {
        if (edge === RectangleEdge.top || edge === RectangleEdge.bottom) {
            return {
                firstEdge: RectangleEdge.left,
                secondEdge: RectangleEdge.right
            };
        }
        else {
            return {
                firstEdge: RectangleEdge.top,
                secondEdge: RectangleEdge.bottom
            };
        }
    }
    /**
     * Finalizes the callout positon based on the hostElement. Only returns the
     * rectangle values to position such that they are anchored to the target.
     * This helps prevent resizing from looking very strange.
     * For instance, if the target edge is top and aligned with the left side then
     * the bottom and left values are returned so as the callou shrinks it shrinks towards that corner.
     *
     * @param {Rectangle} calloutRectangle
     * @param {HTMLElement} hostElement
     * @param {RectangleEdge} targetEdge
     * @param {RectangleEdge} [alignmentEdge]
     * @returns {IPartialIRectangle}
     */
    function _finalizeCalloutPosition(calloutRectangle, hostElement, targetEdge, alignmentEdge) {
        var returnValue = {};
        var hostRect = _getRectangleFromHTMLElement(hostElement);
        var calloutEdge = targetEdge * -1;
        var calloutEdgeString = RectangleEdge[calloutEdge];
        var returnEdge = alignmentEdge ? alignmentEdge : _getFlankingEdges(targetEdge).firstEdge;
        returnValue[calloutEdgeString] = _getRelativeEdgeDifference(calloutRectangle, hostRect, calloutEdge);
        returnValue[RectangleEdge[returnEdge]] = _getRelativeEdgeDifference(calloutRectangle, hostRect, returnEdge);
        return returnValue;
    }
    // Since the beak is rotated 45 degrees the actual height/width is the length of the diagonal.
    // We still want to position the beak based on it's midpoint which does not change. It will
    // be at (beakwidth / 2, beakwidth / 2)
    function _calculateActualBeakWidthInPixels(beakWidth) {
        return Math.sqrt(beakWidth * beakWidth * 2);
    }
    positioningFunctions._calculateActualBeakWidthInPixels = _calculateActualBeakWidthInPixels;
    /**
     * Returns the appropriate IPositionData based on the props altered for RTL.
     * If directionalHintForRTL is passed in that is used if the page is RTL.
     * If a directionalHint is specified and no directionalHintForRTL is available and the page is RTL the hint will be flipped.
     * For instance bottomLeftEdge would become bottomRightEdge.
     * If there is no directionalHint passed in bottomAutoEdge is chosen automatically.
     *
     * @param {IPositionProps} props
     * @returns {IPositionData}
     */
    function _getPositionData(directionalHint, directionalHintForRTL) {
        if (directionalHint === void 0) { directionalHint = 7 /* bottomAutoEdge */; }
        var positionInformation = tslib_1.__assign({}, DirectionalDictionary[directionalHint]);
        if (Utilities_1.getRTL()) {
            // If alignment edge exists and that alignment edge is -2 or 2, right or left, then flip it.
            positionInformation.alignmentEdge = positionInformation.alignmentEdge && positionInformation.alignmentEdge % 2 === 0
                ? positionInformation.alignmentEdge * -1 : undefined;
            return directionalHintForRTL !== undefined ?
                DirectionalDictionary[directionalHintForRTL] :
                positionInformation;
        }
        return positionInformation;
    }
    positioningFunctions._getPositionData = _getPositionData;
    /**
     * Get's the alignment data for the given information. This only really matters if the positioning is Auto.
     * If it is auto then the alignmentEdge should be chosen based on the target edge's position relative to
     * the center of the page.
     *
     * @param {IPositionData} positionData
     * @param {Rectangle} target
     * @param {Rectangle} boundingRect
     * @param {boolean} [coverTarget]
     * @returns {IPositionData}
     */
    function _getAlignmentData(positionData, target, boundingRect, coverTarget) {
        if (positionData.isAuto) {
            var center = _getCenterValue(target, positionData.targetEdge);
            if (center <= boundingRect.width / 2) {
                positionData.alignmentEdge = RectangleEdge.left;
            }
            else {
                positionData.alignmentEdge = RectangleEdge.right;
            }
        }
        return positionData;
    }
    function _positionCalloutWithinBounds(callout, target, bounding, positionData, gap, directionalHintFixed, coverTarget) {
        var estimatedCalloutPosition = _estimatePosition(callout, target, positionData, gap, coverTarget);
        if (_isRectangleWithinBounds(estimatedCalloutPosition, bounding)) {
            return {
                calloutRectangle: estimatedCalloutPosition,
                targetEdge: positionData.targetEdge,
                alignmentEdge: positionData.alignmentEdge
            };
        }
        else {
            return _adjustFitWithinBounds(callout, target, bounding, positionData, gap, directionalHintFixed, coverTarget);
        }
    }
    positioningFunctions._positionCalloutWithinBounds = _positionCalloutWithinBounds;
    function _positionBeak(beakWidth, callout, target, alignmentEdge) {
        var _a = _getFlankingEdges(callout.targetEdge), firstEdge = _a.firstEdge, secondEdge = _a.secondEdge;
        var beakTargetPoint = _getCenterValue(target, callout.targetEdge);
        var actualBeakWidth = _calculateActualBeakWidthInPixels(beakWidth);
        // The "host" callout that we will use to help position the beak.
        var actualCallout = new Rectangle(0, callout.calloutRectangle.width, 0, callout.calloutRectangle.height);
        var calloutBounds = new Rectangle(actualBeakWidth / 2, callout.calloutRectangle.width - actualBeakWidth / 2, actualBeakWidth / 2, callout.calloutRectangle.height - actualBeakWidth / 2);
        var beakPositon = new Rectangle(0, beakWidth, 0, beakWidth);
        beakPositon = _moveEdge(beakPositon, (callout.targetEdge * -1), -beakWidth / 2);
        beakPositon = centerEdgeToPoint(beakPositon, callout.targetEdge * -1, beakTargetPoint - _getRelativeRectEdgeValue(firstEdge, callout.calloutRectangle));
        if (!_isEdgeInBounds(beakPositon, calloutBounds, firstEdge)) {
            beakPositon = _alignEdges(beakPositon, calloutBounds, firstEdge);
        }
        else if (!_isEdgeInBounds(beakPositon, calloutBounds, secondEdge)) {
            beakPositon = _alignEdges(beakPositon, calloutBounds, secondEdge);
        }
        var targetEdge = callout.targetEdge * -1;
        var returnEdge = alignmentEdge ? alignmentEdge : _getFlankingEdges(targetEdge).firstEdge;
        var returnValue = {};
        returnValue[RectangleEdge[targetEdge]] = _getEdgeValue(beakPositon, targetEdge);
        returnValue[RectangleEdge[returnEdge]] = _getRelativeEdgeDifference(beakPositon, actualCallout, returnEdge);
        return returnValue;
    }
    positioningFunctions._positionBeak = _positionBeak;
    function _getRectangleFromHTMLElement(element) {
        var clientRect = element.getBoundingClientRect();
        return new Rectangle(clientRect.left, clientRect.right, clientRect.top, clientRect.bottom);
    }
    positioningFunctions._getRectangleFromHTMLElement = _getRectangleFromHTMLElement;
    function _getRectangleFromIRect(rect) {
        return new Rectangle(rect.left, rect.right, rect.top, rect.bottom);
    }
    positioningFunctions._getRectangleFromIRect = _getRectangleFromIRect;
    function _getTargetRect(bounds, target) {
        var targetRectangle;
        if (target) {
            if (target.preventDefault) {
                var ev = target;
                targetRectangle = new Rectangle(ev.clientX, ev.clientX, ev.clientY, ev.clientY);
            }
            else {
                targetRectangle = _getRectangleFromHTMLElement(target);
            }
            if (!_isRectangleWithinBounds(targetRectangle, bounds)) {
                var outOfBounds = _getOutOfBoundsEdges(targetRectangle, bounds);
                for (var _i = 0, outOfBounds_2 = outOfBounds; _i < outOfBounds_2.length; _i++) {
                    var direction = outOfBounds_2[_i];
                    targetRectangle[RectangleEdge[direction]] = bounds[RectangleEdge[direction]];
                }
            }
        }
        else {
            targetRectangle = new Rectangle(0, 0, 0, 0);
        }
        return targetRectangle;
    }
    positioningFunctions._getTargetRect = _getTargetRect;
    /**
     * If max height is less than zero it returns the bounds height instead.
     */
    function _getMaxHeightFromTargetRectangle(targetRectangle, targetEdge, gapSpace, bounds) {
        var maxHeight = 0;
        switch (targetEdge) {
            case 7 /* bottomAutoEdge */:
            case 5 /* bottomCenter */:
            case 4 /* bottomLeftEdge */:
            case 6 /* bottomRightEdge */:
                maxHeight = bounds.bottom - targetRectangle.bottom - gapSpace;
                break;
            case 3 /* topAutoEdge */:
            case 1 /* topCenter */:
            case 0 /* topLeftEdge */:
            case 2 /* topRightEdge */:
                maxHeight = targetRectangle.top - bounds.top - gapSpace;
                break;
            default:
                maxHeight = bounds.bottom - targetRectangle.top - gapSpace;
                break;
        }
        return maxHeight > 0 ? maxHeight : bounds.height;
    }
    positioningFunctions._getMaxHeightFromTargetRectangle = _getMaxHeightFromTargetRectangle;
    function _getRelativePositions(props, hostElement, calloutElement) {
        var beakWidth = !props.isBeakVisible ? 0 : (props.beakWidth || 0);
        var gap = _calculateActualBeakWidthInPixels(beakWidth) / 2 + (props.gapSpace ? props.gapSpace : 0);
        var boundingRect = props.bounds ?
            _getRectangleFromIRect(props.bounds) :
            new Rectangle(0, window.innerWidth - Utilities_1.getScrollbarWidth(), 0, window.innerHeight);
        var targetRect = _getTargetRect(boundingRect, props.target);
        var positionData = _getAlignmentData(_getPositionData(props.directionalHint, props.directionalHintForRTL), targetRect, boundingRect, props.coverTarget);
        var positionedCallout = _positionCalloutWithinBounds(_getRectangleFromHTMLElement(calloutElement), targetRect, boundingRect, positionData, gap, props.directionalHintFixed, props.coverTarget);
        var beakPositioned = _positionBeak(beakWidth, positionedCallout, targetRect, positionedCallout.alignmentEdge);
        var finalizedCallout = _finalizeCalloutPosition(positionedCallout.calloutRectangle, hostElement, positionedCallout.targetEdge, positionedCallout.alignmentEdge);
        return {
            calloutPosition: finalizedCallout,
            beakPosition: { position: tslib_1.__assign({}, beakPositioned), display: 'block' },
            directionalClassName: SLIDE_ANIMATIONS[positionedCallout.targetEdge],
            submenuDirection: (positionedCallout.targetEdge * -1) === RectangleEdge.right ? 10 /* leftBottomEdge */ : 13 /* rightBottomEdge */
        };
    }
    positioningFunctions._getRelativePositions = _getRelativePositions;
})(positioningFunctions = exports.positioningFunctions || (exports.positioningFunctions = {}));
function getRelativePositions(props, hostElement, calloutElement) {
    return positioningFunctions._getRelativePositions(props, hostElement, calloutElement);
}
exports.getRelativePositions = getRelativePositions;
/**
 * Get's the maximum height that a rectangle can have in order to fit below or above a target.
 * If the directional hint specifies a left or right edge (i.e. leftCenter) it will limit the height to the topBorder
 * of the target given.
 * If no bounds are provided then the window is treated as the bounds.
 */
function getMaxHeight(target, targetEdge, gapSpace, bounds) {
    if (gapSpace === void 0) { gapSpace = 0; }
    var mouseTarget = target;
    var elementTarget = target;
    var targetRect;
    var boundingRectangle = bounds ?
        positioningFunctions._getRectangleFromIRect(bounds) :
        new Rectangle(0, window.innerWidth - Utilities_1.getScrollbarWidth(), 0, window.innerHeight);
    if (mouseTarget.stopPropagation) {
        targetRect = new Rectangle(mouseTarget.clientX, mouseTarget.clientX, mouseTarget.clientY, mouseTarget.clientY);
    }
    else {
        targetRect = positioningFunctions._getRectangleFromHTMLElement(elementTarget);
    }
    return positioningFunctions._getMaxHeightFromTargetRectangle(targetRect, targetEdge, gapSpace, boundingRectangle);
}
exports.getMaxHeight = getMaxHeight;
var _a, _b;
//# sourceMappingURL=positioning.js.map