"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ButtonDecorator = exports.ButtonBase = exports.Button = exports["default"] = void 0;

var _jsxRuntime = require("react/jsx-runtime");

var _hoc = _interopRequireDefault(require("@enact/core/hoc"));

var _kind = _interopRequireDefault(require("@enact/core/kind"));

var _util = require("@enact/core/util");

var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));

var _Spottable = _interopRequireDefault(require("@enact/spotlight/Spottable"));

var _Button = require("@enact/ui/Button");

var _ComponentOverride = _interopRequireDefault(require("@enact/ui/ComponentOverride"));

var _Pure = _interopRequireDefault(require("@enact/ui/internal/Pure"));

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

var _compose = _interopRequireDefault(require("ramda/src/compose"));

var _react = require("react");

var _warning = _interopRequireDefault(require("warning"));

var _Icon = _interopRequireDefault(require("../Icon"));

var _Marquee = require("../Marquee");

var _Skinnable = _interopRequireDefault(require("../Skinnable"));

var _TooltipDecorator = _interopRequireDefault(require("../TooltipDecorator"));

var _ButtonModule = _interopRequireDefault(require("./Button.module.css"));

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

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; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

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; }

/**
 * A button component.
 *
 * This component is most often not used directly but may be composed within another component as it
 * is within [Button]{@link agate/Button.Button}.
 *
 * @class ButtonBase
 * @memberof agate/Button
 * @extends ui/Button.ButtonBase
 * @ui
 * @public
 */
