# All files / tree TreeItemExpander.tsx

100% Statements 81/81
100% Branches 18/18
100% Functions 2/2
100% Lines 81/81

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
    821x
    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
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    805x
    5x
    5x
    800x
    800x
    800x
    162x
    162x
    162x
    972x
    28x
    28x
    3x
    3x
    3x
    3x
    3x
    3x
    28x
    28x
    162x
    162x
    162x
    162x
    965x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
    972x
     import { cnb } from "cnbuilder";
    import type { MouseEventHandler, ReactElement, ReactNode } from "react";
    import { cloneElement, isValidElement } from "react";
    import { IconRotator, useIcon } from "../icon";
    import { useTreeContext } from "./TreeProvider";

    /**
     * @internal
     * @remarks \@since 6.0.0 Updated to use the latest API
     */
    export interface TreeItemExpanderProps {
      /** @defaultValue `false` */
      isLeft?: boolean;
      itemId: string;
      addon: ReactNode;
      disabled: boolean;
      expanded: boolean;
      isLeafNode: boolean;
      className?: string;
    }

    /**
     * @internal
     * @remarks \@since 6.0.0 Updated to support the new `expansionMode` behavior.
     */
    export function TreeItemExpander(props: TreeItemExpanderProps): ReactElement {
      const {
        itemId,
        isLeft = false,
        addon,
        expanded,
        disabled,
        isLeafNode,
        className,
      } = props;
      const {
        expanderIcon,
        expanderLeft,
        expansionMode,
        disableTransition,
        toggleTreeItemExpansion,
      } = useTreeContext();

      const icon = useIcon("dropdown", expanderIcon);
      if (isLeafNode || expanderLeft !== isLeft) {
        if (isValidElement<{ className?: string }>(addon)) {
          return cloneElement(addon, { className });
        }

        return <>{addon}</>;
      }

      const isCloneable = isValidElement(icon);
      let clickProps: { onClick: MouseEventHandler<Element> } | undefined;
      if (expansionMode === "manual" && !disabled) {
        clickProps = {
          onClick(event) {
            // do not select the tree item if the icon is clicked
            event.stopPropagation();
            event.preventDefault();

            toggleTreeItemExpansion(itemId);
          },
        };
      }

      return (
        <>
          <IconRotator
            className={cnb(!addon && className)}
            {...(!isCloneable ? clickProps : undefined)}
            rotated={expanded}
            forceIconWrap={!isCloneable}
            disableTransition={disableTransition}
          >
            {clickProps && isCloneable ? cloneElement(icon, clickProps) : icon}
          </IconRotator>
          {addon}
        </>
      );
    }