import type { Snippet } from 'svelte';
import type { HTMLInputAttributes, HTMLSelectAttributes, HTMLTextareaAttributes } from 'svelte/elements';
import type { NeoAffixProps } from './neo-affix.model.js';
import type { NeoInputValidationProps } from './neo-input-validation.model.js';
import type { NeoLabelProps } from './neo-label.model.js';
import type { NeoValidationFieldContext, NeoValidationProps, NeoValidationState } from './neo-validation.model.js';
import type { HTMLTransitionProps, HTMLUseProps } from '../../utils/action.utils.js';
import type { BorderRadiusInput } from '../../utils/border.utils.js';
import type { Color } from '../../utils/colors.utils.js';
import type { HTMLNeoBaseElement, HTMLRefProps, HTMLTagProps, SvelteEvent } from '../../utils/html-element.utils.js';
import type { BlurElevation, BlurElevationString, ShadowElevation, ShadowElevationString, ShadowHoverElevation, ShadowHoverElevationsString } from '../../utils/shadow.utils.js';
import type { SizeInput } from '../../utils/style.utils.js';
export type NeoInputValue<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> = T extends HTMLTextAreaElement ? HTMLTextareaAttributes['value'] : T extends HTMLSelectElement ? HTMLSelectAttributes['value'] : HTMLInputAttributes['value'] | HTMLInputAttributes['checked'] | HTMLInputAttributes['bind:files'];
type NeoInputHTMLAttributes<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> = T extends HTMLTextAreaElement ? HTMLTextareaAttributes : T extends HTMLSelectElement ? HTMLSelectAttributes & {
    type?: 'select';
} : HTMLInputAttributes & {
    files?: HTMLInputAttributes['bind:files'];
    group?: HTMLInputAttributes['bind:group'];
};
export type NeoInputState<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> = NeoValidationState<NeoInputValue<T>>;
export interface NeoInputStyles {
    /**
     * Input elevation.
     * @default 3
     */
    elevation?: NeoInputElevation;
    /**
     * Whether to increase/decrease the elevation when hovered/focused.
     * @default 0
     */
    hover?: NeoInputHoverElevation;
    /**
     * The blur level to apply when in glass mode.
     *
     * @default elevation, min: 1, max: 5
     * @see glass
     */
    blur?: NeoInputBlur;
    /**
     * If true, negative elevation (< 0) will be displayed as pressed instead of inset.
     */
    pressed?: boolean;
    /**
     * By default, inputs with no elevation will display a border.
     * If this is `true`, the input will never display a border.
     */
    borderless?: boolean;
    /**
     * If true, the input will have a rounded border.
     */
    rounded?: BorderRadiusInput;
    /**
     * If true, the input will be displayed with a glass effect.
     */
    glass?: boolean;
    /**
     * Tints the input with the current color.
     */
    tinted?: boolean;
    /**
     * Text color to use for the input.
     */
    color?: Color | CSSStyleDeclaration['color'];
    /**
     * If true, the input input start as flat on first render.
     * @see [@starting-style](https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-style) for browser support
     */
    start?: boolean;
    /**
     * If true, the input will be disabled and a loading skeleton will be displayed instead of the text.
     */
    skeleton?: boolean;
    /**
     * If true, the input will be disabled.
     */
    disabled?: boolean;
    /**
     * If true, the input will be readonly.
     */
    readonly?: boolean;
}
export interface NeoInputMethods<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> {
    /**
     * Change the input state. If no value is provided, the state attributes will be unchanged.
     * @param state
     */
    mark: (state: NeoInputState<T>) => unknown;
    /**
     * Clear the input. If a state is provided, the input state will be updated accordingly.
     * If a partial state is provided, the input state will be reinitialized and the provided state will be merged.
     *
     * Note: Clearing the input will trigger `onclear` and `oninput` events, but not `onchange`.
     * @param state
     * @param event
     */
    clear: (state?: NeoInputState<T>, event?: InputEvent | SvelteEvent<InputEvent>) => Promise<unknown>;
    /**
     * Change the input value.
     * @param value
     * @param event
     */
    change: (value: NeoInputValue<T>, event?: InputEvent | SvelteEvent<InputEvent>) => Promise<NeoInputState<T>>;
    /**
     * Check the input validity.
     * @param update whether to check the input dirty and/or valid state.
     * @param update.dirty whether to mark the input dirty
     * @param update.valid whether to force a valid state
     */
    validate: (update?: {
        dirty?: boolean;
        valid?: boolean;
    }) => NeoInputState<T>;
}
export type NeoInputBlur = BlurElevation | BlurElevationString;
export type NeoInputElevation = ShadowElevation | ShadowElevationString;
export type NeoInputHoverElevation = ShadowHoverElevation | ShadowHoverElevationsString;
export type NeoInputContext<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> = NeoValidationFieldContext<T, NeoInputValue<T>> & Partial<NeoInputStyles & NeoInputMethods<T>>;
export declare const NeoInputLabelPlacement: {
    readonly Inside: "inside";
    readonly Top: "top";
    readonly Left: "left";
    readonly Right: "right";
};
export type NeoInputLabelPlacements = (typeof NeoInputLabelPlacement)[keyof typeof NeoInputLabelPlacement];
export type NeoBaseInputProps<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement = NeoInputHTMLElement> = {
    /**
     * A snippet to display as the input children.
     */
    children?: Snippet;
    /**
     * A snippet to display as the input display value.
     *
     * @note: This will hide the input (hidden & display: none) and might impact accessibility or form submission.
     */
    display?: Snippet<[NeoInputState<T>]> | string;
    /**
     * Will apply a display: none style to the input.
     */
    hide?: boolean;
    /**
     * If `true`, the input will have no left padding/border radius.
     */
    after?: boolean;
    /**
     * If `true`, the input will have no right padding/border radius.
     */
    before?: boolean;
    /**
     * If the input is currently focused.
     */
    focused?: boolean;
    /**
     * If false, and a default value is provided, the input will be set to the default value when cleared.
     *
     * Note: This does not apply to checkboxes, radios, and file inputs.
     *
     * @default true
     */
    nullable?: boolean;
    /**
     * Fall back value when the input value is cleared.
     */
    defaultValue?: HTMLInputAttributes['value'];
    /**
     * Fall back checked state when the input value is cleared.
     */
    defaultChecked?: HTMLInputAttributes['checked'];
    /**
     * Optional flex strategy for the container
     */
    flex?: CSSStyleDeclaration['flex'];
    /**
     * Optional width constraints.
     */
    width?: SizeInput<'width'>;
    /**
     * Optional height constraints.
     */
    height?: SizeInput<'height'>;
    /**
     * If true, the input will adjust its size to fit the content.
     *
     * @see [field-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/field-sizing) for browser support
     */
    fitContent?: boolean;
    /**
     * If `true`, the input dirty state will update on input events.
     * If `false`, the input dirty state will only update on change events.
     * @default false
     */
    dirtyOnInput?: boolean;
    /**
     * If `true`, the input dirty state will update on blur events.
     * @default false
     */
    dirtyOnBlur?: boolean;
    /**
     * If `true`, the input will check for validity on input events.
     * If `false`, the input will only check for validity on change events.
     * @default false
     */
    validateOnInput?: boolean;
    /**
     * If `true`, the input will check for validity on blur events.
     * @default false
     */
    validateOnBlur?: boolean;
    /**
     * Reflect the input validation message.
     */
    validationMessage?: T['validationMessage'];
    /**
     * Callback when the input state is manually changed.
     * @param state
     */
    onmark?: (state: NeoInputState<T>) => unknown;
    /**
     * Callback when the input is cleared.
     * @param state
     * @param event
     */
    onclear?: (state: NeoInputState<T>, event?: InputEvent) => unknown;
    /**
     * The props to pass to the input display wrapper.
     */
    displayProps?: HTMLNeoBaseElement & HTMLTagProps;
} & HTMLUseProps & HTMLRefProps<T> & NeoInputState<T> & NeoInputHTMLAttributes<T>;
export type NeoInputGroupProps<T extends HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement> = {
    /**
     * A snippet or a string to display as the input label.
     */
    label?: Snippet<[NeoInputContext<T>]> | string;
    /**
     * A snippet or a string to display as the input info message.
     */
    message?: Snippet<[NeoInputContext<T>]> | string;
    /**
     * A snippet or a string to display as the input error message.
     */
    error?: Snippet<[NeoInputContext<T>]> | string;
    /**
     * A snippet to display as the input suffix.
     */
    after?: Snippet<[NeoInputContext<T>]>;
    /**
     * Element(s) to render inside the input-group.
     */
    children?: Snippet<[NeoInputContext<T>]>;
    /**
     * Display a loading spinner inside the input.
     * If defined, some space will be reserved for the spinner.
     * Set to `undefined` when not loading to regain the space.
     */
    loading?: boolean;
    /**
     * If the input is currently hovered.
     */
    hovered?: boolean;
    /**
     * Whether the input group has focus (input, affixes or label).
     */
    focusin?: boolean;
    /**
     * Display a clear button to reset the input value.
     * If used in combination with `loading`, the clear button will be hidden while loading.
     * @default false
     */
    clearable?: boolean;
    /**
     * If `true`, the input will display validation states.
     * @default false
     */
    validation?: NeoInputValidationProps<T>['validation'];
    /**
     * If `true`, and `validation` is enabled, the validation state will be displayed with an icon.
     */
    validationIcon?: boolean;
    /**
     * If false, the input will not be registered with the form context.
     */
    register?: NeoInputValidationProps<T>['register'];
    /**
     * If true, the cursor will be set to pointer when hovering the input.
     */
    clickable?: boolean;
    /**
     * Display the label as a placeholder inside the input when empty
     * @default true
     */
    floating?: boolean;
    /**
     * Label placement.
     * When set to outside (`top`, `left`, `right`), the label will be displayed within the input container's margin.
     * Make sure to set the container's margin appropriately to avoid collision or content shift.
     *
     * @default 'inside'
     */
    placement?: NeoInputLabelPlacements;
    /**
     * The ref to bind to the input wrapper (validation).
     */
    validationRef?: HTMLRefProps['ref'];
    /**
     * The props to pass to the validation component.
     */
    validationProps?: NeoInputValidationProps<T>;
    /**
     * The ref to bind to the input container.
     */
    containerRef?: HTMLRefProps['ref'];
    /**
     * The props to pass to the input container.
     */
    containerProps?: HTMLNeoBaseElement & HTMLTagProps;
    /**
     * The props to pass to the message and error components.
     */
    messageProps?: NeoValidationProps<T>['messageProps'];
    /**
     * The props to pass to the suffix.
     */
    afterProps?: HTMLNeoBaseElement & HTMLTagProps;
    /**
     * The ref to bind to the suffix.
     */
    afterRef?: HTMLElement;
    /**
     * The props to pass to the affix.
     */
    affixProps?: NeoAffixProps;
    /**
     * The ref to bind to the affix.
     */
    affixRef?: HTMLElement;
    /**
     * The props to pass to the label.
     */
    labelProps?: NeoLabelProps;
    /**
     * The ref to bind to the label.
     */
    labelRef?: HTMLLabelElement;
} & Omit<NeoBaseInputProps<T>, 'after' | 'before'> & NeoInputStyles & HTMLTransitionProps;
export type NeoInputProps<T extends HTMLInputElement | HTMLSelectElement = NeoInputHTMLElement> = {
    /**
     * A snippet to display as the input prefix.
     */
    before?: Snippet<[NeoInputContext<T>]>;
    /**
     * A snippet to display inside the input group but outside the input.
     * This is meant for internal use only. Elements will not be styled as affixes.
     *
     * Use `before` or `after` for custom affixes.
     *
     * @internal
     */
    inner?: Snippet<[NeoInputContext<T>]>;
    /**
     * Unique identifier of the input.
     * @default neo-input-{uuid}
     */
    id?: HTMLElement['id'];
    /**
     * The props to pass to the prefix.
     */
    beforeProps?: HTMLNeoBaseElement & HTMLTagProps;
    /**
     * The ref to bind to the prefix.
     */
    beforeRef?: HTMLElement;
} & NeoInputGroupProps<T> & HTMLInputAttributes & {
    files?: HTMLInputAttributes['bind:files'];
    group?: HTMLInputAttributes['bind:group'];
};
export interface NeoTextAreaResize {
    /**
     * The minimum number of rows the textarea can have.
     * @default 1
     */
    min?: number;
    /**
     * The maximum number of rows the textarea can have.
     */
    max?: number;
}
export type NeoTextareaProps<T extends HTMLTextAreaElement = NeoTextareaHTMLElement> = {
    /**
     * Fall back value when the textarea value is cleared.
     */
    defaultValue?: HTMLTextareaAttributes['value'];
    /**
     * Overrides the default scrollbars.
     */
    scrollbar?: boolean;
    /**
     * Unique identifier of the textarea.
     * @default neo-textarea-{uuid}
     */
    id?: HTMLElement['id'];
    /**
     * The resize strategy of the textarea.
     */
    resize?: CSSStyleDeclaration['resize'];
    /**
     * Automatically increments/decrements the textarea rows to fit the content.
     *
     * If `true`, the textarea will increment indefinitely and will not decrement.
     * If an object is provided, the textarea will increment up to `max` rows and decrement to `min` rows.
     *
     * @default true
     */
    autoResize?: boolean | NeoTextAreaResize;
} & Omit<NeoInputGroupProps<T>, 'hide' | 'display' | 'displayProps'> & HTMLTextareaAttributes;
export type NeoInputHTMLElement<T extends HTMLInputElement = HTMLInputElement> = T & Partial<NeoInputMethods<T>>;
export type NeoSelectHTMLElement<T extends HTMLSelectElement = HTMLSelectElement> = T & Partial<NeoInputMethods<T>>;
export type NeoTextareaHTMLElement<T extends HTMLTextAreaElement = HTMLTextAreaElement> = T & Partial<NeoInputMethods<T>> & {
    resize?: () => void;
};
export {};