var ButtonBase = (0, _kind["default"])({
  name: 'Button',
  propTypes:
  /** @lends agate/Button.ButtonBase.prototype */
  {
    /**
     * Animate when this component renders.
     *
     * @type {Boolean}
     * @public
     */
    animateOnRender: _propTypes2["default"].bool,

    /**
     * The delay before the button is animated, in milliseconds.
     *
     * @type {Number}
     * @default 0
     * @public
     */
    animationDelay: _propTypes2["default"].number,

    /**
     * The background opacity of this button.
     *
     * Valid values are:
     * * `'opaque'`,
     * * `'lightOpaque'`, and
     * * `'transparent'`.
     *
     * @type {('opaque'|'lightOpaque'|'transparent')}
     * @default 'opaque'
     * @public
     */
    backgroundOpacity: _propTypes2["default"].oneOf(['opaque', 'lightOpaque', 'transparent']),

    /**
     * A small message overlaid onto the button.
     *
     * @type {Number|String}
     * @public
     */
    badge: _propTypes2["default"].oneOfType([_propTypes2["default"].number, _propTypes2["default"].string]),

    /**
     * A custom color for the badge element.
     *
     * This prop is only visible if the `badge` prop is also set.
     *
     * @type {String}
     * @public
     */
    badgeColor: _propTypes2["default"].string,

    /**
     * Customizes the component by mapping the supplied collection of CSS class names to the
     * corresponding internal elements and states of this component.
     *
     * The following classes are supported:
     *
     * * `button` - The root class name
     * * `bg` - The background node of the button
     * * `selected` - Applied to a `selected` button
     * * `small` - Applied to a button specifying a `size` of `'small'`
     *
     * @type {Object}
     * @public
     */
    css: _propTypes2["default"].object,

    /**
     * Additional DOM nodes which may be necessary for decorating the Button.
     *
     * @type {Node}
     * @private
     */
    decoration: _propTypes2["default"].node,

    /**
     * Provides a way to call special interface attention to this button. It will be "featured"
     * in some way by the theme's visual rules.  This property only has an effect when
     * `backgroundOpacity` is "opaque".
     *
     * @type {Boolean}
     * @public
     */
    highlighted: _propTypes2["default"].bool,

    /**
     * The component used to render the icon.
     *
     * @type {Component|Node}
     * @default Icon
     * @private
     */
    iconComponent: _propTypes["default"].componentOverride,

    /**
     * True if button is an icon only button.
     *
     * @type {Boolean}
     * @default false
     * @private
     */
    iconOnly: _propTypes2["default"].bool,

    /**
     * Specifies on which side (`'before'` or `'after'`) of the text the icon appears.
     *
     * @type {('before'|'after')}
     * @default 'before'
     * @public
     */
    iconPosition: _propTypes2["default"].oneOf(['before', 'after']),

    /**
     * The position of this button in relation to other buttons.
     *
     * To create a collection of buttons that appear as one entity: buttons that butt up against
     * each other. Specify where the button is in the arrangement: 'left', 'center', or 'right'.
     * This prop is not recommended for use on a lonely button with no other buttons nearby.
     * Not specifying this optional prop leaves the button behaving normally.
     *
     * @type {('left'|'center'|'right')}
     * @public
     */
    joinedPosition: _propTypes2["default"].oneOf(['left', 'center', 'right']),

    /**
     * Boolean controlling whether this component should enforce the "minimum width" rules.
     *
     * @type {Boolean}
     * @public
     */
    minWidth: _propTypes2["default"].bool,

    /**
     * Provides a way to call special interface attention to this button. It will be "featured"
     * in some way by the theme's visual rules.
     *
     * @type {Boolean}
     * @public
     */
    selected: _propTypes2["default"].bool,

    /**
     * The size of the button.
     *
     * @type {('smallest'|'small'|'large'|'huge')}
     * @default 'large'
     * @public
     */
    size: _propTypes2["default"].oneOf(['smallest', 'small', 'large', 'huge']),

    /**
     * The amount of sprite "cells" in the src image of the `icon` being supplied. This prop has no effect without `icon`.
     *
     * @type {Number}
     * @public
     */
    spriteCount: _propTypes2["default"].number,

    /**
     * The button type.
     *
     * Grid buttons are intended to be grouped with other related buttons.
     *
     * @type {('grid'|'standard')}
     * @default 'standard'
     * @public
     */
    type: _propTypes2["default"].oneOf(['grid', 'standard'])
  },
  defaultProps: {
    animationDelay: 0,
    backgroundOpacity: 'opaque',
    iconComponent: _Icon["default"],
    iconOnly: false,
    iconPosition: 'before',
    size: 'large',
    type: 'standard'
  },
  styles: {
    css: _ButtonModule["default"],
    publicClassNames: true
  },
  computed: {
    className: function className(_ref) {
      var animateOnRender = _ref.animateOnRender,
          backgroundOpacity = _ref.backgroundOpacity,
          highlighted = _ref.highlighted,
          iconOnly = _ref.iconOnly,
          iconPosition = _ref.iconPosition,
          joinedPosition = _ref.joinedPosition,
          selected = _ref.selected,
          type = _ref.type,
          size = _ref.size,
          styler = _ref.styler;
      return styler.append({
        iconOnly: iconOnly
      }, backgroundOpacity, size, type, // iconBefore/iconAfter only applies when using text and an icon
      !iconOnly && "icon".concat((0, _util.cap)(iconPosition)), joinedPosition && 'joined' + (0, _util.cap)(joinedPosition), // If `joinedPosition` is present, prepend the word "joined" to the variable, so the classes are clearer.
      {
        animateOnRender: animateOnRender,
        highlighted: highlighted,
        selected: selected
      });
    },
    checkPropsIncompatibility: function checkPropsIncompatibility(_ref2) {
      var highlighted = _ref2.highlighted,
          iconOnly = _ref2.iconOnly,
          joinedPosition = _ref2.joinedPosition,
          selected = _ref2.selected,
          type = _ref2.type;
      process.env.NODE_ENV !== "production" ? (0, _warning["default"])(!(highlighted && selected), '"highlighted" prop cannot be used at the same time with "selected" prop.') : void 0;
      process.env.NODE_ENV !== "production" ? (0, _warning["default"])(!(iconOnly && joinedPosition && type), '"iconOnly" prop cannot be used at the same time with "joinedPosition" and "type" props.') : void 0;
      process.env.NODE_ENV !== "production" ? (0, _warning["default"])(!(joinedPosition && type === 'grid'), '"joinedPosition" and "type" (with "grid" value) props cannot be used at the same time.') : void 0;
    },
    decoration: function decoration(_ref3) {
      var badge = _ref3.badge,
          css = _ref3.css,
          _decoration = _ref3.decoration;
      if (!badge) return _decoration;
      return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_react.Fragment, {
        children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
          className: css.badge,
          children: badge
        }), _decoration]
      });
    },
    iconComponent: function iconComponent(_ref4) {
      var _iconComponent = _ref4.iconComponent,
          spriteCount = _ref4.spriteCount;
      // Don't burden basic HTML elements with the spriteCount prop (or other Icon-specific props)
      if (typeof _iconComponent === 'string') return _iconComponent;
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ComponentOverride["default"], {
        component: _iconComponent,
        spriteCount: spriteCount
      });
    },
    style: function style(_ref5) {
      var animationDelay = _ref5.animationDelay,
          badgeColor = _ref5.badgeColor,
          _style = _ref5.style;
      return _objectSpread(_objectSpread({}, _style), {}, {
        '--agate-button-animation-delay': animationDelay,
        '--agate-button-badge-bg-color': badgeColor
      });
    },
    minWidth: function minWidth(_ref6) {
      var iconOnly = _ref6.iconOnly,
          _minWidth = _ref6.minWidth;
      return _minWidth != null ? _minWidth : !iconOnly;
    }
  },
  render: function render(_ref7) {
    var css = _ref7.css,
        rest = _objectWithoutProperties(_ref7, ["css"]);

    delete rest.animateOnRender;
    delete rest.animationDelay;
    delete rest.backgroundOpacity;
    delete rest.badge;
    delete rest.badgeColor;
    delete rest.checkPropsIncompatibility;
    delete rest.highlighted;
    delete rest.iconOnly;
    delete rest.iconPosition;
    delete rest.joinedPosition;
    delete rest.selected;
    delete rest.spriteCount;
    delete rest.type;
    return _Button.ButtonBase.inline(_objectSpread(_objectSpread({}, rest), {}, {
      css: css
    }));
  }
});
/**
 * A higher-order component that determines if it is a button that only displays an icon.
 *
 * @class IconButtonDecorator
 * @memberof agate/Button
 * @hoc
 * @private
 */

