"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.PickerDecorator = exports.PickerBase = exports.Picker = exports.ChangeAdapter = void 0;
Object.defineProperty(exports, "PickerItem", {
  enumerable: true,
  get: function get() {
    return _PickerItem["default"];
  }
});
exports["default"] = void 0;
var _handle = require("@enact/core/handle");
var _kind = _interopRequireDefault(require("@enact/core/kind"));
var _hoc = _interopRequireDefault(require("@enact/core/hoc"));
var _Spottable = _interopRequireDefault(require("@enact/spotlight/Spottable"));
var _Changeable = _interopRequireDefault(require("@enact/ui/Changeable"));
var _IdProvider = _interopRequireDefault(require("@enact/ui/internal/IdProvider"));
var _Touchable = _interopRequireDefault(require("@enact/ui/Touchable"));
var _ViewManager = require("@enact/ui/ViewManager");
var _propTypes = _interopRequireDefault(require("prop-types"));
var _clamp = _interopRequireDefault(require("ramda/src/clamp"));
var _compose = _interopRequireDefault(require("ramda/src/compose"));
var _$L = _interopRequireDefault(require("../$L"));
var _Picker = require("./Picker");
var _Skinnable = _interopRequireDefault(require("../../Skinnable"));
var _PickerModule = _interopRequireDefault(require("./Picker.module.css"));
var _jsxRuntime = require("react/jsx-runtime");
var _PickerItem = _interopRequireDefault(require("./PickerItem"));
var _excluded = ["activeClassName", "aria-label", "children", "currentItemIndex", "currentValueText", "decrementAriaLabel", "decrementItemIndex", "disabled", "focusBackgroundClassName", "handleDecrement", "handleFlick", "handleIncrement", "incrementAriaLabel", "incrementItemIndex", "min", "max", "noAnimation", "onSpotlightDisappear", "orientation", "reverseTransition", "spotlightDisabled", "step", "value", "valueId", "width", "wrap"];
/* eslint-disable react/jsx-no-bind */
/**
 * A internal Picker component.
 *
 * @module agate/internal/Picker
 * @exports Picker
 * @exports PickerDecorator
 * @private
 */
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 PickerRoot = (0, _Touchable["default"])('div');
var PickerButtonItem = (0, _Spottable["default"])('div');
var wrapRange = function wrapRange(min, max, value) {
  if (value > max) {
    return min + (value - max - 1);
  } else if (value < min) {
    return max - (min - value - 1);
  } else {
    return value;
  }
};
var handleChange = function handleChange(direction) {
  return (0, _handle.handle)((0, _handle.adaptEvent)(function (ev, _ref) {
    var min = _ref.min,
      max = _ref.max,
      step = _ref.step,
      value = _ref.value,
      wrap = _ref.wrap;
    return {
      value: wrap ? wrapRange(min, max, value + direction * step) : (0, _clamp["default"])(min, max, value + direction * step),
      reverseTransition: direction < 0
    };
  }, (0, _handle.forward)('onChange')));
};
var increment = handleChange(1);
var decrement = handleChange(-1);

/**
 * The base component for {@link agate/internal/Picker.Picker}.
 *
 * @class Picker
 * @memberof agate/internal/Picker
 * @ui
 * @private
 */
