useDomFullHeight.tsx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { useEffect, useState } from 'react';
  2. import type { MutableRefObject } from 'react';
  3. type TargetValue<T> = T | undefined | null;
  4. type TargetType = HTMLElement | HTMLDivElement | Element | Window | Document;
  5. type BasicTarget<T extends TargetType = Element> =
  6. | TargetValue<T>
  7. | MutableRefObject<TargetValue<T>>;
  8. const getTargetElement = <T extends TargetType>(target: BasicTarget<T> | string) => {
  9. if (!target) {
  10. return null;
  11. }
  12. let targetElement: TargetValue<T> | Element;
  13. if (typeof target === 'string') {
  14. targetElement = document.querySelector(target);
  15. } else if ('current' in target) {
  16. targetElement = target.current;
  17. } else {
  18. targetElement = target;
  19. }
  20. return targetElement;
  21. };
  22. const useDomFullHeight = (target: BasicTarget | string, extraHeight: number = 0) => {
  23. const [state, setState] = useState(100);
  24. useEffect(() => {
  25. const el = getTargetElement(target);
  26. let resizeObserver: ResizeObserver | undefined;
  27. if (el) {
  28. resizeObserver = new ResizeObserver((entries) => {
  29. entries.forEach((entry) => {
  30. const bodyClient = document.body.getBoundingClientRect();
  31. const domClient = entry.target.getBoundingClientRect();
  32. if (domClient.y < 50) {
  33. setState(100);
  34. } else {
  35. setState(bodyClient.height - domClient.y - 24 - extraHeight);
  36. }
  37. });
  38. });
  39. resizeObserver.observe(el);
  40. }
  41. return () => {
  42. if (resizeObserver) {
  43. resizeObserver.disconnect();
  44. }
  45. };
  46. }, [target]);
  47. return {
  48. minHeight: state,
  49. };
  50. };
  51. export default useDomFullHeight;