/**
 * @license MIT
 * author: Cube Dev Team
 * @cube-dev/ui-kit v0.0.0-canary-e980ce7
 * Released under the MIT license.
 */

import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { createFocusableRef } from '@react-spectrum/utils';
import { cloneElement, forwardRef, useImperativeHandle, useMemo, useRef, } from 'react';
import { useHover } from 'react-aria';
import { LoadingIcon } from '../../../icons/index.js';
import { useProviderProps } from '../../../provider.js';
import { BLOCK_STYLES, extractStyles, OUTER_STYLES, tasty, } from '../../../tasty/index.js';
import { mergeProps, useCombinedRefs } from '../../../utils/react/index.js';
import { useFocus } from '../../../utils/react/interactions.js';
import { useFieldProps, useFormProps, wrapWithField } from '../../form/index.js';
import { InvalidIcon } from '../../shared/InvalidIcon.js';
import { ValidIcon } from '../../shared/ValidIcon.js';
const ADD_STYLES = {
    $: '>',
    display: 'grid',
    placeContent: 'stretch',
    placeItems: 'center',
    gridRows: '1sf',
    flow: 'column',
    gap: 0,
    cursor: 'inherit',
    opacity: {
        '': 1,
        disabled: '$disabled-opacity',
    },
};
export const INPUT_WRAPPER_STYLES = {
    display: 'grid',
    flow: 'row',
    position: 'relative',
    gridColumns: {
        '': '1sf',
        prefix: 'max-content 1sf',
        suffix: '1sf max-content',
        'prefix & suffix': 'max-content 1sf max-content',
    },
    gridRows: '1sf',
    placeItems: 'stretch',
    fill: {
        '': '#white',
        disabled: '#dark.04',
    },
    border: {
        '': true,
        valid: '#success-text.50',
        invalid: '#danger-text.50',
        focused: '#primary-text',
        'valid & focused': '#success-text',
        'invalid & focused': '#danger-text',
        disabled: true,
    },
    preset: 't3',
    radius: true,
    cursor: 'text',
    color: {
        '': '#dark-02',
        focused: '#dark-02',
        invalid: '#danger-text',
        disabled: '#dark.30',
    },
    zIndex: {
        '': 'initial',
        focused: 1,
    },
    boxSizing: 'border-box',
    transition: 'theme',
    backgroundClip: 'content-box',
    height: {
        '': '$size $size',
        multiline: 'min $size',
    },
    $size: {
        '': '$size-md',
        'size=small': '$size-sm',
        'size=medium': '$size-md',
        'size=large': '$size-lg',
    },
    Prefix: ADD_STYLES,
    Suffix: ADD_STYLES,
    State: {
        $: '> Suffix >',
        display: 'flex',
    },
    InputIcon: {
        display: 'grid',
        placeItems: 'center',
        width: 'min $size-sm',
        color: 'inherit',
        fontSize: '$icon-size',
    },
    ValidationIcon: {
        $: '> Suffix > State >',
        display: 'grid',
        placeItems: 'center',
        width: {
            '': 'min $size-sm',
            suffix: 'min $size-xs',
        },
        fontSize: '$icon-size',
    },
};
const InputWrapperElement = tasty({
    qa: 'InputWrapper',
    styles: INPUT_WRAPPER_STYLES,
});
const INPUT_STYLE_PROPS_LIST = [...BLOCK_STYLES, 'resize'];
export const DEFAULT_INPUT_STYLES = {
    placeSelf: 'stretch',
    width: 'initial 100% 100%',
    color: 'inherit',
    fill: '#clear',
    border: 0,
    transition: 'theme',
    radius: true,
    padding: '$vertical-padding $right-padding $vertical-padding $left-padding',
    textAlign: 'left',
    reset: 'input',
    preset: 't3',
    flexGrow: 1,
    margin: {
        '': 0,
        multiline: '((($size-md - 1lh) / 2) - 1bw) 0',
        'multiline & size=small': '((($size-sm - 1lh) / 2) - 1bw) 0',
        'multiline & size=large': '((($size-lg - 1lh) / 2) - 1bw) 0',
    },
    resize: 'none',
    boxSizing: 'border-box',
    userSelect: 'auto',
    outline: 0,
    '$vertical-padding': 0,
    '$left-padding': {
        '': '(1x - 1bw)',
        'size=small': '(1x - 1bw)',
        'size=large': '(1.25x - 1bw)',
        'size=xlarge': '(1.5x - 1bw)',
        prefix: '0',
    },
    '$right-padding': {
        '': '(1x - 1bw)',
        'size=small': '(1x - 1bw)',
        'size=large': '(1.25x - 1bw)',
        'size=xlarge': '(1.5x - 1bw)',
        suffix: '0',
    },
};
const InputElement = tasty({ qa: 'Input', styles: DEFAULT_INPUT_STYLES });
function _TextInputBase(props, ref) {
    props = useProviderProps(props);
    props = useFormProps(props);
    props = useFieldProps(props, {
        defaultValidationTrigger: 'onBlur',
        valuePropsMapper: ({ value, onChange }) => ({
            value: typeof value === 'string' || typeof value === 'number'
                ? String(value)
                : '',
            onChange,
        }),
    });
    let { qa, mods, validationState, prefix, isDisabled, multiLine, autoFocus, inputProps, wrapperProps, inputRef, isLoading, loadingIndicator, value, inputStyles = {}, suffix, suffixPosition = 'before', wrapperRef, tooltip, rows = 1, size = 'medium', autocomplete, icon, maxLength, minLength, form, ...otherProps } = props;
    let styles = extractStyles(otherProps, OUTER_STYLES);
    let type = otherProps.type;
    inputStyles = extractStyles(otherProps, INPUT_STYLE_PROPS_LIST, inputStyles, undefined, ['styles']);
    let ElementType = multiLine ? 'textarea' : 'input';
    let { isFocused, focusProps } = useFocus({ isDisabled });
    let { hoverProps, isHovered } = useHover({ isDisabled });
    let domRef = useRef(null);
    inputRef = useCombinedRefs(inputRef);
    // Expose imperative interface for ref
    useImperativeHandle(ref, () => ({
        ...createFocusableRef(domRef, inputRef),
        select() {
            if (inputRef?.current) {
                inputRef.current.select();
            }
        },
        getInputElement() {
            return inputRef?.current;
        },
    }));
    let isInvalid = validationState === 'invalid';
    let validationIcon = isInvalid ? InvalidIcon : ValidIcon;
    let validation = cloneElement(validationIcon);
    // Fix safari bug: https://github.com/philipwalton/flexbugs/issues/270
    if (!inputProps?.placeholder) {
        if (!inputProps) {
            inputProps = {};
        }
        inputProps.placeholder = ' ';
    }
    if (icon) {
        icon = _jsx("div", { "data-element": "InputIcon", children: icon });
        if (prefix) {
            prefix = (_jsxs(_Fragment, { children: [icon, prefix] }));
        }
        else {
            prefix = icon;
        }
    }
    const modifiers = useMemo(() => ({
        invalid: isInvalid,
        valid: validationState === 'valid',
        loadable: !!loadingIndicator,
        focused: isFocused,
        hovered: isHovered,
        disabled: isDisabled,
        multiline: multiLine,
        prefix: !!prefix,
        suffix: (validationState && !isLoading) || isLoading || !!suffix,
        ...mods,
    }), [
        mods,
        isInvalid,
        validationState,
        loadingIndicator,
        isFocused,
        isDisabled,
        isHovered,
        multiLine,
        prefix,
        suffix,
    ]);
    const hasTextSecurity = multiLine && type === 'password';
    const textSecurityStyles = hasTextSecurity && inputProps.value?.length
        ? {
            fontFamily: 'text-security-disc',
        }
        : {};
    const textField = (_jsxs(InputWrapperElement, { ref: wrapperRef, mods: modifiers, "data-size": size, styles: styles, ...wrapperProps, children: [prefix ? _jsx("div", { "data-element": "Prefix", children: prefix }) : null, _jsx(InputElement, { qa: qa || 'Input', as: ElementType, "data-input-type": "textinput", ...mergeProps(inputProps, focusProps, hoverProps), ref: inputRef, rows: multiLine ? rows : undefined, mods: modifiers, style: textSecurityStyles, "data-autofocus": autoFocus ? '' : undefined, autoFocus: autoFocus, "data-size": size, autoComplete: autocomplete, styles: inputStyles, disabled: !!isDisabled, maxLength: maxLength, minLength: minLength }), (validationState && !isLoading) || isLoading || suffix ? (_jsxs("div", { "data-element": "Suffix", children: [suffixPosition === 'before' ? suffix : null, (validationState && !isLoading) || isLoading ? (_jsxs("div", { "data-element": "State", children: [validationState && !isLoading ? validation : null, isLoading && _jsx(LoadingIcon, { "data-element": "InputIcon" })] })) : null, suffixPosition === 'after' ? suffix : null] })) : null] }));
    return wrapWithField(textField, domRef, {
        ...props,
        form: undefined,
    });
}
const TextInputBase = forwardRef(_TextInputBase);
export { TextInputBase };

        