# All files / src/menu MenuVisibilityProvider.tsx

100% Statements 95/95
100% Branches 4/4
100% Functions 3/3
100% Lines 95/95

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
    961x
    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
    193x
    193x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    189x
    189x
    189x
    189x
    189x
    189x
    189x
    105x
    105x
    105x
    105x
    189x
    189x
    189x
    189x
    189x
     "use client";
    import {
      createContext,
      useContext,
      useMemo,
      type ReactElement,
      type ReactNode,
    } from "react";
    import { type NonNullMutableRef, type UseStateObject } from "../types.js";

    /**
     * @remarks
     * \@since 5.0.0
     * \@since 6.0.0 Added the `defaultFocusIndex` ref.
     */
    export interface MenuVisibilityContext
      extends UseStateObject<"visible", boolean> {
      defaultFocusIndex: NonNullMutableRef<number>;
    }

    /**
     * @internal
     * @remarks \@since 5.0.0
     */
    const context = createContext<MenuVisibilityContext>({
      visible: false,
      setVisible() {
        throw new Error('"MenuVisibilityProvider" must be a parent component');
      },
      defaultFocusIndex: { current: 0 },
    });
    context.displayName = "MenuVisibility";

    /**
     * @internal
     * @remarks \@since 5.0.0
     */
    const { Provider } = context;

    /**
     * This hook allows you control the visibility of a parent menu. The main
     * use-case for this hook is adding a custom sheet header/footer.
     *
     * @example
     * Simple Example
     * ```tsx
     * function SheetFooter(): ReactElement {
     *   const { setVisible } = useMenuVisibility();
     *
     *   return (
     *     <DialogFooter>
     *       <Button onClick={() => setVisible(false)}>Cancel</Button>
     *     </DialogFooter>
     *   );
     * }
     * ```
     *
     * @returns the {@link MenuVisibilityContext}
     * @remarks \@since 5.0.0
     */
    export function useMenuVisibility(): Readonly<MenuVisibilityContext> {
      return useContext(context);
    }

    /**
     * @internal
     * @remarks \@since 5.0.0
     */
    export interface MenuVisibilityProviderProps extends MenuVisibilityContext {
      children: ReactNode;
    }

    /**
     * **Client Component**
     *
     * @internal
     * @remarks \@since 5.0.0
     */
    export function MenuVisibilityProvider({
      visible,
      setVisible,
      defaultFocusIndex,
      children,
    }: MenuVisibilityProviderProps): ReactElement {
      const value = useMemo<MenuVisibilityContext>(
        () => ({
          visible,
          setVisible,
          defaultFocusIndex,
        }),
        [visible, setVisible, defaultFocusIndex]
      );

      return <Provider value={value}>{children}</Provider>;
    }