import focus from '@dojo/framework/core/middleware/focus';
import { createICacheMiddleware } from '@dojo/framework/core/middleware/icache';
import theme from '../middleware/theme';
import validity from '@dojo/framework/core/middleware/validity';
import { create, diffProperty, invalidator, tsx } from '@dojo/framework/core/vdom';
import { formatAriaProperties } from '../common/util';
import HelperText from '../helper-text/index';
import Label from '../label/index';
import * as css from '../theme/default/text-input.m.css';
function formatAutocomplete(autocomplete) {
    if (typeof autocomplete === 'boolean') {
        return autocomplete ? 'on' : 'off';
    }
    return autocomplete;
}
const factory = create({
    theme,
    icache: createICacheMiddleware(),
    validity,
    focus,
    diffProperty,
    invalidator
})
    .properties()
    .children();
export const TextInput = factory(function TextInput({ middleware: { icache, theme, validity, focus, diffProperty, invalidator }, properties, children, id }) {
    diffProperty('pattern', (previous, next) => {
        const value = next.pattern instanceof RegExp ? next.pattern.source : next.pattern;
        if (value !== previous.pattern) {
            invalidator();
        }
    });
    const themeCss = theme.classes(css);
    const dirty = icache.getOrSet('dirty', false);
    const { aria = {}, autocomplete, classes, customValidator, disabled, helperText, labelHidden = false, max, maxLength, min, minLength, name, onBlur, onClick, onFocus, onKeyDown, onKeyUp, onOut, onOver, onValidate, onValue, pattern: patternValue, placeholder, readOnly, required, step, theme: themeProp, type = 'text', initialValue, valid: validValue = { valid: undefined, message: '' }, widgetId = `text-input-${id}`, variant } = properties();
    let { value } = properties();
    const [{ label, leading, trailing } = {}] = children();
    if (value === undefined) {
        value = icache.get('value');
        const existingInitialValue = icache.get('initialValue');
        if (initialValue !== existingInitialValue) {
            icache.set('value', initialValue);
            icache.set('initialValue', initialValue);
            value = initialValue;
        }
    }
    const pattern = patternValue instanceof RegExp ? patternValue.source : patternValue;
    function _callOnValidate(valid, message) {
        let { valid: previousValid } = properties();
        let previousMessage;
        if (typeof previousValid === 'object') {
            previousMessage = previousValid.message;
            previousValid = previousValid.valid;
        }
        if (valid !== previousValid || message !== previousMessage) {
            onValidate && onValidate(valid, message);
        }
    }
    if (onValidate) {
        if (value === '' && !dirty) {
            _callOnValidate(undefined, '');
        }
        else {
            icache.set('dirty', true);
            let { valid, message = '' } = validity.get('input', value || '');
            if (valid && customValidator) {
                const customValid = customValidator(value || '');
                if (customValid) {
                    valid = customValid.valid;
                    message = customValid.message || '';
                }
            }
            _callOnValidate(valid, message);
        }
    }
    const { valid, message } = typeof validValue === 'boolean' ? { valid: validValue, message: '' } : validValue;
    const computedHelperText = (valid === false && message) || helperText;
    const inputFocused = focus.isFocused('input');
    return (tsx("div", { key: "root", classes: [theme.variant(), themeCss.root], role: "presentation" },
        tsx("div", { key: "wrapper", classes: [
                themeCss.wrapper,
                disabled ? themeCss.disabled : null,
                inputFocused ? themeCss.focused : null,
                valid === false ? themeCss.invalid : null,
                valid === true ? themeCss.valid : null,
                readOnly ? themeCss.readonly : null,
                required ? themeCss.required : null,
                leading ? themeCss.hasLeading : null,
                trailing ? themeCss.hasTrailing : null,
                !label || labelHidden ? themeCss.noLabel : null
            ], role: "presentation" },
            label && (tsx(Label, { theme: themeProp, classes: classes, variant: variant, disabled: disabled, valid: valid, focused: inputFocused, readOnly: readOnly, required: required, hidden: labelHidden, forId: widgetId, active: !!value || inputFocused }, label)),
            tsx("div", { key: "inputWrapper", classes: [
                    themeCss.inputWrapper,
                    inputFocused ? themeCss.inputWrapperFocused : undefined
                ], role: "presentation" },
                leading,
                tsx("input", Object.assign({}, formatAriaProperties(aria), { "aria-invalid": valid === false ? 'true' : undefined, autocomplete: formatAutocomplete(autocomplete), classes: themeCss.input, disabled: disabled, id: widgetId, focus: focus.shouldFocus, key: 'input', max: max, maxlength: maxLength ? `${maxLength}` : null, min: min, minlength: minLength ? `${minLength}` : null, name: name, pattern: pattern, placeholder: placeholder, readOnly: readOnly, "aria-readonly": readOnly ? 'true' : undefined, required: required, step: step, type: type, value: value, onblur: () => {
                        onBlur && onBlur();
                    }, onfocus: () => {
                        onFocus && onFocus();
                    }, oninput: (event) => {
                        event.stopPropagation();
                        const value = event.target.value;
                        icache.set('value', value);
                        onValue && onValue(value);
                    }, onkeydown: (event) => {
                        event.stopPropagation();
                        onKeyDown && onKeyDown(event.which, () => event.preventDefault());
                    }, onkeyup: (event) => {
                        event.stopPropagation();
                        onKeyUp && onKeyUp(event.which, () => event.preventDefault());
                    }, onclick: () => {
                        onClick && onClick();
                    }, onpointerenter: () => {
                        onOver && onOver();
                    }, onpointerleave: () => {
                        onOut && onOut();
                    } })),
                trailing)),
        tsx(HelperText, { text: computedHelperText, valid: valid, classes: classes, theme: themeProp, variant: variant })));
});
const addonFactory = create({
    theme
}).properties();
export const Addon = addonFactory(function Addon({ middleware: { theme }, properties, children }) {
    const themeCss = theme.classes(css);
    const { filled } = properties();
    return (tsx("span", { classes: [themeCss.addonRoot, filled ? themeCss.addonFilled : null] }, children()));
});
export default TextInput;

/*# sourceMappingURL=index.mjs.map*/