"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.DropdownDecorator = exports.DropdownBase = exports.Dropdown = void 0;
var _handle = require("@enact/core/handle");
var _propTypes = _interopRequireDefault(require("@enact/core/internal/prop-types"));
var _kind = _interopRequireDefault(require("@enact/core/kind"));
var _util = require("@enact/core/util");
var _I18nDecorator = require("@enact/i18n/I18nDecorator");
var _SpotlightContainerDecorator = _interopRequireDefault(require("@enact/spotlight/SpotlightContainerDecorator"));
var _Changeable = _interopRequireDefault(require("@enact/ui/Changeable"));
var _ForwardRef = _interopRequireDefault(require("@enact/ui/ForwardRef"));
var _IdProvider = _interopRequireDefault(require("@enact/ui/internal/IdProvider"));
var _Toggleable = _interopRequireDefault(require("@enact/ui/Toggleable"));
var _classnames2 = _interopRequireDefault(require("classnames"));
var _propTypes2 = _interopRequireDefault(require("prop-types"));
var _compose = _interopRequireDefault(require("ramda/src/compose"));
var _not = _interopRequireDefault(require("ramda/src/not"));
var _warning = _interopRequireDefault(require("warning"));
var _Button = _interopRequireDefault(require("../Button"));
var _ContextualPopupDecorator = _interopRequireDefault(require("../ContextualPopupDecorator"));
var _Icon = _interopRequireDefault(require("../Icon"));
var _Item = _interopRequireDefault(require("../Item"));
var _Skinnable = _interopRequireDefault(require("../Skinnable"));
var _DropdownList = _interopRequireWildcard(require("./DropdownList"));
var _DropdownModule = _interopRequireDefault(require("./Dropdown.module.css"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["children", "forwardRef", "icon", "skin"],
  _excluded2 = ["adjustedDirection", "aria-label", "ariaLabelledBy", "children", "css", "direction", "disabled", "hasChildren", "onAdjustDirection", "onClose", "onOpen", "onSelect", "open", "selected", "skin", "title", "width"];
/**
 * Agate styled Dropdown.
 *
 * @example
 * <Dropdown
 * 	defaultSelected={2}
 * 	title="Dropdown"
 * >
 * 	{['Option 1', 'Option 2', 'Option 3', 'Option 4']}
 * </Dropdown>
 *
 * @module agate/Dropdown
 * @exports Dropdown
 * @exports DropdownBase
 * @exports DropdownDecorator
 */
/**
 * A stateless Dropdown Button component.
 *
 * @class DropdownButtonBase
 * @memberof agate/Dropdown
 * @ui
 * @public
 */
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
var DropdownButtonBase = (0, _kind["default"])({
  name: 'DropdownButtonBase',
  propTypes: /** @lends agate/Dropdown.DropdownButtonBase.prototype */{
    /**
     * Forwards a reference to this component.
     *
     * @type {Object|Function}
     * @private
     */
    forwardRef: _propTypes["default"].ref,
    /**
     * The icon displayed on the dropdown button.
     *
     * @type {String}
     * @public
     */
    icon: _propTypes2["default"].string,
    /**
     * The current skin for this component.
     *
     * @type {String}
     * @public
     */
    skin: _propTypes2["default"].string
  },
  render: function render(_ref) {
    var children = _ref.children,
      forwardRef = _ref.forwardRef,
      icon = _ref.icon,
      skin = _ref.skin,
      rest = _objectWithoutProperties(_ref, _excluded);
    return skin === 'silicon' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button["default"], _objectSpread(_objectSpread({}, rest), {}, {
      icon: icon,
      iconPosition: "after",
      minWidth: true,
      ref: forwardRef,
      children: children
    })) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Item["default"], _objectSpread(_objectSpread({}, rest), {}, {
      ref: forwardRef,
      children: [children, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon["default"], {
        slot: "slotAfter",
        size: "small",
        children: icon
      }, "icon")]
    }));
  }
});
var DropdownButton = (0, _ContextualPopupDecorator["default"])({
  noArrow: true
}, (0, _ForwardRef["default"])(DropdownButtonBase));
DropdownButton.displayName = 'DropdownButton';

/**
 * A stateless Dropdown component.
 *
 * @class DropdownBase
 * @memberof agate/Dropdown
 * @extends agate/Button.Button
 * @extends agate/ContextualPopupDecorator.ContextualPopupDecorator
 * @omit popupComponent
 * @ui
 * @public
 */
