{"size": 11607, "ext": "js", "max_stars_repo_path": "modules/monochrome/dist/es6/shared/popover/popover.js", "max_stars_repo_name": "CapAI/streetscape.gl", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "modules/monochrome/dist/es6/shared/popover/popover.js", "max_issues_repo_name": "CapAI/streetscape.gl", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "modules/monochrome/dist/es6/shared/popover/popover.js", "max_forks_repo_name": "CapAI/streetscape.gl", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 28.2408759124, "max_line_length": 128, "alphanum_fraction": 0.6648574136}
// Copyright (c) 2019 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import _extends from "@babel/runtime/helpers/esm/extends";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _objectSpread2 from "@babel/runtime/helpers/esm/objectSpread";
import React from 'react';
import PropTypes from 'prop-types';
import Popper from 'popper.js';
import styled from '@emotion/styled';
import { withTheme, evaluateStyle } from '../theme';
import { capitalize, getOppositePosition, generateTriangleStyles, nodeHasParent, positionsToPopperPlacement } from './utils';
const isBrowser = typeof document !== 'undefined' && Boolean(document.createElement);
export const POSITIONS = {
  TOP: 'top',
  RIGHT: 'right',
  BOTTOM: 'bottom',
  LEFT: 'left',
  AUTO: 'auto'
};
export const TRIGGERS = {
  CLICK: 'click',
  HOVER: 'hover'
};
const DEFAULT_ARROW_SIZE = 6;
const DEFAULT_BORDER_WIDTH = 1;
const PopoverComponent = styled.div(props => _objectSpread2({
  display: 'inline-flex'
}, evaluateStyle(props.userStyle, props)));
const PopoverTarget = styled.div(props => _objectSpread2({}, evaluateStyle(props.userStyle, props)));
const PopoverContent = styled.div(props => _objectSpread2({}, evaluateStyle(props.userStyle, props)));
const PopoverBody = styled.div(props => {
  let style = null;

  if (props.position && props.position !== POSITIONS.AUTO && props.arrowSize) {
    style = {
      ["margin".concat(capitalize(getOppositePosition(props.position)))]: props.arrowSize
    };
  }

  return _objectSpread2({}, props.theme.__reset__, {}, style, {
    position: 'absolute',
    top: 0,
    left: 0,
    zIndex: 99,
    background: props.background || props.theme.background,
    borderStyle: 'solid',
    borderWidth: props.borderWidth,
    borderColor: props.borderColor || props.theme.controlColorPrimary,
    boxShadow: props.theme.shadow,
    fontFamily: props.theme.fontFamily,
    fontSize: props.theme.fontSize,
    fontWeight: 'normal'
  }, props.popperStyles, {}, evaluateStyle(props.userStyle, props));
});
const OuterArrow = styled.div(props => {
  const {
    position,
    arrowSize,
    popperOffsets
  } = props;

  if (!arrowSize) {
    return null;
  }

  const arrowOffsets = popperOffsets.arrow || {};
  const style = {
    borderColor: props.borderColor || props.theme.controlColorPrimary,
    [getOppositePosition(position)]: -arrowSize
  };

  if (arrowOffsets.top) {
    style.top = arrowOffsets.top;
  }

  if (arrowOffsets.left) {
    style.left = arrowOffsets.left;
  }

  return Object.assign(style, evaluateStyle(props.userStyle, props), generateTriangleStyles(position, arrowSize));
});
const InnerArrow = styled.div(props => {
  const {
    position,
    arrowSize
  } = props;

  if (!arrowSize) {
    return null;
  }

  const isVertical = position === POSITIONS.TOP || position === POSITIONS.BOTTOM;
  const style = {
    borderColor: props.background || props.theme.background
  };

  if (isVertical) {
    style.left = -arrowSize;
    style.top = position === POSITIONS.TOP ? -arrowSize : 0;
    style.marginTop = (position === POSITIONS.TOP ? -1 : 1) * props.borderWidth;
  } else {
    style.top = -arrowSize;
    style.left = position === POSITIONS.LEFT ? -arrowSize : 0;
    style.marginLeft = (position === POSITIONS.LEFT ? -1 : 1) * props.borderWidth;
  }

  return Object.assign(style, evaluateStyle(props.userStyle, props), generateTriangleStyles(position, arrowSize));
});
const POSITIONS_PROP_TYPE = PropTypes.oneOf([POSITIONS.TOP, POSITIONS.RIGHT, POSITIONS.BOTTOM, POSITIONS.LEFT, POSITIONS.AUTO]);

