"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = exports.InputDecorator = exports.InputBase = exports.Input = void 0;
var _kind = _interopRequireDefault(require("@enact/core/kind"));
var _handle = require("@enact/core/handle");
var _I18nDecorator = require("@enact/i18n/I18nDecorator");
var _util = require("@enact/i18n/util");
var _Changeable = _interopRequireDefault(require("@enact/ui/Changeable"));
var _Pure = _interopRequireDefault(require("@enact/ui/internal/Pure"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _compose = _interopRequireDefault(require("ramda/src/compose"));
var _$L = _interopRequireDefault(require("../internal/$L"));
var _Skinnable = _interopRequireDefault(require("../Skinnable"));
var _Tooltip = _interopRequireDefault(require("../TooltipDecorator/Tooltip"));
var _InputDecoratorIcon = _interopRequireDefault(require("./InputDecoratorIcon"));
var _InputSpotlightDecorator = _interopRequireDefault(require("./InputSpotlightDecorator"));
var _util2 = require("./util");
var _InputModule = _interopRequireDefault(require("./Input.module.css"));
var _jsxRuntime = require("react/jsx-runtime");
var _excluded = ["clearButton", "clearIcon", "css", "dir", "disabled", "handleClear", "iconAfter", "iconBefore", "invalidTooltip", "onChange", "placeholder", "size", "type", "value"];
/**
 * Agate styled input components.
 *
 * @example
 * <Input placeholder="Enter text here" />
 *
 * @module agate/Input
 * @exports Input
 * @exports InputBase
 * @exports InputDecorator
 */
/**
 * An input component.
 *
 * @class InputBase
 * @memberof agate/Input
 * @ui
 * @public
 */
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 InputBase = exports.InputBase = (0, _kind["default"])({
  name: 'Input',
  propTypes: /** @lends agate/Input.InputBase.prototype */{
    /**
     * Shows the clear button.
     *
     * @type {Boolean}
     * @public
     */
    clearButton: _propTypes["default"].bool,
    /**
     * The icon to be placed in the clear button.
     *
     * @see {@link agate/Icon.Icon}
     * @type {String}
     * @default 'cancel'
     * @public
     */
    clearIcon: _propTypes["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:
     *
     * * `decorator` - The root class name
     * * `input` - The <input> class name
     *
     * @type {Object}
     * @private
     */
    css: _propTypes["default"].object,
    /**
     * Disables Input and makes it non-interactive.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    disabled: _propTypes["default"].bool,
    /**
     * Blurs the input when the "enter" key is pressed.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    dismissOnEnter: _propTypes["default"].bool,
    /**
     * Adds a `focused` class to the input decorator.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    focused: _propTypes["default"].bool,
    /**
     * The icon to be placed at the end of the input.
     *
     * @see {@link agate/Icon.Icon}
     * @type {String}
     * @public
     */
    iconAfter: _propTypes["default"].string,
    /**
     * The icon to be placed at the beginning of the input.
     *
     * @see {@link agate/Icon.Icon}
     * @type {String}
     * @public
     */
    iconBefore: _propTypes["default"].string,
    /**
     * Indicates {@link agate/Input.InputBase.value|value} is invalid and shows
     * {@link agate/Input.InputBase.invalidMessage|invalidMessage}, if set.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    invalid: _propTypes["default"].bool,
    /**
     * The tooltip text to be displayed when the input is
     * {@link agate/Input.InputBase.invalid|invalid}.
     *
     * If this value is *falsy*, the tooltip will not be shown.
     *
     * @type {String}
     * @default ''
     * @public
     */
    invalidMessage: _propTypes["default"].string,
    /**
     * Called before the input value is changed.
     *
     * The change can be prevented by calling `preventDefault` on the event.
     *
     * @type {Function}
     * @public
     */
    onBeforeChange: _propTypes["default"].func,
    /**
     * Called when blurred.
     *
     * @type {Function}
     * @param {Object} event
     * @public
     */
    onBlur: _propTypes["default"].func,
    /**
     * Called when the input value is changed.
     *
     * @type {Function}
     * @param {Object} event
     * @public
     */
    onChange: _propTypes["default"].func,
    /**
     * Called when clicked.
     *
     * @type {Function}
     * @param {Object} event
     * @public
     */
    onClick: _propTypes["default"].func,
    /**
     * Called when focused.
     *
     * @type {Function}
     * @param {Object} event
     * @public
     */
    onFocus: _propTypes["default"].func,
    /**
     * Called when a key is pressed down.
     *
     * @type {Function}
     * @param {Object} event
     * @public
     */
    onKeyDown: _propTypes["default"].func,
    /**
     * Text to display when {@link agate/Input.InputBase.value|value} is not set.
     *
     * @type {String}
     * @default ''
     * @public
     */
    placeholder: _propTypes["default"].string,
    /**
     * Indicates the content's text direction is right-to-left.
     *
     * @type {Boolean}
     * @private
     */
    rtl: _propTypes["default"].bool,
    /**
     * The size of the input field.
     *
     * @type {('large'|'small')}
     * @default 'large'
     * @public
     */
    size: _propTypes["default"].oneOf(['small', 'large']),
    /**
     * The type of input.
     *
     * Accepted values correspond to the standard HTML5 input types.
     *
     * @type {String}
     * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types|MDN input types doc}
     * @default 'text'
     * @public
     */
    type: _propTypes["default"].string,
    /**
     * The value of the input.
     *
     * @type {String|Number}
     * @public
     */
    value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number])
  },
  defaultProps: {
    clearIcon: 'cancel',
    disabled: false,
    dismissOnEnter: false,
    invalid: false,
    placeholder: '',
    size: 'large',
    type: 'text'
  },
  styles: {
    css: _InputModule["default"],
    className: 'decorator',
    publicClassNames: ['decorator', 'input']
  },
  handlers: {
    onChange: (0, _handle.handle)((0, _handle.adaptEvent)(function (ev) {
      return {
        type: 'onBeforeChange',
        value: ev.target.value
      };
    }, (0, _handle.forwardWithPrevent)('onBeforeChange')), (0, _handle.forwardCustom)('onChange', function (ev) {
      return {
        stopPropagation: function stopPropagation() {
          return ev.stopPropagation();
        },
        value: ev.target.value
      };
    })),
    handleClear: (0, _handle.handle)((0, _handle.forwardCustom)('onChange', function (ev) {
      return {
        stopPropagation: function stopPropagation() {
          return ev.stopPropagation();
        },
        value: ''
      };
    }))
  },
  computed: {
    'aria-label': function ariaLabel(_ref) {
      var placeholder = _ref.placeholder,
        type = _ref.type,
        value = _ref.value;
      var title = value == null || value === '' ? placeholder : '';
      return (0, _util2.calcAriaLabel)(title, type, value);
    },
    className: function className(_ref2) {
      var focused = _ref2.focused,
        iconBefore = _ref2.iconBefore,
        iconAfter = _ref2.iconAfter,
        invalid = _ref2.invalid,
        size = _ref2.size,
        styler = _ref2.styler,
        value = _ref2.value;
      return styler.append({
        emptyValue: !value,
        focused: focused,
        invalid: invalid,
        hasIconBefore: iconBefore,
        hasIconAfter: iconAfter
      }, size);
    },
    dir: function dir(_ref3) {
      var value = _ref3.value,
        placeholder = _ref3.placeholder;
      return (0, _util.isRtlText)(value || placeholder) ? 'rtl' : 'ltr';
    },
    invalidTooltip: function invalidTooltip(_ref4) {
      var css = _ref4.css,
        invalid = _ref4.invalid,
        _ref4$invalidMessage = _ref4.invalidMessage,
        invalidMessage = _ref4$invalidMessage === void 0 ? (0, _$L["default"])('Please enter a valid value.') : _ref4$invalidMessage;
      if (invalid && invalidMessage) {
        return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip["default"], {
          css: css,
          relative: true,
          children: invalidMessage
        });
      }
    },
    // ensure we have a value so the internal <input> is always controlled
    value: function value(_ref5) {
      var _value = _ref5.value;
      return typeof _value === 'number' ? _value : _value || '';
    }
  },
  render: function render(_ref6) {
    var clearButton = _ref6.clearButton,
      clearIcon = _ref6.clearIcon,
      css = _ref6.css,
      dir = _ref6.dir,
      disabled = _ref6.disabled,
      handleClear = _ref6.handleClear,
      iconAfter = _ref6.iconAfter,
      iconBefore = _ref6.iconBefore,
      invalidTooltip = _ref6.invalidTooltip,
      onChange = _ref6.onChange,
      placeholder = _ref6.placeholder,
      size = _ref6.size,
      type = _ref6.type,
      value = _ref6.value,
      rest = _objectWithoutProperties(_ref6, _excluded);
    var inputProps = (0, _util2.extractInputProps)(rest);
    if (type === 'password') {
      inputProps.spellCheck = false;
    }
    delete rest.dismissOnEnter;
    delete rest.focused;
    delete rest.invalid;
    delete rest.invalidMessage;
    delete rest.onBeforeChange;
    delete rest.rtl;
    return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", _objectSpread(_objectSpread({}, rest), {}, {
      "aria-disabled": disabled,
      disabled: disabled,
      children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_InputDecoratorIcon["default"], {
        position: "before",
        size: size,
        children: iconBefore
      }), /*#__PURE__*/(0, _jsxRuntime.jsx)("input", _objectSpread(_objectSpread({}, inputProps), {}, {
        "aria-disabled": disabled,
        className: css.input,
        dir: dir,
        disabled: disabled,
        onChange: onChange,
        placeholder: placeholder,
        size: size,
        tabIndex: -1,
        type: type,
        value: value
      })), clearButton ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputDecoratorIcon["default"], {
        className: (0, _classnames["default"])(_defineProperty({}, css.hideIcon, !((value === null || value === void 0 ? void 0 : value.length) >= 1))),
        position: "after",
        size: size,
        onClick: handleClear,
        children: clearIcon
      }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputDecoratorIcon["default"], {
        position: "after",
        size: size,
        children: iconAfter
      }), invalidTooltip]
    }));
  }
});

