# All files / src/transition CrossFade.tsx

100% Statements 117/117
100% Branches 2/2
100% Functions 1/1
100% Lines 117/117

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    1181x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
    39x
     "use client";
    import { cnb } from "cnbuilder";
    import { Children, cloneElement, type ReactElement } from "react";
    import { type CSSTransitionComponentImplementation } from "./types.js";
    import {
      useCrossFadeTransition,
      type CrossFadeTransitionHookOptions,
    } from "./useCrossFadeTransition.js";

    /**
     * @typeParam E - An HTMLElement type used for the ref required for the
     * transition.
     * @remarks
     * \@since 2.0.0
     * \@since 4.0.0 Updated for the new CSS Transition API
     */
    export interface CrossFadeProps<E extends HTMLElement>
      extends CrossFadeTransitionHookOptions<E>,
        CSSTransitionComponentImplementation<E> {
      /**
       * Unlike the {@link useCrossFadeTransition}, the `appear` value is defaulted
       * to `true` so that the transition can occur when the `key` changes.
       *
       * @see {@link CrossFadeTransitionHookOptions.appear}
       * @defaultValue `true`
       */
      appear?: boolean;
    }

    /**
     * **Client Component**
     *
     * This is a component implementation of the {@link useCrossFadeTransition} hook
     * that implements the `temporary` behavior. Since this component uses the
     * `React.cloneElement` to inject the `ref` and `className` into the `children`,
     * it is recommended to use the hook instead.
     *
     * @example
     * Appear transitions with a React `key`
     * ```tsx
     * import { ReactElement, useState } from "react";
     * import { CrossFade } from "@react-md/transition";
     *
     * import Page1 from "./Page1";
     * import Page2 from "./Page2";
     * import Page3 from "./Page3";
     *
     * function Example(): ReactElement {
     *   const [page, setPage] = useState(0):
     *
     *   let content: ReactNode;
     *   switch (page) {
     *     case 0:
     *       content = <Page1 />
     *       break:
     *     case 1:
     *       content = <Page2 />
     *       break;
     *     case 2:
     *       content = <Page3 />
     *       break;
     *     default:
     *       content = null;
     *   }
     *
     *   return (
     *     <>
     *       <Button
     *         onClick={() => {
     *           setPage(prevPage => {
     *             const nextPage = prevPage + 1;
     *             if (nextPage > 2) {
     *               return 0;
     *             }
     *
     *             return nextPage;
     *           })
     *         }}
     *       >
     *         Change Page
     *       </Button>
     *       <CrossFade key={page}>
     *         <div>{content}</div>
     *       </CrossFade>
     *     </>
     *   );
     * }
     * ```
     *
     * @typeParam E - An HTMLElement type used for the ref required for the
     * transition.
     * @remarks
     * \@since 2.0.0
     * \@since 4.0.0 Updated for the new CSS Transition API and no longer supports
     * wrapping children in a `<div>`.
     */
    export function CrossFade<E extends HTMLElement>(
      props: CrossFadeProps<E>
    ): ReactElement {
      const {
        appear = true,
        transitionIn = appear,
        children,
        className,
        ...options
      } = props;

      const child = Children.only(children);
      const { elementProps, rendered } = useCrossFadeTransition({
        ...options,
        appear,
        className: cnb(child.props.className, className),
        transitionIn,
      });

      return <>{rendered && cloneElement(children, elementProps)}</>;
    }