"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextInput = void 0;
var FontAwesome = require("react-fontawesome");
var React = require("react");
var PropTypes = require("prop-types");
var classnames = require("classnames");
var _ = require("lodash");
var Forms_1 = require("../utils/Forms");
require("./TextInput.less");
require("../less/forms.less");
var propTypes = {
    autoComplete: PropTypes.string,
    className: PropTypes.string,
    disabled: PropTypes.bool,
    disableAutocomplete: PropTypes.bool,
    enableShow: PropTypes.bool,
    error: PropTypes.string,
    hideButtonText: PropTypes.string,
    label: PropTypes.string,
    name: PropTypes.string.isRequired,
    onChange: PropTypes.func,
    onKeyDown: PropTypes.func,
    onKeyPress: PropTypes.func,
    onKeyUp: PropTypes.func,
    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    optional: PropTypes.bool,
    placeholder: PropTypes.string,
    placeholderCaps: PropTypes.bool,
    readOnly: PropTypes.bool,
    required: PropTypes.bool,
    requiredText: PropTypes.string,
    showButtonText: PropTypes.string,
    size: PropTypes.oneOf(Object.values(Forms_1.FormElementSize)),
    type: PropTypes.string,
    value: PropTypes.node,
};
var defaultProps = {
    placeholderCaps: false,
    size: Forms_1.FormElementSize.FULL_WIDTH,
};
var TextInput = /** @class */ (function (_super) {
    __extends(TextInput, _super);
    function TextInput(props) {
        var _this = _super.call(this, TextInput.validateProps(props)) || this;
        // eslint-disable-next-line react/sort-comp
        _this.input = React.createRef();
        _this.onFocus = function (e) {
            var onFocus = _this.props.onFocus;
            _this.setState({ inFocus: true });
            if (onFocus) {
                onFocus(e);
            }
        };
        _this.onBlur = function (e) {
            var onBlur = _this.props.onBlur;
            _this.setState({ inFocus: false, hasBeenFocused: true });
            if (onBlur) {
                onBlur(e);
            }
        };
        _this.toggleHidden = function () {
            _this.setState({ hidden: !_this.state.hidden });
        };
        _this.state = { inFocus: false, hasBeenFocused: false, hidden: true };
        return _this;
    }
    TextInput.validateProps = function (props) {
        if (props.required && props.optional) {
            console.warn("You should not pass both `required` and `optional` on a TextInput.");
        }
        if (props.readOnly && props.disabled) {
            console.warn("The readOnly, disabled props on a TextArea are mutually exclusive. If both are passed readOnly is used");
        }
        return props;
    };
    TextInput.prototype.focus = function () {
        this.input.current.focus();
    };
    TextInput.prototype.currentErrorMessage = function () {
        var _a = this.props, error = _a.error, value = _a.value, required = _a.required, requiredText = _a.requiredText;
        var hasBeenFocused = this.state.hasBeenFocused;
        var errorMessage = "";
        if (required && hasBeenFocused && !value) {
            errorMessage = requiredText || "required";
        }
        if (error) {
            errorMessage = error;
        }
        return errorMessage;
    };
    TextInput.prototype.renderNote = function (errorMessage) {
        var _a = this.props, required = _a.required, requiredText = _a.requiredText, optional = _a.optional;
        var inputNote;
        if (required) {
            inputNote = React.createElement("span", { className: "TextInput--required" }, requiredText || "required");
        }
        if (optional) {
            inputNote = React.createElement("span", { className: "TextInput--optional" }, "optional");
        }
        if (errorMessage) {
            inputNote = (React.createElement("span", { className: "TextInput--error" },
                React.createElement(FontAwesome, { name: "exclamation-triangle" }),
                " ",
                errorMessage));
        }
        return inputNote;
    };
    TextInput.prototype.render = function () {
        var wrapperClass = "TextInput";
        var errorMessage = this.currentErrorMessage();
        var valid = errorMessage === "";
        // add additional wrapper classes
        if (errorMessage)
            wrapperClass += " TextInput--hasError";
        if (this.props.readOnly) {
            wrapperClass += " TextInput--readonly";
        }
        else if (this.props.disabled) {
            wrapperClass += " TextInput--disabled";
        }
        else if (this.state.inFocus) {
            wrapperClass += " TextInput--inFocus";
        }
        // placeholder shown with caps
        if (!this.props.value && this.props.placeholder && this.props.placeholderCaps) {
            wrapperClass += " TextInput--placeholder-shown";
        }
        else if (!this.props.value && this.props.placeholder) {
            wrapperClass += " TextInput--placeholder-shown-no-caps";
        }
        // note on the upper right corner
        var inputNote = this.renderNote(errorMessage);
        var type;
        if (this.props.type === "password") {
            type = this.state.hidden ? "password" : "text";
        }
        else {
            type = this.props.type || "text";
        }
        var autoComplete;
        if (this.props.disableAutocomplete) {
            autoComplete = "off";
        }
        else if (this.props.autoComplete) {
            autoComplete = this.props.autoComplete;
        }
        var additionalProps = _.omit(this.props, Object.keys(propTypes));
        // (a11y) The 'for' attribute of the label tag and the 'id' attribute
        // of the input tag should match so screen readers can determine which
        // label goes with which form element. If an 'id' isn't specified, we
        // use 'name' instead for this purpose.
        var id = additionalProps.id || this.props.name;
        var hideButtonText = this.props.hideButtonText || "Hide";
        var showButtonText = this.props.showButtonText || "Show";
        return (React.createElement("div", { className: classnames(wrapperClass, Forms_1.formElementSizeClassName(this.props.size), this.props.className) },
            React.createElement("div", { className: "TextInput--infoRow" },
                React.createElement("label", { className: "TextInput--label", htmlFor: id }, this.props.label),
                React.createElement("span", { "aria-live": "polite" }, inputNote)),
            React.createElement("input", __assign({}, additionalProps, { id: id, autoComplete: autoComplete, className: "TextInput--input", disabled: this.props.disabled, name: this.props.name, onBlur: this.onBlur, onChange: this.props.onChange, onKeyDown: this.props.onKeyDown, onKeyPress: this.props.onKeyPress, onKeyUp: this.props.onKeyUp, onFocus: this.onFocus, placeholder: this.props.placeholder, readOnly: this.props.readOnly, ref: this.input, required: this.props.required, type: type, value: this.props.value, "aria-invalid": !valid, "aria-label": this.props.label })),
            this.props.enableShow && (React.createElement("button", { type: "button", className: "TextInput--link", onClick: this.toggleHidden, onMouseDown: function (event) {
                    // This prevents focus from jumping to the address bar or
                    // the first element on voiceover-enabled iOS devices
                    event.preventDefault();
                    event.stopPropagation();
                } }, this.state.hidden ? showButtonText : hideButtonText))));
    };
    TextInput.propTypes = propTypes;
    TextInput.defaultProps = defaultProps;
    return TextInput;
}(React.Component));
exports.TextInput = TextInput;
