# All files / form selectUtils.ts

72.11% Statements 75/104
71.42% Branches 10/14
100% Functions 2/2
72.11% Lines 75/104

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
    1051x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    328x
    328x

    328x
    328x
    328x
    328x

    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    105x
    105x
    105x
    105x
    105x
    105x
    105x
    105x
    348x

    348x
    348x
    348x
    328x
    328x
    283x
    328x
    45x
    45x
    328x
    328x
    328x
    328x
    328x
    348x
    18x
    18x
    12x
    12x
    18x
    18x
    18x
    348x
    105x
    105x
    105x
    105x
    105x
    105x
     import { Children, isValidElement, type ReactNode } from "react";
    import { type MenuItemProps } from "../menu/MenuItem.js";

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export interface SelectOption<Value extends string | number = string>
      extends MenuItemProps {
      value: Value;
    }

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    function getLabelFromChildren(children: ReactNode): string {
      if (!children) {
        return "";
      }

      if (typeof children === "string" || typeof children === "number") {
        return `${children}`;
      }

      if (isValidElement<{ children: ReactNode; hidden?: boolean }>(children)) {
        if (children.props.hidden) {
          return "";
        }

        return getLabelFromChildren(children.props.children);
      }

      const childList = Children.toArray(children);
      for (const child of childList) {
        if (typeof child === "string" || typeof child === "number") {
          return `${child}`[0].toUpperCase();
        }

        if (
          isValidElement<{ children: ReactNode; hidden?: boolean }>(child) &&
          !child.props.hidden
        ) {
          return getLabelFromChildren(child.props.children);
        }
      }

      return "";
    }

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    interface ExtractedOptions<Value extends string | number> {
      options: readonly Value[];
      currentOption: SelectOption<Value> | undefined;
    }

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export function extractOptionsFromChildren<Value extends string | number>(
      children: ReactNode,
      currentValue: Value | undefined
    ): ExtractedOptions<Value> {
      let currentOption: SelectOption<Value> | undefined;

      const options: Value[] = [];
      const searchValues: string[] = [];
      Children.forEach(children, (child) => {
        if (!isValidElement<SelectOption<Value>>(child)) {
          return;
        }

        const { value, disabled, children } = child.props;
        if (typeof value !== "undefined") {
          if (
            value === currentValue ||
            (!currentOption && typeof currentValue === "undefined")
          ) {
            currentOption = child.props;
          }

          if (!disabled) {
            options.push(child.props.value);
            searchValues.push(getLabelFromChildren(children));
          }
        } else if (children) {
          const result = extractOptionsFromChildren(children, currentValue);
          if (!currentOption) {
            ({ currentOption } = result);
          }

          options.push(...result.options);
        }
      });

      return {
        options,
        currentOption,
      };
    }