import { create, tsx } from '@dojo/framework/core/vdom';
import Label from '../label/index';
import { formatAriaProperties, isRenderResult } from '../common/util';
import * as css from '../theme/default/text-area.m.css';
import * as labelCss from '../theme/default/label.m.css';
import HelperText from '../helper-text/index';
import { createICacheMiddleware } from '@dojo/framework/core/middleware/icache';
import theme from '../middleware/theme';
import focus from '@dojo/framework/core/middleware/focus';
import validity from '@dojo/framework/core/middleware/validity';
const factory = create({
    icache: createICacheMiddleware(),
    theme,
    focus,
    validity
})
    .properties()
    .children();
export const TextArea = factory(function TextArea({ id, middleware: { icache, theme, focus, validity }, properties, children }) {
    const themeCss = theme.classes(css);
    function callOnValidate(valid, message) {
        let { valid: previousValid, onValidate } = properties();
        let previousMessage;
        if (typeof previousValid === 'object') {
            previousMessage = previousValid.message;
            previousValid = previousValid.valid;
        }
        if (valid !== previousValid || message !== previousMessage) {
            onValidate && onValidate(valid, message);
        }
    }
    function validate() {
        const { customValidator, value = icache.get('value') || '' } = properties();
        const dirty = icache.getOrSet('dirty', false);
        if (value === '' && !dirty) {
            callOnValidate(undefined, '');
            return;
        }
        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);
    }
    function getValidity() {
        const { valid = { valid: undefined, message: undefined } } = properties();
        if (typeof valid === 'boolean') {
            return { valid, message: undefined };
        }
        return {
            valid: valid.valid,
            message: valid.message
        };
    }
    const { aria = {}, columns = 20, disabled, widgetId = `textarea-${id}`, maxLength, minLength, name, placeholder, readOnly, required, rows = 2, initialValue, wrapText, theme: themeProp, classes, labelHidden, helperText, onValidate, variant } = properties();
    let { value } = properties();
    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;
        }
    }
    onValidate && validate();
    const { valid, message } = getValidity();
    const computedHelperText = (valid === false && message) || helperText;
    const inputFocused = focus.isFocused('input');
    const [labelChild] = children();
    const label = isRenderResult(labelChild) ? labelChild : labelChild.label;
    return (tsx("div", { key: "root", classes: [theme.variant(), themeCss.root] },
        tsx("div", { key: "wrapper", classes: [
                themeCss.wrapper,
                disabled ? themeCss.disabled : null,
                valid === false ? themeCss.invalid : null,
                valid === true ? themeCss.valid : null,
                readOnly ? themeCss.readonly : null,
                required ? themeCss.required : null,
                inputFocused ? themeCss.focused : null
            ] },
            label ? (tsx(Label, { theme: theme.compose(labelCss, css, 'label'), classes: classes, variant: variant, disabled: disabled, valid: valid, readOnly: readOnly, required: required, hidden: labelHidden, forId: widgetId, focused: inputFocused, active: !!value || inputFocused }, label)) : null,
            tsx("div", { classes: themeCss.inputWrapper },
                tsx("textarea", Object.assign({ id: widgetId, key: "input" }, formatAriaProperties(aria), { classes: themeCss.input, cols: columns, disabled: disabled, focus: focus.shouldFocus, "aria-invalid": valid === false ? 'true' : undefined, maxlength: maxLength ? `${maxLength}` : null, minlength: minLength ? `${minLength}` : null, name: name, placeholder: placeholder, readOnly: readOnly, "aria-readonly": readOnly ? 'true' : undefined, required: required, rows: rows, value: value, wrap: wrapText, onblur: () => {
                        const { onBlur } = properties();
                        onBlur && onBlur();
                    }, onfocus: () => {
                        const { onFocus } = properties();
                        onFocus && onFocus();
                    }, oninput: (event) => {
                        const { onValue } = properties();
                        event.stopPropagation();
                        const value = event.target.value;
                        icache.set('value', value);
                        onValue && onValue(value);
                    }, onkeydown: (event) => {
                        const { onKeyDown } = properties();
                        event.stopPropagation();
                        onKeyDown &&
                            onKeyDown(event.which, () => {
                                event.preventDefault();
                            });
                    }, onkeyup: (event) => {
                        const { onKeyUp } = properties();
                        event.stopPropagation();
                        onKeyUp &&
                            onKeyUp(event.which, () => {
                                event.preventDefault();
                            });
                    }, onclick: () => {
                        const { onClick } = properties();
                        onClick && onClick();
                    }, onpointerenter: () => {
                        const { onOver } = properties();
                        onOver && onOver();
                    }, onpointerleave: () => {
                        const { onOut } = properties();
                        onOut && onOut();
                    } })))),
        tsx(HelperText, { text: computedHelperText, valid: valid, classes: classes, theme: themeProp, variant: variant })));
});
export default TextArea;

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