# All files / src/icon IconRotator.tsx

100% Statements 79/79
100% Branches 5/5
100% Functions 1/1
100% Lines 79/79

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
    801x
    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
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    508x
    501x
    501x
    501x
    501x
    501x
    7x
    7x
    7x
    7x
    7x
    7x
    7x
    1x
     import { cnb } from "cnbuilder";
    import {
      Children,
      cloneElement,
      forwardRef,
      isValidElement,
      type CSSProperties,
      type HTMLAttributes,
      type ReactNode,
    } from "react";
    import { iconRotator, type IconRotatorClassNameOptions } from "./styles.js";

    /**
     * @remarks \@since 6.0.0 Removed `animate` prop and added `disableTransition`
     */
    export interface IconRotatorBaseProps
      extends HTMLAttributes<HTMLSpanElement>,
        IconRotatorClassNameOptions {
      /**
       * An optional style to apply to the surrounding span when the `forceIconWrap`
       * prop is enabled or the children is not a single react element.
       */
      style?: CSSProperties;

      /**
       * Boolean if the child icon should be "forcefully" wrapped in a `<span>`
       * element. This should be enabled if you have a custom icon that does not
       * pass the `className` prop down.
       *
       * @defaultValue `false`
       */
      forceIconWrap?: boolean;
    }

    export interface IconRotatorProps extends IconRotatorBaseProps {
      /**
       * The icon that should be rotated. If this is a valid React Element, the
       * class names will be cloned into that icon, otherwise the icon will be
       * wrapped in a span with the correct class names applied.
       */
      children: ReactNode;
    }

    /**
     * **Server Component**
     *
     * The `IconRotator` is a simple component that is used to rotate an icon from a
     * one degrees to another.
     */
    export const IconRotator = forwardRef<HTMLSpanElement, IconRotatorProps>(
      function IconRotator(props, ref) {
        const {
          className: propClassName,
          rotated,
          children,
          forceIconWrap = false,
          disableTransition = false,
          ...remaining
        } = props;

        const className = iconRotator({
          rotated,
          className: propClassName,
          disableTransition,
        });
        if (!forceIconWrap && isValidElement<{ className?: string }>(children)) {
          const child = Children.only(children);
          return cloneElement(child, {
            className: cnb(className, child.props.className),
          });
        }

        return (
          <span {...remaining} ref={ref} className={className}>
            {children}
          </span>
        );
      }
    );