"use strict";

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.NotificationActionButton = NotificationActionButton;
exports.NotificationButton = NotificationButton;
exports.NotificationTextDetails = NotificationTextDetails;
exports.ToastNotification = ToastNotification;
exports.InlineNotification = InlineNotification;

var _propTypes = _interopRequireDefault(require("prop-types"));

var _react = _interopRequireWildcard(require("react"));

var _classnames = _interopRequireDefault(require("classnames"));

var _carbonComponents = require("carbon-components");

var _iconsReact = require("@carbon/icons-react");

var _Button = _interopRequireDefault(require("../Button"));

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

var prefix = _carbonComponents.settings.prefix;

function NotificationActionButton(_ref) {
  var children = _ref.children,
      customClassName = _ref.className,
      onClick = _ref.onClick,
      rest = _objectWithoutProperties(_ref, ["children", "className", "onClick"]);

  var className = (0, _classnames.default)(customClassName, "".concat(prefix, "--inline-notification__action-button"));
  return _react.default.createElement(_Button.default, _extends({
    className: className,
    kind: "ghost",
    onClick: onClick,
    size: "small"
  }, rest), children);
}

NotificationActionButton.propTypes = {
  /**
   * Specify an optional className to be applied to the notification action button
   */
  className: _propTypes.default.string,

  /**
   * Specify the content of the notification action button.
   */
  children: _propTypes.default.node,

  /**
   * Optionally specify a click handler for the notification action button.
   */
  onClick: _propTypes.default.func
};

function NotificationButton(_ref2) {
  var _cx, _cx2;

  var ariaLabel = _ref2.ariaLabel,
      className = _ref2.className,
      iconDescription = _ref2.iconDescription,
      type = _ref2.type,
      IconTag = _ref2.renderIcon,
      name = _ref2.name,
      notificationType = _ref2.notificationType,
      rest = _objectWithoutProperties(_ref2, ["ariaLabel", "className", "iconDescription", "type", "renderIcon", "name", "notificationType"]);

  var buttonClassName = (0, _classnames.default)(className, (_cx = {}, _defineProperty(_cx, "".concat(prefix, "--toast-notification__close-button"), notificationType === 'toast'), _defineProperty(_cx, "".concat(prefix, "--inline-notification__close-button"), notificationType === 'inline'), _cx));
  var iconClassName = (0, _classnames.default)((_cx2 = {}, _defineProperty(_cx2, "".concat(prefix, "--toast-notification__close-icon"), notificationType === 'toast'), _defineProperty(_cx2, "".concat(prefix, "--inline-notification__close-icon"), notificationType === 'inline'), _cx2));
  return _react.default.createElement("button", _extends({}, rest, {
    type: type,
    "aria-label": iconDescription,
    title: iconDescription,
    className: buttonClassName
  }), IconTag && _react.default.createElement(IconTag, {
    "aria-label": ariaLabel,
    className: iconClassName,
    name: name
  }));
}

NotificationButton.propTypes = {
  /**
   * Specify an optional className to be applied to the notification button
   */
  className: _propTypes.default.string,

  /**
   * Specify a label to be read by screen readers on the notification button
   */
  ariaLabel: _propTypes.default.string,

  /**
   * Optional prop to specify the type of the Button
   */
  type: _propTypes.default.string,

  /**
   * Provide a description for "close" icon that can be read by screen readers
   */
  iconDescription: _propTypes.default.string,

  /**
   * Optional prop to allow overriding the icon rendering.
   * Can be a React component class
   */
  renderIcon: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),

  /**
   * Specify an optional icon for the Button through a string,
   * if something but regular "close" icon is desirable
   */
  name: _propTypes.default.string,

  /**
   * Specify the notification type
   */
  notificationType: _propTypes.default.oneOf(['toast', 'inline'])
};
NotificationButton.defaultProps = {
  ariaLabel: 'close notification',
  // TODO: deprecate this prop
  notificationType: 'toast',
  type: 'button',
  iconDescription: 'close icon',
  renderIcon: _iconsReact.Close20
};

function NotificationTextDetails(_ref3) {
  var title = _ref3.title,
      subtitle = _ref3.subtitle,
      caption = _ref3.caption,
      notificationType = _ref3.notificationType,
      children = _ref3.children,
      rest = _objectWithoutProperties(_ref3, ["title", "subtitle", "caption", "notificationType", "children"]);

  if (notificationType === 'toast') {
    return _react.default.createElement("div", _extends({}, rest, {
      className: "".concat(prefix, "--toast-notification__details")
    }), _react.default.createElement("h3", {
      className: "".concat(prefix, "--toast-notification__title")
    }, title), _react.default.createElement("div", {
      className: "".concat(prefix, "--toast-notification__subtitle")
    }, subtitle), _react.default.createElement("div", {
      className: "".concat(prefix, "--toast-notification__caption")
    }, caption), children);
  }

  if (notificationType === 'inline') {
    return _react.default.createElement("div", _extends({}, rest, {
      className: "".concat(prefix, "--inline-notification__text-wrapper")
    }), _react.default.createElement("p", {
      className: "".concat(prefix, "--inline-notification__title")
    }, title), _react.default.createElement("div", {
      className: "".concat(prefix, "--inline-notification__subtitle")
    }, subtitle), children);
  }
}