var PickerBase = exports.PickerBase = (0, _kind["default"])({
  name: 'Picker',
  propTypes: /** @lends agate/internal/Picker.Picker.prototype */{
    /**
     * Index for internal ViewManager
     *
     * @type {Number}
     * @required
     * @public
     */
    index: _propTypes["default"].number.isRequired,
    /**
     * The maximum value selectable by the picker (inclusive).
     *
     * The range between `min` and `max` should be evenly divisible by
     * {@link agate/internal/Picker.Picker.step|step}.
     *
     * @type {Number}
     * @required
     * @public
     */
    max: _propTypes["default"].number.isRequired,
    /**
     * The minimum value selectable by the picker (inclusive).
     *
     * The range between `min` and `max` should be evenly divisible by
     * {@link agate/internal/Picker.Picker.step|step}.
     *
     * @type {Number}
     * @required
     * @public
     */
    min: _propTypes["default"].number.isRequired,
    /**
     * Accessibility hint
     *
     * For example, `hour`, `year`, and `meridiem`
     *
     * @type {String}
     * @default ''
     * @public
     */
    accessibilityHint: _propTypes["default"].string,
    /**
     * The "aria-label" for the picker.
     *
     * By default, `aria-valuetext` is set to the current value.
     * This should only be used when the parent controls the value of
     * the picker directly through the props.
     *
     * @type {String}
     * @public
     */
    'aria-label': _propTypes["default"].string,
    /**
     * Overrides the `aria-valuetext` for the picker. By default, `aria-valuetext` is set
     * to the current value. This should only be used when the parent controls the value of
     * the picker directly through the props.
     *
     * @type {String|Number}
     * @public
     */
    'aria-valuetext': _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]),
    /**
     * Children from which to pick
     *
     * @type {Node}
     * @public
     */
    children: _propTypes["default"].node,
    /**
     * Class name for component.
     *
     * @type {String}
     * @public
     */
    className: _propTypes["default"].string,
    /**
     * Customize component style
     *
     * @type {Object}
     * @private
     */
    css: _propTypes["default"].object,
    /**
     * Sets the hint string read when focusing the decrement button.
     *
     * @type {String}
     * @default 'previous item'
     * @public
     */
    decrementAriaLabel: _propTypes["default"].string,
    /**
     * Disables the picker.
     *
     * @type {Boolean}
     * @public
     */
    disabled: _propTypes["default"].bool,
    /**
     * The picker id reference for setting aria-controls.
     *
     * @type {String}
     * @private
     */
    id: _propTypes["default"].string,
    /**
     * Sets the hint string read when focusing the increment button.
     *
     * @default 'next item'
     * @type {String}
     * @public
     */
    incrementAriaLabel: _propTypes["default"].string,
    /**
     * By default, the picker will animate transitions between items if it has a defined
     * `width`. Specifying `noAnimation` will prevent any transition animation for the
     * component.
     *
     * @type {Boolean}
     * @public
     */
    noAnimation: _propTypes["default"].bool,
    /**
     * A function to run when the control should increment or decrement.
     *
     * @type {Function}
     * @public
     */
    onChange: _propTypes["default"].func,
    /**
     * A function to run when the picker is removed while retaining focus.
     *
     * @type {Function}
     * @private
     */
    onSpotlightDisappear: _propTypes["default"].func,
    /**
     * Orientation of the picker.
     *
     * Controls whether the buttons are arranged horizontally or vertically around the value.
     *
     * * Values: `'horizontal'`, `'vertical'`
     *
     * @type {String}
     * @default 'vertical'
     * @public
     */
    orientation: _propTypes["default"].oneOf(['horizontal', 'vertical']),
    /**
     * When it's `true` it changes the direction of the transition animation.
     *
     * @type {Boolean}
     * @public
     */
    reverseTransition: _propTypes["default"].bool,
    /**
     * When `true`, the component cannot be navigated using spotlight.
     *
     * @type {Boolean}
     * @public
     */
    spotlightDisabled: _propTypes["default"].bool,
    /**
     * Allow the picker to only increment or decrement by a given value.
     *
     * A step of `2` would cause a picker to increment from 10 to 12 to 14, etc. It must evenly
     * divide into the range designated by `min` and `max`.
     *
     * @type {Number}
     * @default 1
     * @public
     */
    step: _propTypes["default"].number,
    /**
     * The type of picker. It determines the aria-label for the next and previous buttons.
     *
     * Depending on the `type`, `decrementAriaLabel`, and `incrementAriaLabel`,
     * the screen readers read out differently when Spotlight is on the next button, the previous button,
     * or the picker itself.
     *
     * For example, if Spotlight is on the next button
     * and aria label props(`decrementAriaLabel` and `incrementAriaLabel`) are not defined,
     * then the screen readers read out as follows.
     *	`'string'` type: `'next item'`
     * 	`'number'` type: `'increase the value'`
     *
     * @type {('number'|'string')}
     * @default 'string'
     * @public
     */
    type: _propTypes["default"].oneOf(['number', 'string']),
    /**
     * Index of the selected child.
     *
     * @type {Number}
     * @default 0
     * @public
     */
    value: _propTypes["default"].number,
    /**
     * Choose a specific size for your picker. `'small'`, `'medium'`, `'large'`, or set to `null` to
     * assume auto-sizing. `'small'` is good for numeric pickers, `'medium'` for single or short
     * word pickers, `'large'` for maximum-sized pickers.
     *
     * You may also supply a number. This number will determine the minimum size of the Picker.
     * Setting a number to less than the number of characters in your longest value may produce
     * unexpected results.
     *
     * @type {('small'|'medium'|'large'|Number)}
     * @public
     */
    width: _propTypes["default"].oneOfType([_propTypes["default"].oneOf([null, 'small', 'medium', 'large']), _propTypes["default"].number]),
    /**
     * Should the picker stop incrementing when the picker reaches the last element? Set `wrap`
     * to `true` to allow the picker to continue from the opposite end of the list of options.
     *
     * @type {Boolean}
     * @public
     */
    wrap: _propTypes["default"].bool
  },
  defaultProps: {
    accessibilityHint: '',
    orientation: 'vertical',
    step: 1,
    type: 'string',
    value: 0
  },
  styles: {
    css: _PickerModule["default"],
    className: 'picker',
    publicClassNames: true
  },
  handlers: {
    handleDecrement: decrement,
    handleFlick: (0, _handle.handle)((0, _handle.forEventProp)('direction', 'vertical'),
    // ignore "slow" flicks by filtering out velocity below a threshold
    (0, _handle.oneOf)([function (_ref2) {
      var velocityY = _ref2.velocityY;
      return velocityY < 0;
    }, increment], [function (_ref3) {
      var velocityY = _ref3.velocityY;
      return velocityY > 0;
    }, decrement])),
    handleIncrement: increment
  },
  computed: {
    activeClassName: function activeClassName(_ref4) {
      var styler = _ref4.styler;
      return styler.join('active', 'item');
    },
    'aria-label': function ariaLabel(_ref5) {
      var _ariaLabel = _ref5['aria-label'],
        valueText = _ref5['aria-valuetext'];
      if (_ariaLabel != null) {
        return _ariaLabel;
      }
      return valueText;
    },
    className: function className(_ref6) {
      var orientation = _ref6.orientation,
        styler = _ref6.styler;
      return styler.append(orientation);
    },
    currentItemIndex: function currentItemIndex(_ref7) {
      var values = _ref7.children,
        index = _ref7.index,
        max = _ref7.max,
        min = _ref7.min,
        wrap = _ref7.wrap;
      if (Array.isArray(values)) {
        if (wrap) {
          return wrapRange(min, max, index);
        } else return index;
      } else return 0;
    },
    currentValueText: function currentValueText(_ref8) {
      var accessibilityHint = _ref8.accessibilityHint,
        ariaValueText = _ref8['aria-valuetext'],
        children = _ref8.children,
        value = _ref8.value;
      if (ariaValueText != null) {
        return ariaValueText;
      }
      var valueText = value;
      if (children && Array.isArray(children)) {
        if (children[value] && children[value].props) {
          valueText = children[value].props.children;
        } else {
          valueText = children[value];
        }
      }
      if (accessibilityHint) {
        valueText = "".concat(valueText, " ").concat(accessibilityHint);
      }
      return valueText;
    },
    decrementAriaLabel: function decrementAriaLabel(_ref9) {
      var _decrementAriaLabel = _ref9.decrementAriaLabel,
        type = _ref9.type;
      if (_decrementAriaLabel != null) {
        return _decrementAriaLabel;
      }
      if (type === 'number') {
        return "".concat((0, _$L["default"])('decrease the value'));
      } else {
        return "".concat((0, _$L["default"])('previous item'));
      }
    },
    decrementItemIndex: function decrementItemIndex(_ref10) {
      var values = _ref10.children,
        index = _ref10.index,
        max = _ref10.max,
        min = _ref10.min,
        wrap = _ref10.wrap;
      if (Array.isArray(values)) {
        if (wrap) {
          return wrapRange(min, max, index - 1);
        } else return index - 1;
      } else return 0;
    },
    focusBackgroundClassName: function focusBackgroundClassName(_ref11) {
      var styler = _ref11.styler;
      return styler.join('focusBackground');
    },
    incrementAriaLabel: function incrementAriaLabel(_ref12) {
      var _incrementAriaLabel = _ref12.incrementAriaLabel,
        type = _ref12.type;
      if (_incrementAriaLabel != null) {
        return _incrementAriaLabel;
      }
      if (type === 'number') {
        return "".concat((0, _$L["default"])('increase the value'));
      } else {
        return "".concat((0, _$L["default"])('next item'));
      }
    },
    incrementItemIndex: function incrementItemIndex(_ref13) {
      var values = _ref13.children,
        index = _ref13.index,
        max = _ref13.max,
        min = _ref13.min,
        wrap = _ref13.wrap;
      if (Array.isArray(values)) {
        if (wrap) {
          return wrapRange(min, max, index + 1);
        } else return index + 1;
      } else return 0;
    },
    valueId: function valueId(_ref14) {
      var id = _ref14.id;
      return "".concat(id, "_value");
    }
  },
  render: function render(props) {
    var activeClassName = props.activeClassName,
      ariaLabel = props['aria-label'],
      values = props.children,
      currentItemIndex = props.currentItemIndex,
      currentValueText = props.currentValueText,
      decAriaLabel = props.decrementAriaLabel,
      decrementItemIndex = props.decrementItemIndex,
      disabled = props.disabled,
      focusBackgroundClassName = props.focusBackgroundClassName,
      handleDecrement = props.handleDecrement,
      handleFlick = props.handleFlick,
      handleIncrement = props.handleIncrement,
      incAriaLabel = props.incrementAriaLabel,
      incrementItemIndex = props.incrementItemIndex,
      min = props.min,
      max = props.max,
      noAnimation = props.noAnimation,
      onSpotlightDisappear = props.onSpotlightDisappear,
      orientation = props.orientation,
      reverseTransition = props.reverseTransition,
      spotlightDisabled = props.spotlightDisabled,
      step = props.step,
      value = props.value,
      valueId = props.valueId,
      width = props.width,
      wrap = props.wrap,
      rest = _objectWithoutProperties(props, _excluded);
    var isFirst = value <= min;
    var isLast = value >= max;
    var decrementAriaLabel = "".concat(currentValueText, " ").concat(decAriaLabel);
    var incrementAriaLabel = "".concat(currentValueText, " ").concat(incAriaLabel);
    var transitionDuration = 150;
    var decrementValue = function decrementValue() {
      var clampledValue = min < max ? (0, _clamp["default"])(min, max, value - step) : min;
      var restrictedDecrementValue = wrap ? wrapRange(min, max, value - step) : clampledValue;
      if (isFirst && !wrap) {
        return '';
      } else if (Array.isArray(values)) {
        return values;
      } else {
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Picker.PickerItem, {
          style: {
            direction: 'ltr'
          },
          children: restrictedDecrementValue
        }, restrictedDecrementValue);
      }
    };
    var incrementValue = function incrementValue() {
      var clampledValue = min < max ? (0, _clamp["default"])(min, max, value + step) : max;
      var restrictedIncrementValue = wrap ? wrapRange(min, max, value + step) : clampledValue;
      if (isLast && !wrap) {
        return '';
      } else if (Array.isArray(values)) {
        return values;
      } else {
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Picker.PickerItem, {
          style: {
            direction: 'ltr'
          },
          children: restrictedIncrementValue
        }, restrictedIncrementValue);
      }
    };
    var sizingPlaceholder = null;
    if (typeof width === 'number' && width > 0) {
      sizingPlaceholder = /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        "aria-hidden": true,
        className: _PickerModule["default"].sizingPlaceholder,
        children: '0'.repeat(width)
      });
    }
    var horizontal = orientation === 'horizontal';
    var arranger = horizontal ? _ViewManager.SlideLeftArranger : _ViewManager.SlideTopArranger;
    delete rest['aria-valuetext'];
    delete rest.accessibilityHint;
    delete rest.decrementAriaLabel;
    delete rest.incrementAriaLabel;
    delete rest.noAnimation;
    delete rest.onChange;
    delete rest.orientation;
    delete rest.wrap;
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)(PickerRoot, _objectSpread(_objectSpread({}, rest), {}, {
      disabled: disabled,
      onFlick: handleFlick,
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        className: focusBackgroundClassName
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(PickerButtonItem, {
        "aria-controls": valueId,
        "aria-disabled": disabled || isFirst,
        "aria-label": decrementAriaLabel,
        className: _PickerModule["default"].itemDecrement,
        disabled: disabled || isFirst,
        onClick: decrementValue() === '' ? function () {} : handleDecrement,
        onSpotlightDisappear: onSpotlightDisappear,
        spotlightDisabled: spotlightDisabled || decrementValue() === '',
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ViewManager.ViewManager, {
          "aria-hidden": true,
          arranger: arranger,
          className: _PickerModule["default"].viewManager,
          duration: transitionDuration,
          index: decrementItemIndex,
          noAnimation: noAnimation || disabled,
          reverseTransition: reverseTransition,
          children: decrementValue()
        })
      }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
        "aria-label": ariaLabel,
        "aria-valuetext": currentValueText,
        className: activeClassName,
        id: valueId,
        role: "spinbutton",
        children: [sizingPlaceholder, /*#__PURE__*/(0, _jsxRuntime.jsx)(_ViewManager.ViewManager, {
          "aria-hidden": true,
          arranger: arranger,
          className: _PickerModule["default"].viewManager,
          disabled: disabled,
          duration: transitionDuration,
          index: currentItemIndex,
          noAnimation: noAnimation || disabled,
          reverseTransition: reverseTransition,
          children: values
        })]
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)(PickerButtonItem, {
        "aria-controls": valueId,
        "aria-disabled": disabled || isLast,
        "aria-label": incrementAriaLabel,
        className: _PickerModule["default"].itemIncrement,
        disabled: disabled || isLast,
        onClick: incrementValue() === '' ? function () {} : handleIncrement,
        onSpotlightDisappear: onSpotlightDisappear,
        spotlightDisabled: spotlightDisabled || incrementValue() === '',
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ViewManager.ViewManager, {
          "aria-hidden": true,
          arranger: arranger,
          className: _PickerModule["default"].viewManager,
          duration: transitionDuration,
          index: incrementItemIndex,
          noAnimation: noAnimation || disabled,
          reverseTransition: reverseTransition,
          children: incrementValue()
        })
      })]
    }));
  }
});

