import { MDCTextField } from "@material/textfield";
import { h, Host, } from "@stencil/core";
import { debounce } from "lodash-es";
import { ARROW_DOWN, ARROW_UP, ENTER, ESCAPE, SPACE, TAB, } from "../../util/keycodes";
import { getHref, getTarget, getRel } from "../../util/link-helper";
import { createRandomString } from "../../util/random-string";
import { globalConfig } from "../../global/config";
const CHANGE_EVENT_DEBOUNCE_TIMEOUT = 300;
const RESIZE_HANDLER_DEBOUNCE_TIMEOUT = 100;
/**
 * @exampleComponent limel-example-input-field-text
 * @exampleComponent limel-example-input-field-placeholder
 * @exampleComponent limel-example-input-field-text-multiple
 * @exampleComponent limel-example-input-field-number
 * @exampleComponent limel-example-input-field-autocomplete
 * @exampleComponent limel-example-input-field-icon-leading
 * @exampleComponent limel-example-input-field-icon-trailing
 * @exampleComponent limel-example-input-field-icon-both
 * @exampleComponent limel-example-input-field-showlink
 * @exampleComponent limel-example-input-field-error-icon
 * @exampleComponent limel-example-input-field-textarea
 * @exampleComponent limel-example-input-field-suffix
 * @exampleComponent limel-example-input-field-prefix
 * @exampleComponent limel-example-input-field-search
 * @exampleComponent limel-example-input-field-pattern
 * @exampleComponent limel-example-input-field-focus
 * @exampleComponent limel-example-input-field-selection
 */