/**
 * Applies Agate specific behaviors to {@link agate/Input.InputBase|InputBase} components.
 *
 * @class InputDecorator
 * @hoc
 * @memberof agate/Input
 * @mixes ui/Changeable.Changeable
 * @mixes agate/Skinnable.Skinnable
 * @public
 */
var InputDecorator = exports.InputDecorator = (0, _compose["default"])(_Pure["default"], (0, _I18nDecorator.I18nContextDecorator)({
  rtlProp: 'rtl'
}), _Changeable["default"], _InputSpotlightDecorator["default"], _Skinnable["default"]);

/**
 * A Spottable, Agate styled input component with embedded icon support.
 *
 * By default, `Input` maintains the state of its `value` property. Supply the `defaultValue`
 * property to control its initial value. If you wish to directly control updates to the component,
 * supply a value to `value` at creation time and update it in response to `onChange` events.
 *
 * @class Input
 * @memberof agate/Input
 * @extends agate/Input.InputBase
 * @mixes ui/Changeable.Changeable
 * @mixes spotlight/Spottable.Spottable
 * @mixes agate/Skinnable.Skinnable
 * @ui
 * @public
 */
var Input = exports.Input = InputDecorator(InputBase);

/**
 * Focuses the internal input when the component gains 5-way focus.
 *
 * By default, the internal input is not editable when the component is focused via 5-way and must
 * be selected to become interactive. In pointer mode, the input will be editable when clicked.
 *
 * @name autoFocus
 * @memberof agate/Input.prototype
 * @type {Boolean}
 * @default false
 * @public
 */

