import * as React from 'react';
import type { TransitionStatus } from 'react-transition-group/Transition';

export type { TransitionStatus };

export interface TransitionProps {
  /**
   * Add a custom transition end trigger. Called with the transitioning DOM
   * node and a done callback. Allows for more fine grained transition end
   * logic. Note: Timeouts are still used as a fallback if provided.
   */
  addEndListener?: (node: HTMLElement, done: () => void) => void;
  /**
   * Normally a component is not transitioned if it is shown when the
   * `<Transition>` component mounts. If you want to transition on the first
   * mount set  appear to true, and the component will transition in as soon
   * as the `<Transition>` mounts. Note: there are no specific "appear" states.
   * appear only adds an additional enter transition.
   *
   * @default true
   */
  appear?: boolean | undefined;
  /**
   * An element or render function.
   */
  children:
    | React.ReactNode
    | ((status: TransitionStatus, props: Record<string, unknown>) => React.ReactNode);
  /**
   * Class name attaced to dom element.
   */
  className?: string;
  /**
   * Show the component; triggers the enter or exit states
   */
  in?: boolean;
  /**
   * By default the child component is mounted immediately along with the
   * parent Transition component. If you want to "lazy mount" the component on
   * the first `in={true}` you can set `mountOnEnter`. After the first enter
   * transition the component will stay mounted, even on "exited", unless you
   * also specify `unmountOnExit`.
   */
  mountOnEnter?: boolean;
  /**
   * Handler fired before the "entering" status is applied. An extra
   * parameter `isAppearing` is supplied to indicate if the enter stage is
   * occurring on the initial mount
   */
  onEnter?: (node: HTMLElement, isAppearing: boolean) => void;
  /**
   * Handler fired after the "entering" status is applied. An extra parameter
   * isAppearing is supplied to indicate if the enter stage is occurring on
   * the initial mount
   */
  onEntering?: (node: HTMLElement, isAppearing: boolean) => void;
  /**
   * Handler fired after the "entered" status is applied. An extra parameter
   * isAppearing is supplied to indicate if the enter stage is occurring on
   * the initial mount
   */
  onEntered?: (node: HTMLElement, isAppearing: boolean) => void;
  /**
   * Handler fired before the "exiting" status is applied.
   */
  onExit?: (node: HTMLElement) => void;
  /**
   * Handler fired after the "exiting" status is applied.
   */
  onExiting?: (node: HTMLElement) => void;
  /**
   * Handler fired after the "exited" status is applied.
   */
  onExited?: (node: HTMLElement) => void;
  /**
   * Style object.
   */
  style?: React.CSSProperties;
  /**
   * The duration of the transition, in milliseconds. Required unless addEndListener is provided.
   *
   * You may specify a single timeout for all transitions:
   * ```js
   *   timeout={500}
   * ```
   * or individually:
   * ```js
   * timeout={{
   *  appear: 500,
   *  enter: 300,
   *  exit: 500,
   * }}
   * ```
   * - appear defaults to the value of `enter`
   * - enter defaults to `0`
   * - exit defaults to `0`
   *
   * @default 200
   */
  timeout?: number | { appear?: number; enter?: number; exit?: number };
  /**
   * By default the child component stays mounted after it reaches the
   * 'exited' state. Set `unmountOnExit` if you'd prefer to unmount the
   * component after it finishes exiting.
   */
  unmountOnExit?: boolean;
}