exports.ButtonBase = ButtonBase;
var IconButtonDecorator = (0, _hoc["default"])(function (config, Wrapped) {
  return (0, _kind["default"])({
    name: 'IconButtonDecorator',
    computed: {
      iconOnly: function iconOnly(_ref8) {
        var children = _ref8.children;
        return _react.Children.toArray(children).filter(Boolean).length === 0;
      }
    },
    render: function render(props) {
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapped, _objectSpread({}, props));
    }
  });
});
/**
 * Applies Agate specific behaviors to [ButtonBase]{@link agate/Button.ButtonBase} components.
 *
 * @hoc
 * @memberof agate/Button
 * @mixes ui/Button.ButtonDecorator
 * @mixes spotlight/Spottable.Spottable
 * @mixes agate/Skinnable.Skinnable
 * @public
 */

var ButtonDecorator = (0, _compose["default"])(_Pure["default"], IconButtonDecorator, (0, _Marquee.MarqueeDecorator)({
  className: _ButtonModule["default"].marquee
}), (0, _TooltipDecorator["default"])({
  tooltipDestinationProp: 'decoration'
}), _Button.ButtonDecorator, _Spottable["default"], _Skinnable["default"]);
/**
 * A button component, ready to use in Agate applications.
 *
 * Usage:
 * ```
 * <Button
 *   backgroundOpacity="transparent"
 * >
 *   Press me!
 * </Button>
 * ```
 *
 * @class Button
 * @memberof agate/Button
 * @extends agate/Button.ButtonBase
 * @mixes agate/Button.ButtonDecorator
 * @ui
 * @public
 */

exports.ButtonDecorator = ButtonDecorator;
var Button = ButtonDecorator(ButtonBase);
exports.Button = Button;
var _default = Button;
exports["default"] = _default;