// Type definitions for sandstone/Input

import { ChangeableProps as ui_Changeable_ChangeableProps } from "@enact/ui/Changeable";
import { SkinnableProps as sandstone_Skinnable_SkinnableProps } from "@enact/sandstone/Skinnable";
import { ToggleableProps as ui_Toggleable_ToggleableProps } from "@enact/ui/Toggleable";
import * as React from "react";
import { SpottableProps as spotlight_Spottable_SpottableProps } from "@enact/spotlight/Spottable";

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

export interface InputFieldBaseProps {
  /**
   * Passed by AnnounceDecorator for accessibility.
   */
  announce?: Function;
  /**
   * Disables InputField and becomes non-interactive.
   */
  disabled?: boolean;
  /**
   * Blurs the input when the "enter" key is pressed.
   */
  dismissOnEnter?: boolean;
  /**
   * The icon to be placed at the end of the input.
   */
  iconAfter?: string;
  /**
   * The icon to be placed at the beginning of the input.
   */
  iconBefore?: string;
  /**
 * Indicates    is invalid and shows
  , if set.
 */
  invalid?: boolean;
  /**
 * The tooltip text to be displayed when the input is
  .
 * 
 * If this value is  _falsy_ , the tooltip will be shown with the default message.
 */
  invalidMessage?: string;
  /**
   * Called before the input value is changed.
   *
   * The change can be prevented by calling  `preventDefault`  on the event.
   */
  onBeforeChange?: Function;
  /**
   * Called when blurred.
   */
  onBlur?: Function;
  /**
 * Called when the input value is changed.
 * 
 * The event payload includes the current  `value`  as well as a  `stopPropagation()`  method
which may be called to stop the original  `onChange`  event from the  `<input>`  from
bubbling.
 */
  onChange?: Function;
  /**
   * Called when clicked.
   */
  onClick?: Function;
  /**
   * Called when focused.
   */
  onFocus?: Function;
  /**
   * Called when a key is pressed down.
   */
  onKeyDown?: Function;
  /**
   * Text to display when    is not set.
   */
  placeholder?: string;
  /**
   * The size of the input field.
   */
  size?: "large" | "small";
  /**
   * The type of input.
   *
   * Accepted values correspond to the standard HTML5 input types.
   */
  type?: string;
  /**
   * The value of the input.
   */
  value?: string | number;
}
/**
 * A Sandstone styled input component.
 * 
 * It supports start and end icons but it does not support Spotlight. Apps should use
  .
 */

export class InputFieldBase extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputFieldBaseProps>
> {}

export interface InputPopupBaseProps {
  /**
   * Passed by AnnounceDecorator for accessibility.
   */
  announce?: object;
  /**
   * Sets the hint string read when focusing the back button.
   */
  backButtonAriaLabel?: string;
  /**
   * Customize component style
   */
  css?: object;
  /**
   * Initial value of the input.
   *
   * This value is used for setting the  `defaultValue`  of the  `InputField` .
   */
  defaultValue?: string | number;
  /**
   * Disables the input popup.
   */
  disabled?: boolean;
  /**
   * Sets spotlightId to InputField.
   */
  inputFieldSpotlightId?: string;
  /**
 * Indicates the value is invalid and shows
  , if set.
 */
  invalid?: boolean;
  /**
 * The tooltip text to be displayed when the input is
  .
 * 
 * If this value is  _falsy_ , the tooltip will be shown with the default message.
 */
  invalidMessage?: string;
  /**
 * Set the length of number input field.
 * 
 * Sets the amount of numbers this field will collect. Any number between 1 and 6
(inclusive) will render individual number cells, greater than 6 will render a single box
with numbers in it. This only has an effect on  `'number'`  and  `'passwordnumber'`   `type` 
and when  `numberInputField`  is  `'auto'` .
 * 
 * This value will override  `minLength`  and  `maxLength` .
 */
  length?: number;
  /**
   * The maximum length of number input fields.
   *
   * Overridden by  `length`  value.
   */
  maxLength?: number;
  /**
 * The minimum length of number input fields.
 * 
 * Overridden by  `length`  value.
 * 
 * When smaller than  `maxLength` , number type inputs will show a submit button and will not
auto-submit when the length reaches  `maxLength` . Defaults to the  `maxLength`  value.
 */
  minLength?: number;
  /**
   * Omits the back button.
   */
  noBackButton?: boolean;
  /**
   * Omits the submit button.
   */
  noSubmitButton?: boolean;
  /**
 * The type of numeric input to use.
 * 
 * The default is to display separated digits when  `length`  is less than  `7` . If  `field`  is
set, a standard  `InputField`  will be used instead of the normal number input.
 * 
 * This has no effect on other   .
 */
  numberInputField?: "auto" | "separated" | "joined" | "field";
  /**
   * Called before the input value is changed.
   *
   * The change can be prevented by calling  `preventDefault`  on the event.
   */
  onBeforeChange?: Function;
  /**
   * Called when the input value is changed.
   */
  onChange?: Function;
  /**
   * Called when the popup is closed.
   */
  onClose?: Function;
  /**
   * Called when input is complete.
   */
  onComplete?: Function;
  /**
   * Called when the popup is opened.
   */
  onOpenPopup?: Function;
  /**
   * Opens the popup.
   */
  open?: boolean;
  /**
   * Text displayed when value is not set.
   */
  placeholder?: string;
  /**
   * The "aria-label" for the popup when opened.
   */
  popupAriaLabel?: string;
  /**
   * Type of popup.
   */
  popupType?: "fullscreen" | "overlay";
  /**
   * Size of the input field.
   */
  size?: "large" | "small";
  /**
   * Subtitle below the title of popup.
   */
  subtitle?: string;
  /**
   * Title text of popup.
   */
  title?: string;
  /**
   * Type of the input.
   */
  type?:
    | "text"
    | "password"
    | "number"
    | "passwordnumber"
    | "url"
    | "tel"
    | "passwordtel";
  /**
   * Initial value of the input.
   *
   * This value is used for setting the  `defaultValue`  of the  `InputField` .
   */
  value?: string | number;
}
/**
 * Base component for providing text input in the form of a popup without button.
 */

