"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.InputDecorator = exports.InputBase = exports.Input = exports["default"] = void 0;

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

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 _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"));

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

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

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

/**
 * An input component.
 *
 * @class InputBase
 * @memberof agate/Input
 * @ui
 * @public
 */
var InputBase = (0, _kind["default"])({
  name: 'Input',
  propTypes:
  /** @lends agate/Input.InputBase.prototype */
  {
    /**
     * 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 [value]{@link agate/Input.InputBase.value} is invalid and shows
     * [invalidMessage]{@link agate/Input.InputBase.invalidMessage}, if set.
     *
     * @type {Boolean}
     * @default false
     * @public
     */
    invalid: _propTypes["default"].bool,

    /**
     * The tooltip text to be displayed when the input is
     * [invalid]{@link agate/Input.InputBase.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 [value]{@link agate/Input.InputBase.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 [MDN input types doc]{@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Form_%3Cinput%3E_types}
     * @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: {
    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
      };
    }))
  },
  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;
      return styler.append({
        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 css = _ref6.css,
        dir = _ref6.dir,
        disabled = _ref6.disabled,
        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, ["css", "dir", "disabled", "iconAfter", "iconBefore", "invalidTooltip", "onChange", "placeholder", "size", "type", "value"]);

    var inputProps = (0, _util2.extractInputProps)(rest);
    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
      })), /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputDecoratorIcon["default"], {
        position: "after",
        size: size,
        children: iconAfter
      }), invalidTooltip]
    }));
  }
});
/**
 * Applies Agate specific behaviors to [InputBase]{@link agate/Input.InputBase} components.
 *
 * @class InputDecorator
 * @hoc
 * @memberof agate/Input
 * @mixes ui/Changeable.Changeable
 * @mixes agate/Skinnable.Skinnable
 * @public
 */

exports.InputBase = InputBase;
var 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
 */

exports.InputDecorator = InputDecorator;
var 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
 */

exports.Input = Input;
var _default = Input;
exports["default"] = _default;