All files / libs/ext/react/hooks/src/lib/use-text-overflows useTextOverflows.ts

0% Statements 0/42
0% Branches 0/1
0% Functions 0/1
0% Lines 0/42

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                                                                                     
import { useCallback, useRef, useState, type DependencyList, type RefCallback } from 'react';

import { useMergedRef } from '../use-merged-ref/useMergedRef';
import { useResizeObserver, type UseResizeObserverOptions } from '../use-resize-observer/useResizeObserver';
import { useUpdateEffect } from '../use-update-effect/useUpdateEffect';

const isTextCutOff = <TElement extends HTMLElement>(element: TElement | null) =>
  !!element && (element.offsetWidth < element.scrollWidth || element.offsetHeight < element.scrollHeight);

export type UseTextOverflowsValue<TElement extends HTMLElement> = {
  ref: RefCallback<TElement>;
  doesTextOverflow: boolean;
};

/**
 * Find out if a text overflows (when using text-overflow). This uses ResizeObserver.
 *
 * @param deps - Dependencies to update the text overflow state (aka pass the content of the element being observed).
 */
export const useTextOverflows = <TElement extends HTMLElement>(
  deps: DependencyList = [],
): UseTextOverflowsValue<TElement> => {
  const [doesTextOverflow, setDoesTextOverflow] = useState<boolean>(false);

  const onResize: UseResizeObserverOptions<TElement>['onResize'] = useCallback(
    (_, element) => setDoesTextOverflow(isTextCutOff(element)),
    [],
  );

  const observerRef = useResizeObserver({ onResize });
  const internalRef = useRef<TElement>(null);

  const mergedRef = useMergedRef<TElement>(observerRef, internalRef);

  // eslint-disable-next-line react-hooks/exhaustive-deps -- Array must be static.
  useUpdateEffect(() => setDoesTextOverflow(isTextCutOff(internalRef.current)), deps);

  return {
    ref: mergedRef,
    doesTextOverflow,
  };
};