class Popover extends React.Component {
  constructor(props) {
    super(props);

    _defineProperty(this, "_handleTargetClick", () => {
      this._togglePopover();
    });

    _defineProperty(this, "_handleTargetMouseEnter", () => {
      clearTimeout(this.hideTimer);

      this._showPopover();
    });

    _defineProperty(this, "_handleTargetMouseLeave", () => {
      this._hidePopoverWithDelay();
    });

    _defineProperty(this, "_handlePopoverMouseEnter", () => {
      clearTimeout(this.hideTimer);
    });

    _defineProperty(this, "_handlePopoverMouseLeave", () => {
      this._hidePopoverWithDelay();
    });

    _defineProperty(this, "_handleKeyPress", evt => {
      if (evt.key === 'Escape') {
        this._hidePopover();
      }
    });

    _defineProperty(this, "_handlePopperUpdate", data => {
      this.setState({
        popperOffsets: data.offsets,
        popperPlacement: data.placement,
        popperStyles: data.styles
      });
      return data;
    });

    _defineProperty(this, "_hidePopover", () => {
      this.setState(this._getDefaultState(this.props));

      this._destroyPopover();
    });

    _defineProperty(this, "_handleDocumentClick", evt => {
      if (!this.$popper || nodeHasParent(evt.target, this.$popper) || nodeHasParent(evt.target, this.$target)) {
        return;
      }

      this._hidePopover();
    });

    this.state = this._getDefaultState(props);
  }

  componentDidUpdate(prevProps, prevState) {
    if (this.state.isVisible && !prevState.isVisible) {
      const PopperClass = this.props.popperClass;
      this.popper = new PopperClass(this.$target, this.$popper, {
        placement: this.state.popperPlacement,
        modifiers: {
          arrow: {
            element: this.$arrow,
            enabled: true
          },
          applyStyle: {
            enabled: false
          },
          applyReactStyle: {
            enabled: true,
            fn: this._handlePopperUpdate,
            order: 900
          }
        }
      });

      if (this.props.trigger === TRIGGERS.CLICK) {
        this._addClickEvents();
      }
    }
  }

  componentWillUnmount() {
    this._destroyPopover();

    this._removeClickEvents();
  }

  _getDefaultState(props) {
    return {
      isVisible: false,
      popperOffsets: {},
      popperPlacement: positionsToPopperPlacement(props.position, props.arrowPosition),
      popperStyles: {}
    };
  }

  _showPopover() {
    this.setState({
      isVisible: true
    });
  }

  _hidePopoverWithDelay() {
    const {
      onMouseOutDelay
    } = this.props;

    if (onMouseOutDelay) {
      this.hideTimer = setTimeout(this._hidePopover, onMouseOutDelay);
      return;
    }

    this._hidePopover();
  }

  _addClickEvents() {
    if (!isBrowser) {
      return;
    }

    document.addEventListener('mousedown', this._handleDocumentClick);
    document.addEventListener('keyup', this._handleKeyPress);
  }

  _removeClickEvents() {
    if (!isBrowser) {
      return;
    }

    document.removeEventListener('mousedown', this._handleDocumentClick);
    document.removeEventListener('keyup', this._handleKeyPress);
  }

  _togglePopover() {
    const isVisible = !this.state.isVisible;
    this.setState({
      isVisible
    });

    if (!isVisible) {
      this._destroyPopover();
    }
  }