/**
 * Applies a disabled style and prevents interacting with the component.
 *
 * @name disabled
 * @memberof agate/Input.prototype
 * @type {Boolean}
 * @default false
 * @public
 */

/**
 * Sets the initial value.
 *
 * @name defaultValue
 * @memberof agate/Input.prototype
 * @type {String}
 * @public
 */

/**
 * Blurs the input when the "enter" key is pressed.
 *
 * @name dismissOnEnter
 * @memberof agate/Input.prototype
 * @type {Boolean}
 * @default false
 * @public
 */

/**
 * Called when the internal input is focused.
 *
 * @name onActivate
 * @memberof agate/Input.prototype
 * @type {Function}
 * @param {Object} event
 * @public
 */

/**
 * Called when the internal input loses focus.
 *
 * @name onDeactivate
 * @memberof agate/Input.prototype
 * @type {Function}
 * @param {Object} event
 * @public
 */

/**
 * Called when the component is removed when it had focus.
 *
 * @name onSpotlightDisappear
 * @memberof agate/Input.prototype
 * @type {Function}
 * @param {Object} event
 * @public
 */

/**
 * Disables spotlight navigation into the component.
 *
 * @name spotlightDisabled
 * @memberof agate/Input.prototype
 * @type {Boolean}
 * @default false
 * @public
 */
var _default = exports["default"] = Input;