export class InputPopupBase extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputPopupBaseProps>
> {}

export interface InputFieldDecoratorProps
  extends Merge<
    ui_Changeable_ChangeableProps,
    sandstone_Skinnable_SkinnableProps
  > {}
export function InputFieldDecorator<P>(
  Component: React.ComponentType<P> | string,
): React.ComponentType<P & InputFieldDecoratorProps>;

export interface InputFieldProps
  extends Merge<
    Merge<
      Merge<InputFieldBaseProps, ui_Changeable_ChangeableProps>,
      spotlight_Spottable_SpottableProps
    >,
    sandstone_Skinnable_SkinnableProps
  > {
  /**
 * Focuses the internal input when the component gains 5-way focus.
 * 
 * By default, the internal input is not editable when the component is focused via 5-way and must
be selected to become interactive. In pointer mode, the input will be editable when clicked.
 */
  autoFocus?: boolean;
  /**
   * Applies a disabled style and prevents interacting with the component.
   */
  disabled?: boolean;
  /**
   * Sets the initial value.
   */
  defaultValue?: string;
  /**
   * Blurs the input when the "enter" key is pressed.
   */
  dismissOnEnter?: boolean;
  /**
   * Called when the internal input is focused.
   */
  onActivate?: Function;
  /**
   * Called when the internal input loses focus.
   */
  onDeactivate?: Function;
  /**
   * Called when the component is removed when it had focus.
   */
  onSpotlightDisappear?: Function;
  /**
   * Disables spotlight navigation into the component.
   */
  spotlightDisabled?: boolean;
}
/**
 * A Spottable, Sandstone styled input component with embedded icon support.
 * 
 * By default,  `InputField`  maintains the state of its  `value`  property. Supply the  `defaultValue` 
property to control its initial value. If you wish to directly control updates to the component,
supply a value to  `value`  at creation time and update it in response to  `onChange`  events.
 */

export class InputField extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputFieldProps>
> {}

export interface InputBaseProps {
  /**
   * Disables the button that activates the input popup.
   */
  disabled?: boolean;
  /**
   * Text displayed when value is not set.
   */
  placeholder?: string;
  /**
   * The size of the input field.
   */
  size?: "large" | "small";
  /**
   * Type of the input.
   */
  type?:
    | "text"
    | "password"
    | "number"
    | "passwordnumber"
    | "url"
    | "tel"
    | "passwordtel";
  /**
   * The value of the input.
   */
  value?: string | number;
}
/**
 * Base component for providing text input in the form of a popup.
 */

export class InputBase extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputBaseProps>
> {}

export interface InputDecoratorProps
  extends Merge<
    Merge<ui_Toggleable_ToggleableProps, ui_Changeable_ChangeableProps>,
    sandstone_Skinnable_SkinnableProps
  > {}
export function InputDecorator<P>(
  Component: React.ComponentType<P> | string,
): React.ComponentType<P & InputDecoratorProps>;

export interface InputProps extends InputBaseProps {}
/**
 * Provides an input in the form of a popup.
 * 
 * Usage:
 * ```
<Input
  onComplete={this.handleInputComplete}
  placeholder="Placeholder"
  subtitle="TitleBelow"
  title="Title"
/>
```
 
 * By default,  `Input`  maintains the state of its  `value`  property. Supply the  `defaultValue` 
property to control its initial value. If you wish to directly control updates to the
component, supply a value to  `value`  at creation time and update it in response to  `onChange` 
events.
 */

export class Input extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputProps>
> {}

export interface InputPopupProps extends InputPopupBaseProps {}
/**
 * Provides an input popup without button.
 * 
 * Usage:
 * ```
<InputPopup
  open={this.state.open}
  onComplete={this.handleInputPopupComplete}
  placeholder="Placeholder"
  subtitle="Subtitle"
  title="Title"
/>
```
 
 * By default,  `InputPopup`  maintains the state of its  `value`  property. Supply the  `defaultValue` 
property to control its initial value. If you wish to directly control updates to the
component, supply a value to  `value`  at creation time and update it in response to  `onChange` 
events.
 */

export class InputPopup extends React.Component<
  Merge<React.HTMLProps<HTMLElement>, InputPopupProps>
> {}

export default Input;