/**
 * A higher-order component that filters the values returned by the onChange event on {@link agate/internal/Picker.Picker}
 *
 * @class ChangeAdapter
 * @hoc
 * @memberof agate/internal/Picker
 * @private
 */
var ChangeAdapter = exports.ChangeAdapter = (0, _hoc["default"])(function (config, Wrapped) {
  return (0, _kind["default"])({
    name: 'ChangeAdapter',
    handlers: {
      onChange: (0, _handle.handle)((0, _handle.adaptEvent)(function (_ref15) {
        var value = _ref15.value;
        return {
          value: value
        };
      }, (0, _handle.forward)('onChange')))
    },
    render: function render(props) {
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapped, _objectSpread({}, props));
    }
  });
});

/**
 * Applies Agate specific behaviors to {@link agate/Picker.Picker|Picker}.
 *
 * @hoc
 * @memberof agate/internal/Picker
 * @mixes ui/Changeable.Changeable
 * @mixes agate/Skinnable.Skinnable
 * @private
 */
var PickerDecorator = exports.PickerDecorator = (0, _compose["default"])((0, _IdProvider["default"])({
  generateProp: null
}), _Changeable["default"], (0, _Changeable["default"])({
  prop: 'reverseTransition'
}), (0, _Skinnable["default"])({
  prop: 'skin'
}));
var Picker = exports.Picker = PickerDecorator(PickerBase);
var _default = exports["default"] = Picker;