  _destroyPopover() {
    if (this.popper) {
      this.popper.destroy();
      delete this.popper;
    }

    if (this.props.trigger === TRIGGERS.CLICK) {
      this._removeClickEvents();
    }
  }

  _renderTarget(styleProps) {
    const {
      trigger,
      style
    } = this.props;
    const interactionProps = {};

    if (trigger === TRIGGERS.HOVER) {
      interactionProps.onMouseEnter = this._handleTargetMouseEnter;
      interactionProps.onMouseLeave = this._handleTargetMouseLeave;
    } else if (trigger === TRIGGERS.CLICK) {
      interactionProps.onClick = this._handleTargetClick;
    }

    return React.createElement(PopoverTarget, _extends({}, interactionProps, {
      userStyle: style.target
    }, styleProps, {
      ref: el => {
        this.$target = el;
      }
    }), this.props.children);
  }

  _renderArrow(styleProps) {
    const {
      style
    } = this.props;
    return React.createElement(OuterArrow, _extends({
      userStyle: style.arrowBorder
    }, styleProps, {
      ref: el => {
        this.$arrow = el;
      }
    }), React.createElement(InnerArrow, _extends({
      userStyle: style.arrow
    }, styleProps)));
  }

  _renderBody(styleProps) {
    const {
      className,
      style,
      trigger
    } = this.props;
    const interactionProps = {};

    if (trigger === TRIGGERS.HOVER) {
      interactionProps.onMouseEnter = this._handlePopoverMouseEnter;
      interactionProps.onMouseLeave = this._handlePopoverMouseLeave;
    }

    return React.createElement(PopoverBody, _extends({
      className: className
    }, interactionProps, {
      userStyle: style.body
    }, styleProps, {
      ref: el => {
        this.$popper = el;
      }
    }), this._renderContent(styleProps), this._renderArrow(styleProps));
  }

  _renderContent(styleProps) {
    const content = typeof this.props.content === 'function' ? this.props.content() : this.props.content;
    return React.createElement(PopoverContent, _extends({
      userStyle: this.props.style.content
    }, styleProps), content);
  }

  render() {
    const {
      theme,
      style
    } = this.props;
    const {
      isVisible,
      popperPlacement,
      popperStyles,
      popperOffsets
    } = this.state;
    const [position] = popperPlacement.split('-');
    const arrowPosition = position === POSITIONS.AUTO ? POSITIONS.TOP : position;
    const styleProps = {
      theme,
      arrowSize: 'arrowSize' in style ? style.arrowSize : DEFAULT_ARROW_SIZE,
      background: style.background,
      borderWidth: 'borderWidth' in style ? style.borderWidth : DEFAULT_BORDER_WIDTH,
      borderColor: style.borderColor,
      position,
      arrowPosition,
      popperStyles,
      popperOffsets,
      isActive: isVisible
    };
    return React.createElement(PopoverComponent, _extends({
      userStyle: style.popover
    }, styleProps), this._renderTarget(styleProps), isVisible && this._renderBody(styleProps));
  }

}

_defineProperty(Popover, "propTypes", {
  className: PropTypes.string,
  style: PropTypes.object,
  content: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired,
  position: POSITIONS_PROP_TYPE,
  arrowPosition: POSITIONS_PROP_TYPE,
  onMouseOutDelay: PropTypes.number,
  trigger: PropTypes.oneOf([TRIGGERS.HOVER, TRIGGERS.CLICK]),
  popperClass: PropTypes.func
});

_defineProperty(Popover, "defaultProps", {
  className: '',
  style: {},
  trigger: TRIGGERS.CLICK,
  onMouseOutDelay: 0,
  popperClass: Popper
});

const ThemedPopover = withTheme(Popover);
Object.assign(ThemedPopover, POSITIONS);
Object.assign(ThemedPopover, TRIGGERS);
export default ThemedPopover;
//# sourceMappingURL=popover.js.map