# All files / src/layout useLayoutWindowSplitter.ts

100% Statements 137/137
100% Branches 1/1
100% Functions 1/1
100% Lines 137/137

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
    1381x
    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
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
    46x
     "use client";
    import { type UncontrolledDraggableOptions } from "../draggable/useDraggable.js";
    import { type UseStateInitializer } from "../types.js";
    import { useWindowSize } from "../useWindowSize.js";
    import {
      useWindowSplitter,
      type WindowSplitterImplementation,
      type WindowSplitterOptions,
      type WindowSplitterWidgetProps,
    } from "../window-splitter/useWindowSplitter.js";

    /**
     * @remarks \@since 6.0.0
     */
    export interface LayoutWindowSplitterOptions
      extends Omit<WindowSplitterOptions, "min" | "max"> {
      /**
       * @see {@link WindowSplitterOptions.min}
       * @defaultValue `96`
       */
      min?: number;

      /**
       * This is the minimum max value that can be allowed while resizing the
       * browser. I don't know the best way to describe it, but the `max` value is
       * determined by:
       *
       * ```ts
       * const { width } = useWindowSize({ disableHeight: true });
       * const max = Math.max(maxMinimum, width * windowPercentage);
       * ```
       *
       * @defaultValue `600`
       */
      maxMinimum?: number;

      /**
       * This will be multiplied by the current window's width to determine the
       * dynamic max value for the window splitter.
       *
       * @see {@link maxMinimum}
       * @defaultValue `0.45`
       */
      windowPercentage?: number;

      /** @defaultValue `256` */
      defaultValue?: UseStateInitializer<number>;
    }

    /**
     * @remarks \@since 6.0.0
     */
    export interface ProvidedLayoutWindowSplitterProps
      extends WindowSplitterWidgetProps<HTMLButtonElement> {
      /** @defaultValue {@link WindowSplitterImplementation.value} */
      navWidth: number;
    }

    /**
     * @remarks \@since 6.0.0
     */
    export interface LayoutWindowSplitterImplementation
      extends WindowSplitterImplementation {
      splitterProps: ProvidedLayoutWindowSplitterProps;
    }

    /**
     * A custom window splitter implementation to be used with the
     * `LayoutWindowSplitter` that will dynamically configure the max width to be a
     * percentage of the current window's width.
     *
     * Note: This will automatically save the width in local storage as
     * `"navWidth"`. See the example below if you do not want to use local storage.
     *
     * @example
     * Without this hook
     * ```tsx
     * import { useWindowSize, useWindowSplitter } from "@react-md/core";
     * import type { ProvidedLayoutWindowSplitterProps } from "@react-md/core";
     *
     * export function useMyLayoutWindowSplitter(): ProvidedLayoutWindowSplitterProps {
     *   const { width } = useWindowSize({ disableHeight: true });
     *   const { splitterProps, value } = useWindowSplitter({
     *     min: 96,
     *     max: Math.max(maxMinimum, width * 0.45),
     *     maxMinimum: 600,
     *   });
     *
     *   return {
     *     ...splitterProps,
     *     navWidth: value,
     *   };
     * }
     *
     * function MyLayout() {
     *   const splitterProps = useMyLayoutWindowSplitter();
     *
     *   return (
     *     <LayoutWindowSplitter
     *       {...splitterProps}
     *       aria-controls="layout-nav-id"
     *     />
     *   );
     * }
     * ```
     *
     * @see {@link useResizableLayout} For a pre-built solution.
     * @remarks \@since 6.0.0
     */
    export function useLayoutWindowSplitter(
      options: LayoutWindowSplitterOptions = {}
    ): LayoutWindowSplitterImplementation {
      const {
        min = 96,
        maxMinimum = 600,
        windowPercentage = 0.45,
        defaultValue = 256,
        ...remaining
      } = options;
      const { width } = useWindowSize({ disableHeight: true });
      const implementation = useWindowSplitter({
        min,
        max: Math.max(maxMinimum, width * windowPercentage),
        defaultValue,
        // type cast so it doesn't complain about defaultValue being provided with
        // value. That's mostly for public api usage
        ...(remaining as UncontrolledDraggableOptions),
      });

      return {
        ...implementation,
        splitterProps: {
          ...implementation.splitterProps,
          navWidth: implementation.value,
        },
      };
    }