export class InputField {
    constructor() {
        /**
         * Set to `true` to disable the field.
         * Use `disabled` to indicate that the field can normally be interacted
         * with, but is currently disabled. This tells the user that if certain
         * requirements are met, the field may become enabled again.
         */
        this.disabled = false;
        /**
         * Set to `true` to make the field read-only.
         * Use `readonly` when the field is only there to present the data it holds,
         * and will not become possible for the current user to edit.
         */
        this.readonly = false;
        /**
         * Set to `true` to indicate that the current value of the input field is
         * invalid.
         */
        this.invalid = false;
        /**
         * Set to `true` to indicate that the field is required.
         */
        this.required = false;
        /**
         * Type of input.
         *
         * Note** regarding type `url`: `limel-input` uses the native validation
         * built into the browser for many types of input fields. The native
         * validation for `url` is very strict, and does not allow relative urls,
         * nor any other formats that are not a "fully qualified" url. To allow
         * such urls, use the type `urlAsText` instead. `urlAsText` works exactly
         * like `text` in all regards, except that it enables use of the `showLink`
         * property.
         */
        this.type = 'text';
        /**
         * Set to `true` to format the current value of the input field only
         * if the field is of type number.
         * The number format is determined by the current language of the browser.
         */
        this.formatNumber = true;
        /**
         * Defines which numeric values are valid and the increment/decrement interval.
         * For example, `step={0.1}` allows decimals and steps by 0.1.
         * Set to `'any'` to allow any numeric value.
         * Only applies when `type` is `number`.
         */
        this.step = 'any';
        /**
         * list of suggestions `value` can autocomplete to.
         */
        this.completions = [];
        /**
         * For inputs of type `email`, `tel`, `url`, and `urlAsText`, set this to
         * `true` to show a trailing icon with a `mailto:`,`tel:`, or normal link,
         * respectively. The default icon can be overridden using the `trailingIcon`
         * property.
         */
        this.showLink = false;
        /**
         * The locale to use for formatting numbers.
         */
        this.locale = globalConfig.defaultLocale;
        this.isFocused = false;
        this.wasInvalid = false;
        this.showCompletions = false;
        this.completionsList = [];
        this.changeWaiting = false;
        this.initialize = () => {
            const element = this.limelInputField.shadowRoot.querySelector('.mdc-text-field');
            if (!element) {
                return;
            }
            this.mdcTextField = new MDCTextField(element);
            if (this.value) {
                this.mdcTextField.value = this.value;
            }
            if (this.invalid) {
                this.mdcTextField.valid = false;
            }
            this.mapCompletions();
            window.addEventListener('resize', this.layout, { passive: true });
            this.limelInputField.addEventListener('focus', this.setFocus);
        };
        this.mapCompletions = () => {
            this.completionsList = [...this.completions].map((item) => {
                return { text: item };
            });
        };
        this.setFocus = () => {
            this.mdcTextField.focus();
        };
        this.getContainerClassList = () => {
            const classList = {
                'mdc-text-field': true,
                'mdc-text-field--outlined': true,
                'mdc-text-field--invalid': this.isInvalid(),
                'mdc-text-field--disabled': this.disabled || this.readonly,
                'lime-text-field--readonly': this.readonly,
                'mdc-text-field--required': this.required,
                'lime-text-field--empty': this.isEmpty(),
                'lime-has-prefix': this.hasPrefix(),
                'lime-has-suffix': this.hasSuffix(),
            };
            if (this.type === 'textarea') {
                classList['mdc-text-field--textarea'] = true;
            }
            else {
                classList['mdc-text-field--with-leading-icon'] = !!this.leadingIcon;
                classList['mdc-text-field--with-trailing-icon'] =
                    !!this.getTrailingIcon();
            }
            return classList;
        };
        this.isEmpty = () => {
            var _a;
            if (this.type === 'number' && ((_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.validity.badInput)) {
                return false;
            }
            return !this.getCurrentValue();
        };
        this.getCurrentValue = () => {
            if (this.changeWaiting && this.inputElement) {
                return this.inputElement.value;
            }
            return this.value;
        };
        this.renderInput = (properties) => {
            if (this.type === 'textarea') {
                return;
            }
            const type = this.type === 'urlAsText' ? 'text' : this.type;
            return (h("input", Object.assign({}, properties, { type: type, pattern: this.pattern, onWheel: this.handleWheel, onKeyDown: this.onKeyDown, placeholder: this.placeholder })));
        };
        this.renderTextarea = (properties) => {
            if (this.type !== 'textarea') {
                return;
            }
            return (h("span", { class: "mdc-text-field__resizer" }, h("textarea", Object.assign({}, properties, { placeholder: this.placeholder }))));
        };
        this.layout = () => {
            var _a;
            (_a = this.mdcTextField) === null || _a === void 0 ? void 0 : _a.layout();
            this.restyleCompletionsDropDown();
        };
        this.restyleCompletionsDropDown = debounce(() => {
            const stateOfShowCompletions = this.showCompletions;
            this.showCompletions = false;
            requestAnimationFrame(() => {
                this.showCompletions = stateOfShowCompletions;
            });
        }, RESIZE_HANDLER_DEBOUNCE_TIMEOUT);
        this.getAdditionalProps = () => {
            const props = {};
            if (this.type === 'number') {
                props.step = this.step;
            }
            if (this.type === 'number' && Number.isInteger(this.min)) {
                props.min = this.min;
            }
            if (this.type === 'number' && Number.isInteger(this.max)) {
                props.max = this.max;
            }
            if (this.minlength) {
                props.minlength = this.minlength;
            }
            if (this.maxlength) {
                props.maxlength = this.maxlength;
            }
            return props;
        };
        this.onFocus = () => {
            this.isFocused = true;
            this.showCompletions = true;
        };
        this.onBlur = () => {
            this.isFocused = false;
            this.validate();
            this.changeEmitter.flush();
        };
        this.hasHelperText = () => {
            var _a;
            return !!((_a = this.helperText) !== null && _a !== void 0 ? _a : this.validationMessage);
        };
        this.hasHelperLine = () => {
            return this.maxlength > 0 || this.hasHelperText();
        };
        this.renderHelperLine = () => {
            var _a;
            const text = this.getCurrentValue() || '';
            const length = text.length;
            if (!this.hasHelperLine()) {
                return;
            }
            return (h("limel-helper-line", { helperTextId: this.helperTextId, helperText: (_a = this.helperText) !== null && _a !== void 0 ? _a : this.validationMessage, length: length, maxLength: this.maxlength, invalid: this.isInvalid() }));
        };
        this.renderSuffix = () => {
            if (!this.hasSuffix() || this.type === 'textarea') {
                return;
            }
            const classList = {
                'mdc-text-field__affix': true,
                'mdc-text-field__affix--suffix': true,
            };
            return h("span", { class: classList }, this.suffix);
        };
        this.hasSuffix = () => {
            return this.suffix !== null && this.suffix !== undefined;
        };
        this.renderPrefix = () => {
            if (!this.hasPrefix() || this.type === 'textarea') {
                return;
            }
            const classList = {
                'mdc-text-field__affix': true,
                'mdc-text-field__affix--prefix': true,
            };
            return h("span", { class: classList }, this.prefix);
        };
        this.hasPrefix = () => {
            return this.prefix !== null && this.prefix !== undefined;
        };
        this.isInvalid = () => {
            if (this.readonly) {
                // A readonly field can never be invalid.
                return false;
            }
            if (this.invalid) {
                // `this.invalid` is set by the consumer. If the consumer explicitly
                // told us to consider the field invalid, we consider it invalid
                // regardless of what our internal validation thinks, and regardless
                // of whether the field has been modified.
                return true;
            }
            return this.wasInvalid;
        };
        this.validate = () => {
            if (this.readonly || this.invalid) {
                this.wasInvalid = false;
                return;
            }
            if (this.inputElement) {
                this.wasInvalid = !this.inputElement.checkValidity();
            }
        };
        this.setInputElement = (element) => {
            if (element) {
                this.inputElement = element;
            }
        };
        this.renderLeadingIcon = () => {
            if (this.type === 'textarea') {
                return;
            }
            if (this.leadingIcon) {
                return (h("i", { class: "material-icons mdc-text-field__icon mdc-text-field__icon--leading" }, h("limel-icon", { name: this.leadingIcon })));
            }
        };
        this.renderTrailingLinkOrButton = () => {
            if (this.type === 'textarea') {
                return;
            }
            const trailingIcon = this.getTrailingIcon();
            if (!this.isInvalid() && this.hasLink()) {
                return this.renderLinkIcon(this.getLink(), trailingIcon);
            }
            else if (trailingIcon) {
                return this.renderTrailingIcon(trailingIcon);
            }
        };
        this.hasLink = () => {
            return (this.showLink &&
                ['email', 'tel', 'url', 'urlAsText'].includes(this.type));
        };
        this.getLink = () => {
            const props = { href: '' };
            switch (this.type) {
                case 'email': {
                    props.href = `mailto:${this.value}`;
                    break;
                }
                case 'tel': {
                    props.href = `tel:${this.value}`;
                    break;
                }
                default: {
                    props.href = getHref(this.value);
                    props.target = getTarget(this.value);
                    props.rel = getRel(props.target);
                }
            }
            return props;
        };
        this.renderLinkIcon = (linkProps, icon) => {
            // If the trailing icon uses the class `mdc-text-field__icon--trailing`,
            // MDC attaches a click handler to it, which apparently runs
            // `preventDefault()` on the event. For links, we don't want that,
            // so instead of `mdc-text-field__icon--trailing`, we use our own class
            // `lime-trailing-icon-for-link`, which uses all the same styling. /Ads
            return (h("a", Object.assign({}, linkProps, { class: "material-icons mdc-text-field__icon lime-trailing-icon-for-link", tabindex: this.disabled || this.isEmpty() ? '-1' : '0', role: "button" }), h("limel-icon", { name: icon })));
        };
        this.renderTrailingIcon = (icon) => {
            if (this.isInvalid()) {
                return (h("i", { key: "invalid", class: "material-icons mdc-text-field__icon invalid-icon" }, h("limel-icon", { name: icon })));
            }
            return (h("i", { key: "action", class: "material-icons mdc-text-field__icon mdc-text-field__icon--trailing", tabIndex: 0, role: "button", onKeyDown: this.handleIconKeyPress, onClick: this.handleIconClick }, h("limel-icon", { name: icon })));
        };
        this.getTrailingIcon = () => {
            if (this.isInvalid()) {
                return 'high_importance';
            }
            if (this.trailingIcon) {
                return this.trailingIcon;
            }
            if (this.showLink && this.type === 'email') {
                return 'filled_message';
            }
            if (this.showLink && this.type === 'tel') {
                return 'phone';
            }
            if (this.showLink &&
                (this.type === 'url' || this.type === 'urlAsText')) {
                return 'external_link';
            }
        };
        this.renderFormattedNumber = () => {
            if (this.type !== 'number') {
                return;
            }
            let renderValue = this.value;
            if (this.formatNumber && this.value) {
                renderValue = new Intl.NumberFormat(this.locale).format(Number(this.value));
                if (renderValue === 'NaN') {
                    return;
                }
            }
            return (h("span", { class: "lime-formatted-input lime-looks-like-input-value" }, renderValue));
        };
        /**
         * Key handler for the input field
         * Will change focus to the first/last item in the dropdown list to enable selection with the keyboard
         *
         * @param event - event
         */
        this.onKeyDown = (event) => {
            this.showCompletions = true;
            const isForwardTab = event.key === TAB &&
                !event.altKey &&
                !event.metaKey &&
                !event.shiftKey;
            const isUp = event.key === ARROW_UP;
            const isDown = event.key === ARROW_DOWN;
            if (event.key === TAB && event.shiftKey) {
                this.showCompletions = false;
            }
            if (!isForwardTab && !isUp && !isDown) {
                return;
            }
            const list = document.querySelector(` #${this.portalId} limel-list`);
            if (!list) {
                return;
            }
            event.preventDefault();
            if (isForwardTab || isDown) {
                const listElement = list.shadowRoot.querySelector('.mdc-deprecated-list-item:first-child');
                listElement.focus();
                return;
            }
            if (isUp) {
                const listElement = list.shadowRoot.querySelector('.mdc-deprecated-list-item:last-child');
                listElement.focus();
            }
        };
        this.handleCompletionChange = (event) => {
            event.stopPropagation();
            if (!event.detail) {
                return;
            }
            this.showCompletions = false;
            /*
             This change event doesn't need to be debounced in itself, but we want
             to make absolutely sure that an earlier change event that *has* been
             debounced doesn't emit after this one. Therefore, we run this through
             the same debounced emitter function. /Ads
             */
            this.changeEmitter(event.detail.text);
            this.changeEmitter.flush();
        };
        this.renderAutocompleteList = () => {
            if (this.type === 'textarea' || this.completions.length === 0) {
                return;
            }
            const dropdownZIndex = getComputedStyle(this.limelInputField).getPropertyValue('--dropdown-z-index');
            return (h("limel-portal", { visible: this.showCompletions, containerId: this.portalId, inheritParentWidth: true, containerStyle: { 'z-index': dropdownZIndex } }, h("limel-menu-surface", { open: this.showCompletions, allowClicksElement: this.limelInputField, style: {
                    '--menu-surface-width': '100%',
                    'max-height': 'inherit',
                    display: 'flex',
                }, onDismiss: this.handleCloseMenu }, this.renderListResult())));
        };
        this.renderListResult = () => {
            const filteredCompletions = this.filterCompletions(this.getCurrentValue());
            if (!filteredCompletions || filteredCompletions.length === 0) {
                return null;
            }
            return (h("limel-list", { onChange: this.handleCompletionChange, onKeyDown: this.handleKeyDownInDropdown, type: "selectable", items: filteredCompletions }));
        };
        this.handleKeyDownInDropdown = (event) => {
            const keyFound = [TAB, ESCAPE, ENTER].includes(event.key);
            if (keyFound) {
                this.setFocus();
            }
        };
        this.handleCloseMenu = () => {
            this.showCompletions = false;
        };
        this.filterCompletions = (filter) => {
            if (!filter) {
                return this.completionsList;
            }
            return this.completionsList.filter((completion) => completion.text.toLowerCase().includes(filter.toLowerCase()));
        };
        this.handleInput = (event) => {
            event.stopPropagation();
            let value = event.target.value;
            if (this.type === 'number') {
                if (!value && event.data) {
                    event.stopPropagation();
                    return;
                }
                if (value) {
                    value = Number(value);
                }
            }
            this.changeWaiting = true;
            this.changeEmitter(value);
        };
        this.changeEmitter = debounce((value) => {
            this.change.emit(value);
            this.changeWaiting = false;
        }, CHANGE_EVENT_DEBOUNCE_TIMEOUT);
        this.handleChange = (event) => {
            event.stopPropagation();
            this.changeEmitter.flush();
        };
        this.handleIconClick = () => {
            this.action.emit();
        };
        this.handleIconKeyPress = (event) => {
            const isEnter = event.key === ENTER;
            const isSpace = event.key === SPACE;
            if (isSpace || isEnter) {
                this.action.emit();
            }
        };
        this.handleWheel = () => {
            // This empty event handler is here to circumvent a bug.
            // In some browsers (Chrome for example), hovering the input with
            // the input focused, and scrolling, will both change the value
            // AND scroll the page. We would prefer to never change the value
            // on scroll, instead always scrolling the page, but since we
            // haven't found a way to do that, this is the next best thing, as
            // it prevents the page from being scrolled, but only in the
            // circumstances when the value is changed by the scrolling.
            // Please test THOROUGHLY if you remove this event handler 😄
        };
        this.portalId = createRandomString();
        this.helperTextId = createRandomString();
        this.labelId = createRandomString();
    }
    connectedCallback() {
        this.initialize();
    }
    componentDidLoad() {
        this.initialize();
    }
    disconnectedCallback() {
        if (this.mdcTextField) {
            this.mdcTextField.destroy();
        }
        this.restyleCompletionsDropDown.cancel();
        window.removeEventListener('resize', this.layout);
        this.limelInputField.removeEventListener('focus', this.setFocus);
    }
    componentDidUpdate() {
        if (this.invalid) {
            this.mdcTextField.valid = false;
        }
        this.mdcTextField.disabled = this.disabled || this.readonly;
    }
    /**
     * Returns the start position of the current text selection.
     * Returns `null` if the input element is not available or if
     * the input type does not support selection (e.g., `number`).
     */
    async getSelectionStart() {
        var _a, _b;
        try {
            return (_b = (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : null;
        }
        catch (_c) {
            // Some input types (e.g., number) throw InvalidStateError
            return null;
        }
    }
    /**
     * Returns the end position of the current text selection.
     * Returns `null` if the input element is not available or if
     * the input type does not support selection (e.g., `number`).
     */
    async getSelectionEnd() {
        var _a, _b;
        try {
            return (_b = (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.selectionEnd) !== null && _b !== void 0 ? _b : null;
        }
        catch (_c) {
            // Some input types (e.g., number) throw InvalidStateError
            return null;
        }
    }
    /**
     * Returns the direction of the current text selection.
     * Can be `'forward'`, `'backward'`, or `'none'`.
     * Returns `null` if the input element is not available or if
     * the input type does not support selection (e.g., `number`).
     */
    async getSelectionDirection() {
        var _a, _b;
        try {
            return (_b = (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.selectionDirection) !== null && _b !== void 0 ? _b : null;
        }
        catch (_c) {
            // Some input types (e.g., number) throw InvalidStateError
            return null;
        }
    }
    render() {
        const properties = this.getAdditionalProps();
        properties['aria-labelledby'] = this.labelId;
        properties.class = 'mdc-text-field__input';
        properties.ref = this.setInputElement;
        properties.onInput = this.handleInput;
        properties.onChange = this.handleChange;
        properties.onFocus = this.onFocus;
        properties.onBlur = this.onBlur;
        properties.required = this.required;
        properties.readonly = this.readonly;
        properties.disabled = this.disabled || this.readonly;
        let ariaControls = '';
        if (this.hasHelperText()) {
            ariaControls += this.helperTextId;
            properties['aria-describedby'] = this.helperTextId;
        }
        if (this.renderAutocompleteList()) {
            if (ariaControls) {
                ariaControls += ' ';
            }
            ariaControls += this.portalId;
        }
        if (ariaControls) {
            properties['aria-controls'] = ariaControls;
        }
        return (h(Host, { key: '5026e41e99b24333c72b6372f85ba5915a5ba0a1' }, h("limel-notched-outline", { key: '5d50900e3b92709a8f4e581d6c08cb21a3aa53f1', labelId: this.labelId, label: this.label, required: this.required, invalid: this.invalid || this.isInvalid(), disabled: this.disabled, readonly: this.readonly, hasValue: !!this.value, hasLeadingIcon: !!this.leadingIcon }, h("label", { key: '24de43f8c2e05781db453a7d71b3f84b8f5ac0e9', slot: "content", class: this.getContainerClassList() }, this.renderLeadingIcon(), this.renderPrefix(), this.renderFormattedNumber(), this.renderInput(properties), this.renderSuffix(), this.renderTextarea(properties), this.renderTrailingLinkOrButton())), this.renderHelperLine(), this.renderAutocompleteList()));
    }
    valueWatcher(newValue) {
        if (!this.mdcTextField) {
            return;
        }
        if (this.changeWaiting) {
            return;
        }
        if (this.type === 'number' &&
            this.isFocused &&
            Number(newValue) === Number(this.mdcTextField.value)) {
            return;
        }
        if (newValue !== this.mdcTextField.value) {
            this.mdcTextField.value = newValue || '';
        }
        if (this.wasInvalid) {
            this.validate();
        }
    }
    completionsWatcher() {
        this.mapCompletions();
    }
    get validationMessage() {
        var _a;
        if (this.isInvalid() && !this.invalid) {
            return ((_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.validationMessage) || '';
        }
        return '';
    }
    static get is() { return "limel-input-field"; }
    static get encapsulation() { return "shadow"; }
    static get delegatesFocus() { return true; }
    static get originalStyleUrls() {
        return {
            "$": ["input-field.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["input-field.css"]
        };
    }
    static get properties() {
        return {
            "disabled": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to disable the field.\nUse `disabled` to indicate that the field can normally be interacted\nwith, but is currently disabled. This tells the user that if certain\nrequirements are met, the field may become enabled again."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "disabled",
                "defaultValue": "false"
            },
            "readonly": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to make the field read-only.\nUse `readonly` when the field is only there to present the data it holds,\nand will not become possible for the current user to edit."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "readonly",
                "defaultValue": "false"
            },
            "invalid": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to indicate that the current value of the input field is\ninvalid."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "invalid",
                "defaultValue": "false"
            },
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The input label."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "label"
            },
            "placeholder": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The placeholder text shown inside the input field, when the field is focused and empty."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "placeholder"
            },
            "helperText": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Optional helper text to display below the input field when it has focus"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "helper-text"
            },
            "prefix": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A short piece of text to display before the value inside the input field.\nDisplayed for all types except `textarea`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "prefix"
            },
            "suffix": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A short piece of text to display after the value inside the input field.\nDisplayed for all types except `textarea`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "suffix"
            },
            "required": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to indicate that the field is required."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "required",
                "defaultValue": "false"
            },
            "value": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The value of the field."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "value"
            },
            "trailingIcon": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Trailing icon to show to the far right in the field."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "trailing-icon"
            },
            "leadingIcon": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Leading icon to show to the far left in the field."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "leading-icon"
            },
            "pattern": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Regular expression that the current value of the input field must match.\nNo forward slashes should be specified around the pattern.\nOnly used if type is `text`, `tel`, `email`, `url`, `urlAsText`,\n`password`, or `search`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "pattern"
            },
            "type": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "InputType",
                    "resolved": "\"date\" | \"datetime-local\" | \"email\" | \"month\" | \"number\" | \"password\" | \"search\" | \"tel\" | \"text\" | \"textarea\" | \"time\" | \"url\" | \"urlAsText\" | \"week\"",
                    "references": {
                        "InputType": {
                            "location": "import",
                            "path": "../input-field/input-field.types",
                            "id": "src/components/input-field/input-field.types.ts::InputType",
                            "referenceLocation": "InputType"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Type of input.\n\nNote** regarding type `url`: `limel-input` uses the native validation\nbuilt into the browser for many types of input fields. The native\nvalidation for `url` is very strict, and does not allow relative urls,\nnor any other formats that are not a \"fully qualified\" url. To allow\nsuch urls, use the type `urlAsText` instead. `urlAsText` works exactly\nlike `text` in all regards, except that it enables use of the `showLink`\nproperty."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "type",
                "defaultValue": "'text'"
            },
            "formatNumber": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Set to `true` to format the current value of the input field only\nif the field is of type number.\nThe number format is determined by the current language of the browser."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "format-number",
                "defaultValue": "true"
            },
            "step": {
                "type": "any",
                "mutable": false,
                "complexType": {
                    "original": "number | 'any'",
                    "resolved": "\"any\" | number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Defines which numeric values are valid and the increment/decrement interval.\nFor example, `step={0.1}` allows decimals and steps by 0.1.\nSet to `'any'` to allow any numeric value.\nOnly applies when `type` is `number`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "step",
                "defaultValue": "'any'"
            },
            "max": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Maximum allowed value if input type is `number`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "max"
            },
            "min": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Minimum allowed value if input type is `number`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "min"
            },
            "maxlength": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Maximum length of the value if type is `password`, `search`, `tel`,\n`text`, `url`, or `urlAsText`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "maxlength"
            },
            "minlength": {
                "type": "number",
                "mutable": false,
                "complexType": {
                    "original": "number",
                    "resolved": "number",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Minimum length of the value if type is `password`, `search`, `tel`,\n`text`, `url`, or `urlAsText`."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "minlength"
            },
            "completions": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "string[]",
                    "resolved": "string[]",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "list of suggestions `value` can autocomplete to."
                },
                "getter": false,
                "setter": false,
                "defaultValue": "[]"
            },
            "showLink": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "For inputs of type `email`, `tel`, `url`, and `urlAsText`, set this to\n`true` to show a trailing icon with a `mailto:`,`tel:`, or normal link,\nrespectively. The default icon can be overridden using the `trailingIcon`\nproperty."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "show-link",
                "defaultValue": "false"
            },
            "locale": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "The locale to use for formatting numbers."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "locale",
                "defaultValue": "globalConfig.defaultLocale"
            }
        };
    }
    static get states() {
        return {
            "isFocused": {},
            "wasInvalid": {},
            "showCompletions": {}
        };
    }
    static get events() {
        return [{
                "method": "change",
                "name": "change",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the input value is changed."
                },
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                }
            }, {
                "method": "action",
                "name": "action",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when `trailingIcon` or `leadingIcon` is set\nand the icon is interacted with."
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }];
    }
    static get methods() {
        return {
            "getSelectionStart": {
                "complexType": {
                    "signature": "() => Promise<number | null>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<number>"
                },
                "docs": {
                    "text": "Returns the start position of the current text selection.\nReturns `null` if the input element is not available or if\nthe input type does not support selection (e.g., `number`).",
                    "tags": []
                }
            },
            "getSelectionEnd": {
                "complexType": {
                    "signature": "() => Promise<number | null>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<number>"
                },
                "docs": {
                    "text": "Returns the end position of the current text selection.\nReturns `null` if the input element is not available or if\nthe input type does not support selection (e.g., `number`).",
                    "tags": []
                }
            },
            "getSelectionDirection": {
                "complexType": {
                    "signature": "() => Promise<\"forward\" | \"backward\" | \"none\" | null>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<\"none\" | \"forward\" | \"backward\">"
                },
                "docs": {
                    "text": "Returns the direction of the current text selection.\nCan be `'forward'`, `'backward'`, or `'none'`.\nReturns `null` if the input element is not available or if\nthe input type does not support selection (e.g., `number`).",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "limelInputField"; }
    static get watchers() {
        return [{
                "propName": "value",
                "methodName": "valueWatcher"
            }, {
                "propName": "completions",
                "methodName": "completionsWatcher"
            }];
    }
}
