# All files / src/tooltip useTooltipPosition.ts

100% Statements 101/101
100% Branches 5/5
100% Functions 2/2
100% Lines 101/101

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
    1021x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    2x
    2x
    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
    207x
    207x
    207x
    207x
    207x
    207x
    207x
    207x
    207x
    207x
    207x
    21x
    21x
    21x
    21x
    21x
    21x
    21x
    21x
    207x
    207x
    207x
    207x
    11x
    11x
    196x
    196x
    196x
     "use client";
    import { useCallback, useState } from "react";
    import type { SimplePosition } from "../positioning/types.js";
    import {
      DEFAULT_TOOLTIP_POSITION,
      DEFAULT_TOOLTIP_THRESHOLD,
    } from "./constants.js";
    import { getPosition } from "./utils.js";

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

    /**
     * @remarks \@since 2.8.0
     */
    export interface TooltipPositionHookOptions {
      /**
       * An optional controlled position to use that will disable the functionality
       * to determine the "best" position to render the tooltip within the viewport.
       */
      position?: SimplePosition;

      /**
       * An optional position to use before the positioning calculation has
       * occurred. This is also used to determine if the position should be
       * horizontal vs vertical.
       *
       * Vertical - `"below"` or `"above"`
       * Horizontal - `"left"` or `"right"`
       *
       * @defaultValue `DEFAULT_TOOLTIP_POSITION`
       * @see {@link DEFAULT_TOOLTIP_POSITION}
       */
      defaultPosition?: SimplePosition;

      /**
       * This value should be between 0 and 1 and will be multiplied by either the
       * viewport height or viewport width to determine the best position to render
       * the tooltip based on available space within the viewport.
       *
       * You _probably_ won't ever really need to update this value.
       *
       * @defaultValue `DEFAULT_TOOLTIP_THRESHOLD`
       * @see {@link DEFAULT_TOOLTIP_THRESHOLD}
       */
      threshold?: number;
    }

    /**
     * @internal
     * @remarks \@since 2.8.0
     */
    export type UpdateTooltipPosition = (container: HTMLElement) => void;

    /**
     * @internal
     * @remarks \@since 2.8.0
     */
    export type TooltipPositionHookReturnValue = [
      SimplePosition,
      UpdateTooltipPosition,
    ];

    /**
     * A hook that's used to determine the "best" position to render the tooltip
     * within the viewport.
     *
     * @internal
     * @remarks \@since 2.8.0
     */
    export function useTooltipPosition(
      options: TooltipPositionHookOptions
    ): TooltipPositionHookReturnValue {
      const {
        position: determinedPosition,
        threshold = DEFAULT_TOOLTIP_THRESHOLD,
        defaultPosition = DEFAULT_TOOLTIP_POSITION,
      } = options;

      const [position, setPosition] = useState(defaultPosition);
      const updatePosition = useCallback<UpdateTooltipPosition>(
        (container) => {
          setPosition(
            getPosition({
              container,
              threshold,
              defaultPosition,
            })
          );
        },
        [defaultPosition, threshold]
      );

      if (typeof determinedPosition !== "undefined") {
        return [determinedPosition, noop];
      }

      return [position, updatePosition];
    }