var DropdownBase = exports.DropdownBase = (0, _kind["default"])({
  name: 'Dropdown',
  propTypes: /** @lends agate/Dropdown.DropdownBase.prototype */{
    /**
     * The direction of the Dropdown, which is adjusted when the original direction
     * cannot be used.
     *
     * @type {('above'|'below')}
     * @default 'below'
     * @private
     */
    adjustedDirection: _propTypes2["default"].oneOf(['above', 'below']),
    /**
     * The "aria-label" for the Dropdown.
     *
     * @type {String}
     * @public
     */
    'aria-label': _propTypes2["default"].string,
    /**
     * Items to be displayed in the `Dropdown` when `open`.
     *
     * Takes either an array of strings or an array of objects. When strings, the values will be
     * used in the generated components as the readable text. When objects, the properties will
     * be passed onto an `Item` component; `children` as well as a unique `key` properties are
     * required.
     *
     * @type {String[]|Array.<{key: (Number|String), children: (String|Component)}>}
     * @public
     */
    children: _propTypes2["default"].oneOfType([_propTypes2["default"].arrayOf(_propTypes2["default"].string), _propTypes2["default"].arrayOf(_propTypes2["default"].shape({
      children: _propTypes["default"].renderable.isRequired,
      key: _propTypes2["default"].oneOfType([_propTypes2["default"].string, _propTypes2["default"].number]).isRequired
    }))]),
    /**
     * Customizes the component by mapping the supplied collection of CSS class names to the
     * corresponding internal elements and states of this component.
     *
     * @type {Object}
     * @private
     */
    css: _propTypes2["default"].object,
    /**
     * Placement of the Dropdown.
     *
     * @type {('above'|'below')}
     * @default 'below'
     * @public
     */
    direction: _propTypes2["default"].oneOf(['above', 'below']),
    /**
     * Disables Dropdown and becomes non-interactive.
     *
     * @type {Boolean}
     * @public
     */
    disabled: _propTypes2["default"].bool,
    /**
     * The `id` of Dropdown referred to when generating id for `'title'`.
     *
     * @type {String}
     * @private
     */
    id: _propTypes2["default"].string,
    /**
     * Called when the direction is adjusted.
     *
     * @type {Function}
     * @private
     */
    onAdjustDirection: _propTypes2["default"].func,
    /**
     * Called when the Dropdown is closing.
     *
     * @type {Function}
     * @public
     */
    onClose: _propTypes2["default"].func,
    /**
     * Called when the Dropdown is opening.
     *
     * @type {Function}
     * @public
     */
    onOpen: _propTypes2["default"].func,
    /**
     * Called when an item is selected.
     *
     * The event payload will be an object with the following members:
     * * `data` - The value for the option as received in the `children` prop
     * * `selected` - Number representing the selected option, 0 indexed
     *
     * @type {Function}
     * @public
     */
    onSelect: _propTypes2["default"].func,
    /**
     * Displays the items.
     *
     * @type {Boolean}
     * @public
     */
    open: _propTypes2["default"].bool,
    /**
     * Indicates the locale's text direction is right-to-left.
     *
     * @type {Boolean}
     * @private
     */
    rtl: _propTypes2["default"].bool,
    /**
     * Index of the selected item.
     *
     * @type {Number}
     * @public
     */
    selected: _propTypes2["default"].number,
    /**
     * The current skin for this component.
     *
     * @type {String}
     * @public
     */
    skin: _propTypes2["default"].string,
    /**
     * Text displayed in the Dropdown when nothing is selected.
     *
     * The title will be replaced with the selected item, if set.
     *
     * @type {String}
     * @public
     */
    title: _propTypes2["default"].string,
    /**
     * Width of the Dropdown.
     *
     * @type {('smallest'|'small'|'medium'|'large'|'x-large'|'huge')}
     * @default 'medium'
     * @public
     */
    width: _propTypes2["default"].oneOf(['smallest', 'small', 'medium', 'large', 'x-large', 'huge'])
  },
  defaultProps: {
    adjustedDirection: 'below',
    direction: 'below',
    width: 'medium'
  },
  handlers: {
    onSelect: (0, _handle.handle)((0, _handle.forward)('onSelect'), (0, _handle.forward)('onClose')),
    onOpen: (0, _handle.handle)((0, _handle.forward)('onClick'), (0, _not["default"])((0, _handle.forProp)('disabled', true)), (0, _not["default"])((0, _handle.forProp)('open', true)), (0, _handle.forward)('onOpen'))
  },
  styles: {
    css: _DropdownModule["default"],
    className: 'dropdown',
    publicClassNames: true
  },
  computed: {
    ariaLabelledBy: function ariaLabelledBy(_ref2) {
      var id = _ref2.id,
        title = _ref2.title;
      return title ? "".concat(id, "_title") : void 0;
    },
    children: function children(_ref3) {
      var _children = _ref3.children,
        selected = _ref3.selected;
      if (!Array.isArray(_children)) return [];
      return _children.map(function (child, i) {
        var aria = {
          role: 'checkbox',
          'aria-checked': selected === i
        };
        process.env.NODE_ENV !== "production" ? (0, _warning["default"])(child != null, "Unsupported null or undefined child provided at index ".concat(i, " which will not be visible when rendered.")) : void 0;
        if (typeof child === 'string') {
          return _objectSpread(_objectSpread({}, aria), {}, {
            children: child,
            key: "item_".concat(child)
          });
        }
        return _objectSpread(_objectSpread({}, aria), child);
      });
    },
    className: function className(_ref4) {
      var adjustedDirection = _ref4.adjustedDirection,
        css = _ref4.css,
        open = _ref4.open,
        width = _ref4.width,
        title = _ref4.title,
        skin = _ref4.skin,
        styler = _ref4.styler;
      return styler.append("".concat(width, "Width"), {
        hasTitle: Boolean(title),
        open: open
      }, skin === 'silicon' ? (0, _classnames2["default"])(css.dropdownButton, _defineProperty({}, css.upDropdownButton, adjustedDirection === 'above')) : {});
    },
    direction: function direction(_ref5) {
      var _direction = _ref5.direction;
      return "".concat(_direction, " center");
    },
    hasChildren: function hasChildren(_ref6) {
      var children = _ref6.children;
      return children.length > 0;
    },
    title: function title(_ref7) {
      var children = _ref7.children,
        selected = _ref7.selected,
        _title = _ref7.title;
      if ((0, _DropdownList.isSelectedValid)({
        children: children,
        selected: selected
      })) {
        var child = children[selected];
        return typeof child === 'object' ? child.children : child;
      }
      return _title;
    }
  },
  render: function render(_ref8) {
    var adjustedDirection = _ref8.adjustedDirection,
      ariaLabel = _ref8['aria-label'],
      ariaLabelledBy = _ref8.ariaLabelledBy,
      children = _ref8.children,
      css = _ref8.css,
      direction = _ref8.direction,
      disabled = _ref8.disabled,
      hasChildren = _ref8.hasChildren,
      onAdjustDirection = _ref8.onAdjustDirection,
      onClose = _ref8.onClose,
      onOpen = _ref8.onOpen,
      onSelect = _ref8.onSelect,
      open = _ref8.open,
      selected = _ref8.selected,
      skin = _ref8.skin,
      title = _ref8.title,
      width = _ref8.width,
      rest = _objectWithoutProperties(_ref8, _excluded2);
    delete rest.rtl;
    var ariaProps = (0, _util.extractAriaProps)(rest);
    var calcAriaProps = ariaLabel != null ? null : {
      role: 'region',
      'aria-labelledby': ariaLabelledBy
    };
    var popupProps = {
      'aria-live': null,
      children: children,
      direction: "".concat(adjustedDirection, " center"),
      disabled: disabled,
      onSelect: onSelect,
      open: open,
      selected: selected,
      skin: skin,
      skinVariants: skin === 'silicon' ? {
        'night': false
      } : {},
      width: width,
      role: null
    };

    // `ui/Group`/`ui/Repeater` will throw an error if empty so we disable the Dropdown and
    // prevent Dropdown to open if there are no children.
    var openDropdown = hasChildren && !disabled && open;
    return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", _objectSpread(_objectSpread(_objectSpread({}, calcAriaProps), rest), {}, {
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(DropdownButton, _objectSpread(_objectSpread({
        "aria-label": ariaLabel,
        css: css,
        direction: direction,
        disabled: hasChildren ? disabled : true,
        icon: openDropdown ? 'arrowlargeup' : 'arrowlargedown',
        onAdjustDirection: onAdjustDirection,
        onClick: onOpen,
        onClose: onClose,
        offset: "none",
        open: openDropdown,
        popupComponent: _DropdownList["default"],
        popupProps: popupProps,
        role: "button",
        skin: skin,
        spotlightRestrict: "self-only"
      }, ariaProps), {}, {
        children: title
      }))
    }));
  }
});