NotificationTextDetails.propTypes = {
  /**
   * Pass in the children that will be rendered in NotificationTextDetails
   */
  children: _propTypes.default.node,

  /**
   * Specify the title
   */
  title: _propTypes.default.string,

  /**
   * Specify the sub-title
   */
  subtitle: _propTypes.default.node,

  /**
   * Specify the caption
   */
  caption: _propTypes.default.node,

  /**
   * Specify the notification type
   */
  notificationType: _propTypes.default.oneOf(['toast', 'inline'])
};
NotificationTextDetails.defaultProps = {
  title: 'title',
  caption: 'caption',
  notificationType: 'toast'
};
var iconTypes = {
  error: _iconsReact.ErrorFilled20,
  success: _iconsReact.CheckmarkFilled20,
  warning: _iconsReact.WarningFilled20
};

function NotificationIcon(_ref4) {
  var iconDescription = _ref4.iconDescription,
      kind = _ref4.kind,
      notificationType = _ref4.notificationType;
  var IconForKind = iconTypes[kind];

  if (!IconForKind) {
    return null;
  }

  return _react.default.createElement(IconForKind, {
    className: "".concat(prefix, "--").concat(notificationType, "-notification__icon")
  }, _react.default.createElement("title", null, iconDescription));
}

NotificationIcon.propTypes = {
  notificationType: _propTypes.default.oneOf(['inline', 'toast']).isRequired,
  kind: _propTypes.default.oneOf(['error', 'success', 'warning', 'info']).isRequired,
  iconDescription: _propTypes.default.string.isRequired
};

function ToastNotification(_ref5) {
  var _cx3;

  var role = _ref5.role,
      notificationType = _ref5.notificationType,
      onCloseButtonClick = _ref5.onCloseButtonClick,
      iconDescription = _ref5.iconDescription,
      className = _ref5.className,
      caption = _ref5.caption,
      subtitle = _ref5.subtitle,
      title = _ref5.title,
      kind = _ref5.kind,
      lowContrast = _ref5.lowContrast,
      hideCloseButton = _ref5.hideCloseButton,
      children = _ref5.children,
      timeout = _ref5.timeout,
      rest = _objectWithoutProperties(_ref5, ["role", "notificationType", "onCloseButtonClick", "iconDescription", "className", "caption", "subtitle", "title", "kind", "lowContrast", "hideCloseButton", "children", "timeout"]);

  var _useState = (0, _react.useState)(true),
      _useState2 = _slicedToArray(_useState, 2),
      isOpen = _useState2[0],
      setIsOpen = _useState2[1];

  var containerClassName = (0, _classnames.default)(className, (_cx3 = {}, _defineProperty(_cx3, "".concat(prefix, "--toast-notification"), true), _defineProperty(_cx3, "".concat(prefix, "--toast-notification--low-contrast"), lowContrast), _defineProperty(_cx3, "".concat(prefix, "--toast-notification--").concat(kind), kind), _cx3));

  function handleCloseButtonClick(event) {
    setIsOpen(false);
    onCloseButtonClick(event);
  }

  (0, _react.useEffect)(function () {
    if (!timeout) {
      return;
    }

    var timeoutId = window.setTimeout(function () {
      setIsOpen(false);
      onCloseButtonClick(event);
    }, timeout);
    return function () {
      window.clearTimeout(timeoutId);
    };
  }, [onCloseButtonClick, timeout]);

  if (!isOpen) {
    return null;
  }

  return _react.default.createElement("div", _extends({}, rest, {
    role: role,
    kind: kind,
    className: containerClassName
  }), _react.default.createElement(NotificationIcon, {
    notificationType: notificationType,
    kind: kind,
    iconDescription: iconDescription
  }), _react.default.createElement(NotificationTextDetails, {
    title: title,
    subtitle: subtitle,
    caption: caption,
    notificationType: notificationType
  }, children), !hideCloseButton && _react.default.createElement(NotificationButton, {
    iconDescription: iconDescription,
    notificationType: notificationType,
    onClick: handleCloseButtonClick
  }));
}

