/**
 * Flowtype definitions for index
 * Generated by Flowgen from a Typescript Definition
 * Flowgen v1.2.0
 * Author: [Joar Wilk](http://twitter.com/joarwilk)
 * Repo: http://github.com/joarwilk/flowgen
 */

import * as React from 'react'

declare module downshift {
  declare type StateChangeTypes = {
    unknown: '__autocomplete_unknown__',
    mouseUp: '__autocomplete_mouseup__',
    itemMouseEnter: '__autocomplete_item_mouseenter__',
    keyDownArrowUp: '__autocomplete_keydown_arrow_up__',
    keyDownArrowDown: '__autocomplete_keydown_arrow_down__',
    keyDownEscape: '__autocomplete_keydown_escape__',
    keyDownEnter: '__autocomplete_keydown_enter__',
    clickItem: '__autocomplete_click_item__',
    blurInput: '__autocomplete_blur_input__',
    changeInput: '__autocomplete_change_input__',
    keyDownSpaceButton: '__autocomplete_keydown_space_button__',
    clickButton: '__autocomplete_click_button__',
    blurButton: '__autocomplete_blur_button__',
    controlledPropUpdatedSelectedItem: '__autocomplete_controlled_prop_updated_selected_item__',
  }
  declare type StateChangeValues =
    | '__autocomplete_unknown__'
    | '__autocomplete_mouseup__'
    | '__autocomplete_item_mouseenter__'
    | '__autocomplete_keydown_arrow_up__'
    | '__autocomplete_keydown_arrow_down__'
    | '__autocomplete_keydown_escape__'
    | '__autocomplete_keydown_enter__'
    | '__autocomplete_click_item__'
    | '__autocomplete_blur_input__'
    | '__autocomplete_change_input__'
    | '__autocomplete_keydown_space_button__'
    | '__autocomplete_click_button__'
    | '__autocomplete_blur_button__'
    | '__autocomplete_controlled_prop_updated_selected_item__'
  declare type Callback = () => void
  declare export interface DownshiftState<Item> {
    highlightedIndex: number | null;
    inputValue: string | null;
    isOpen: boolean;
    selectedItem: Item;
  }
  declare export interface DownshiftProps<Item> {
    defaultSelectedItem?: Item;
    defaultHighlightedIndex?: number | null;
    defaultInputValue?: string;
    defaultIsOpen?: boolean;
    itemToString?: (item: Item) => string;
    selectedItemChanged?: (prevItem: Item, item: Item) => boolean;
    getA11yStatusMessage?: (options: A11yStatusMessageOptions<Item>) => string;
    onChange?: (
      selectedItem: Item,
      stateAndHelpers: ControllerStateAndHelpers<Item>,
    ) => void;
    onSelect?: (
      selectedItem: Item,
      stateAndHelpers: ControllerStateAndHelpers<Item>,
    ) => void;
    onStateChange?: (
      options: StateChangeOptions<Item>,
      stateAndHelpers: ControllerStateAndHelpers<Item>,
    ) => void;
    onInputValueChange?: (
      inputValue: string,
      stateAndHelpers: ControllerStateAndHelpers<Item>,
    ) => void;
    stateReducer?: (
      state: DownshiftState<Item>,
      changes: StateChangeOptions<Item>,
    ) => StateChangeOptions<Item>;
    itemCount?: number;
    highlightedIndex?: number;
    inputValue?: string;
    isOpen?: boolean;
    selectedItem?: Item;
    children: ChildrenFunction<Item>;
    id?: string;
    environment?: Environment;
    onOuterClick?: () => void;
    onUserAction?: (
      options: StateChangeOptions<Item>,
      stateAndHelpers: ControllerStateAndHelpers<Item>,
    ) => void;
  }
  declare export interface Environment {
    addEventListener: typeof window.addEventListener;
    removeEventListener: typeof window.removeEventListener;
    document: Document;
  }
  declare export interface A11yStatusMessageOptions<Item> {
    highlightedIndex: number | null;
    inputValue: string;
    isOpen: boolean;
    itemToString: (item: Item) => string;
    previousResultCount: number;
    resultCount: number;
    selectedItem: Item;
  }
  declare export interface StateChangeOptions<Item> {
    type: StateChangeValues;
    highlightedIndex: number;
    inputValue: string;
    isOpen: boolean;
    selectedItem: Item;
  }
  declare export type StateChangeFunction<Item> = (
    state: DownshiftState<Item>,
  ) => StateChangeOptions<Item>

  declare export type GetRootPropsReturn = {
    role: 'combobox';
    'aria-expanded': boolean;
    'aria-haspopup': 'listbox';
    'aria-owns': string | null;
    'aria-labelledby': string;
  }
  declare export interface GetRootPropsOptions {
    refKey: string;
  }

