# All files / src/menu MenuSheet.tsx

84.89% Statements 118/139
100% Branches 3/3
25% Functions 1/4
84.89% Lines 118/139

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
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    1401x
    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
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    406x
    390x
    390x
    16x
    16x
    16x
    16x
    16x

    16x
    16x
    16x

    16x
    16x
    16x
    16x
    16x
    16x
    16x
    16x
     "use client";
    import { type CSSProperties, type ReactElement, type ReactNode } from "react";
    import { Sheet, type BaseSheetProps } from "../sheet/Sheet.js";
    import { type LabelRequiredForA11y, type PropsWithRef } from "../types.js";
    import { type RenderMenuAsSheet } from "./MenuConfigurationProvider.js";

    const noop = (): void => {
      // do nothing
    };

    /**
     * @remarks \@since 6.0.0
     */
    export type MenuSheetConfigurableProps = Omit<
      BaseSheetProps,
      "visible" | "onRequestClose"
    >;

    /**
     * @remarks \@since 6.0.0
     */
    export interface MenuSheetConvenienceProps {
      /**
       * This can be used to apply additional props to the `Sheet` component when
       * the `Menu` is being rendered as a `Sheet`.
       *
       * Note: You can override the `style` and `className` using
       * {@link sheetStyle} and {@link sheetClassName} instead for convenience.
       *
       * @example
       * ```tsx
       * <Menu
       *   {...props}
       *   sheetProps={{
       *     style: {
       *       // custom inline style
       *     },
       *     className: "come-class-name",
       *     horizontalSize: "touch",
       *   }}
       * />
       * ```
       */
      sheetProps?: PropsWithRef<MenuSheetConfigurableProps, HTMLDivElement>;

      /**
       * Convenience prop to apply custom style to the `Sheet` component when the
       * `Menu` is being rendered as a `Sheet`.
       */
      sheetStyle?: CSSProperties;

      /**
       * Convenience prop to apply custom class name to the `Sheet` component when
       * the `Menu` is being rendered as a `Sheet`.
       */
      sheetClassName?: string;
    }

    /**
     * @internal
     * @remarks
     * \@since 5.0.0
     * \@since 6.0.0 Updated to use the latest menu API.
     */
    export interface MenuSheetProps extends BaseSheetProps {
      /** {@inheritDoc MenuConfiguration.sheetHeader} */
      header?: ReactNode;
      /** {@inheritDoc MenuConfiguration.sheetFooter} */
      footer?: ReactNode;
      children: ReactNode;

      /** @remarks \@since 6.0.0 */
      enabled: RenderMenuAsSheet;
    }

    /**
     * **Client Component**
     *
     * Implements a `Menu` using the `Sheet` component that probably shouldn't
     * really be used externally.
     *
     * @internal
     * @remarks
     * \@since 5.0.0
     * \@since 6.0.0 Added the `enabled` prop and does not render a custom `Menu`
     * implementation.
     */
    export function MenuSheet(
      props: LabelRequiredForA11y<MenuSheetProps>
    ): ReactElement {
      const {
        header,
        footer,
        children,
        onClick = noop,
        overlayProps,
        enabled,
        ...remaining
      } = props;
      const { onRequestClose } = props;

      if (!enabled) {
        return <>{children}</>;
      }

      return (
        <Sheet
          {...remaining}
          onClick={(event) => {
            onClick(event);

            // Prevent closing parent sheet/menus if an element in the header or
            // footer is clicked
            if (
              !(event.target instanceof HTMLElement) ||
              event.target
                .closest('.rmd-menu,[role="dialog"]')
                ?.getAttribute("role") === "dialog"
            ) {
              event.stopPropagation();
            }
          }}
          overlayProps={{
            ...overlayProps,
            onClick: (event) => {
              overlayProps?.onClick?.(event);

              // prevent closing parent menus if the overlay element is clicked.
              event.stopPropagation();
              onRequestClose();
            },
          }}
        >
          {header}
          {children}
          {footer}
        </Sheet>
      );
    }