ToastNotification.propTypes = {
  /**
   * Pass in the children that will be rendered within the ToastNotification
   */
  children: _propTypes.default.node,

  /**
   * Specify an optional className to be applied to the notification box
   */
  className: _propTypes.default.string,

  /**
   * Specify what state the notification represents
   */
  kind: _propTypes.default.oneOf(['error', 'info', 'success', 'warning']).isRequired,

  /**
   * Specify whether you are using the low contrast variant of the ToastNotification.
   */
  lowContrast: _propTypes.default.bool,

  /**
   * Specify the title
   */
  title: _propTypes.default.string.isRequired,

  /**
   * Specify the sub-title
   */
  subtitle: _propTypes.default.node,

  /**
   * By default, this value is "alert". You can also provide an alternate
   * role if it makes sense from the accessibility-side
   */
  role: _propTypes.default.string.isRequired,

  /**
   * Specify the caption
   */
  caption: _propTypes.default.node,

  /**
   * Provide a function that is called when menu is closed
   */
  onCloseButtonClick: _propTypes.default.func,

  /**
   * Provide a description for "close" icon that can be read by screen readers
   */
  iconDescription: _propTypes.default.string.isRequired,

  /**
   * By default, this value is "toast". You can also provide an alternate type
   * if it makes sense for the underlying `<NotificationTextDetails>` and `<NotificationButton>`
   */
  notificationType: _propTypes.default.string,

  /**
   * Specify the close button should be disabled, or not
   */
  hideCloseButton: _propTypes.default.bool,

  /**
   * Specify an optional duration the notification should be closed in
   */
  timeout: _propTypes.default.number
};
ToastNotification.defaultProps = {
  kind: 'error',
  title: 'provide a title',
  caption: 'provide a caption',
  role: 'alert',
  notificationType: 'toast',
  iconDescription: 'closes notification',
  onCloseButtonClick: function onCloseButtonClick() {},
  hideCloseButton: false,
  timeout: 0
};

function InlineNotification(_ref6) {
  var _cx4;

  var actions = _ref6.actions,
      role = _ref6.role,
      notificationType = _ref6.notificationType,
      onCloseButtonClick = _ref6.onCloseButtonClick,
      iconDescription = _ref6.iconDescription,
      className = _ref6.className,
      subtitle = _ref6.subtitle,
      title = _ref6.title,
      kind = _ref6.kind,
      lowContrast = _ref6.lowContrast,
      hideCloseButton = _ref6.hideCloseButton,
      children = _ref6.children,
      rest = _objectWithoutProperties(_ref6, ["actions", "role", "notificationType", "onCloseButtonClick", "iconDescription", "className", "subtitle", "title", "kind", "lowContrast", "hideCloseButton", "children"]);

  var _useState3 = (0, _react.useState)(true),
      _useState4 = _slicedToArray(_useState3, 2),
      isOpen = _useState4[0],
      setIsOpen = _useState4[1];

  var containerClassName = (0, _classnames.default)(className, (_cx4 = {}, _defineProperty(_cx4, "".concat(prefix, "--inline-notification"), true), _defineProperty(_cx4, "".concat(prefix, "--inline-notification--low-contrast"), lowContrast), _defineProperty(_cx4, "".concat(prefix, "--inline-notification--").concat(kind), kind), _defineProperty(_cx4, "".concat(prefix, "--inline-notification--hide-close-button"), hideCloseButton), _cx4));

  function handleCloseButtonClick(event) {
    setIsOpen(false);
    onCloseButtonClick(event);
  }

  if (!isOpen) {
    return null;
  }

  return _react.default.createElement("div", _extends({}, rest, {
    role: role,
    kind: kind,
    className: containerClassName
  }), _react.default.createElement("div", {
    className: "".concat(prefix, "--inline-notification__details")
  }, _react.default.createElement(NotificationIcon, {
    notificationType: notificationType,
    kind: kind,
    iconDescription: iconDescription
  }), _react.default.createElement(NotificationTextDetails, {
    title: title,
    subtitle: subtitle,
    notificationType: notificationType
  }, children)), actions, !hideCloseButton && _react.default.createElement(NotificationButton, {
    iconDescription: iconDescription,
    notificationType: notificationType,
    onClick: handleCloseButtonClick
  }));
}

InlineNotification.propTypes = {
  /**
   * Pass in the action nodes that will be rendered within the InlineNotification
   */
  actions: _propTypes.default.node,

  /**
   * Pass in the children that will be rendered within the InlineNotification
   */
  children: _propTypes.default.node,

  /**
   * Specify an optional className to be applied to the notification box
   */
  className: _propTypes.default.string,

  /**
   * Specify what state the notification represents
   */
  kind: _propTypes.default.oneOf(['error', 'info', 'success', 'warning']).isRequired,

  /**
   * Specify whether you are using the low contrast variant of the InlineNotification.
   */
  lowContrast: _propTypes.default.bool,

  /**
   * Specify the title
   */
  title: _propTypes.default.string.isRequired,

  /**
   * Specify the sub-title
   */
  subtitle: _propTypes.default.node,

  /**
   * By default, this value is "alert". You can also provide an alternate
   * role if it makes sense from the accessibility-side
   */
  role: _propTypes.default.string.isRequired,

  /**
   * Provide a function that is called when menu is closed
   */
  onCloseButtonClick: _propTypes.default.func,

  /**
   * Provide a description for "close" icon that can be read by screen readers
   */
  iconDescription: _propTypes.default.string.isRequired,

  /**
   * By default, this value is "inline". You can also provide an alternate type
   * if it makes sense for the underlying `<NotificationTextDetails>` and `<NotificationButton>`
   */
  notificationType: _propTypes.default.string,

  /**
   * Specify the close button should be disabled, or not
   */
  hideCloseButton: _propTypes.default.bool
};
InlineNotification.defaultProps = {
  role: 'alert',
  notificationType: 'inline',
  iconDescription: 'closes notification',
  onCloseButtonClick: function onCloseButtonClick() {},
  hideCloseButton: false
};