/**
 * Applies Agate specific behaviors and functionality to
 * {@link agate/Dropdown.DropdownBase|DropdownBase}.
 *
 * @hoc
 * @memberof agate/Dropdown
 * @mixes ui/Changeable.Changeable
 * @mixes ui/Toggleable.Toggleable
 * @mixes spotlight/SpotlightContainerDecorator.SpotlightContainerDecorator
 * @mixes agate/Skinnable.Skinnable
 * @public
 */
var DropdownDecorator = exports.DropdownDecorator = (0, _compose["default"])((0, _SpotlightContainerDecorator["default"])({
  enterTo: 'default-element',
  preserveId: true
}), (0, _I18nDecorator.I18nContextDecorator)({
  rtlProp: 'rtl'
}), (0, _IdProvider["default"])({
  generateProp: null,
  prefix: 'd_'
}), (0, _Changeable["default"])({
  change: 'onAdjustDirection',
  prop: 'adjustedDirection'
}), (0, _Changeable["default"])({
  change: 'onSelect',
  prop: 'selected'
}), (0, _Toggleable["default"])({
  activate: 'onOpen',
  deactivate: 'onClose',
  prop: 'open',
  toggle: null
}), (0, _Skinnable["default"])({
  prop: 'skin'
}));

/**
 * An Agate Dropdown component.
 *
 * By default, `Dropdown` maintains the state of its `selected` property. Supply the
 * `defaultSelected` property to control its initial value. If you wish to directly control updates
 * to the component, supply a value to `selected` at creation time and update it in response to
 * `onSelect` events.
 *
 * @class Dropdown
 * @memberof agate/Dropdown
 * @extends agate/Dropdown.DropdownBase
 * @mixes agate/Dropdown.DropdownDecorator
 * @ui
 * @public
 */
var Dropdown = exports.Dropdown = DropdownDecorator(DropdownBase);
var _default = exports["default"] = Dropdown;