  declare type GetToggleButtonCallbacks = {
    onMouseMove: (e: SyntheticEvent<Element>) => void;
    onMouseDown: (e: SyntheticEvent<Element>) => void;
    onBlur: (e: SyntheticEvent<Element>) => void;
  } | {
    onPress: (e: SyntheticEvent<Element>) => void; // should be react native type
  } | {}
  declare export type GetToggleButtonReturn = {
    type: 'button';
    role: 'button';
    'aria-label': 'close menu' | 'open menu';
    'aria-haspopup': true;
    'data-toggle': true;
  } & GetInputPropsCallbacks
  declare export interface getToggleButtonPropsOptions
    extends React.HTMLProps<HTMLButtonElement> {}

  declare export interface GetLabelPropsReturn {
    htmlFor: string;
    id: string;
  }
  declare export interface GetLabelPropsOptions
    extends React.HTMLProps<HTMLLabelElement> {}

  declare export type getMenuPropsReturn = {
    role: 'listbox';
    'aria-labelledby': string | null;
    id: string;
  }

  declare type GetInputPropsCallbacks = ({
    onKeyDown: (e: SyntheticEvent<Element>) => void;
    onBlur: (e: SyntheticEvent<Element>) => void;
  } & ({
    onInput: (e: SyntheticEvent<Element>) => void;
  } | {
    onChangeText: (e: SyntheticEvent<Element>) => void;
  } | {
    onChange: (e: SyntheticEvent<Element>) => void;
  })) | {}
  declare export type GetInputPropsReturn = {
    'aria-autocomplete': 'list';
    'aria-activedescendant': string | null;
    'aria-controls': string | null;
    'aria-labelledby': string;
    autoComplete: 'off';
    value: string;
    id: string;
  } & GetInputPropsCallbacks;
  declare export interface GetInputPropsOptions
    extends React.HTMLProps<HTMLInputElement> {}

  declare type GetItemPropsCallbacks = {
    onMouseMove: (e: SyntheticEvent<Element>) => void;
    onMouseDown: (e: SyntheticEvent<Element>) => void;
  } & ({
    onPress: (e: SyntheticEvent<Element>) => void;
  } | {
    onClick: (e: SyntheticEvent<Element>) => void;
  })
  declare export type GetItemPropsReturn = {
    id: string;
    role: 'option';
    'aria-selected': boolean;
  } & GetItemPropsCallbacks
  declare export type GetItemPropsOptions<Item> = {
    index?: number,
    item: Item,
  }

  declare export interface PropGetters<Item> {
    getRootProps: <T:{}>(options: GetRootPropsOptions & T) => GetRootPropsReturn & T;
    getButtonProps: <T:{}>(options?: getToggleButtonPropsOptions & T) => GetToggleButtonReturn & T;
    getToggleButtonProps: <T:{}>(options?: getToggleButtonPropsOptions & T) => GetToggleButtonReturn & T;
    getLabelProps: <T:{}>(options?: GetLabelPropsOptions & T) => GetLabelPropsReturn & T;
    getMenuProps: <T:{}>(options?: T) => getMenuPropsReturn & T;
    getInputProps: <T:{}>(options?: GetInputPropsOptions & T) => GetInputPropsReturn & T;
    getItemProps: <T:{}>(options: GetItemPropsOptions<Item> & T) => GetItemPropsReturn & T;
  }
  declare export interface Actions<Item> {
    reset: (otherStateToSet?: {}, cb?: Callback) => void;
    openMenu: (cb?: Callback) => void;
    closeMenu: (cb?: Callback) => void;
    toggleMenu: (otherStateToSet?: {}, cb?: Callback) => void;
    selectItem: (item: Item, otherStateToSet?: {}, cb?: Callback) => void;
    selectItemAtIndex: (
      index: number,
      otherStateToSet?: {},
      cb?: Callback,
    ) => void;
    selectHighlightedItem: (otherStateToSet?: {}, cb?: Callback) => void;
    setHighlightedIndex: (
      index: number,
      otherStateToSet?: {},
      cb?: Callback,
    ) => void;
    clearSelection: (cb?: Callback) => void;
    clearItems: () => void;
    setItemCount: (count: number) => void;
    unsetItemCount: () => void;
    setState: (
      stateToSet: StateChangeOptions<Item> | StateChangeFunction<Item>,
      cb?: Callback,
    ) => void;
    // props
    itemToString: (item: Item) => string;
  }
  declare export type ControllerStateAndHelpers<Item> = DownshiftState<Item> &
    PropGetters<Item> &
    Actions<Item>
  declare export type ChildrenFunction<Item> = (
    options: ControllerStateAndHelpers<Item>,
  ) => React.ReactNode
  declare export type DownshiftType<Item> = Class<
    React.Component<DownshiftProps<Item>, DownshiftState<Item>>,
  > & {
    stateChangeTypes: StateChangeTypes,
  }
  declare var DownshiftComponent: DownshiftType<any>
  declare export default DownshiftComponent
}
