Yuki Takei 2 лет назад
Родитель
Сommit
a5280e5a01
2 измененных файлов с 53 добавлено и 0 удалено
  1. 1 0
      packages/ui/src/utils/index.ts
  2. 52 0
      packages/ui/src/utils/use-rect.ts

+ 1 - 0
packages/ui/src/utils/index.ts

@@ -1,2 +1,3 @@
 export * from './browser-utils';
 export * from './browser-utils';
 export * from './use-fullscreen';
 export * from './use-fullscreen';
+export * from './use-rect';

+ 52 - 0
packages/ui/src/utils/use-rect.ts

@@ -0,0 +1,52 @@
+// ref: https://gist.github.com/morajabi/523d7a642d8c0a2f71fcfa0d8b3d2846?permalink_comment_id=4688158#gistcomment-4688158
+
+import { useState, useRef, useEffect } from 'react';
+
+type MutableRefObject<T> = {
+  current: T
+}
+
+type EventType = 'resize' | 'scroll'
+
+const useEffectInEvent = (
+    event: EventType,
+    useCapture?: boolean,
+    set?: () => void,
+) => {
+  useEffect(() => {
+    if (set) {
+      set();
+      window.addEventListener(event, set, useCapture);
+
+      return () => window.removeEventListener(event, set, useCapture);
+    }
+  }, [event, set, useCapture]);
+};
+
+export const useRect = <T extends HTMLDivElement | null>(
+  event: EventType = 'resize',
+): [DOMRect | undefined, MutableRefObject<T | null>, number] => {
+  const [rect, setRect] = useState<DOMRect>();
+
+  const reference = useRef<T>(null);
+
+  const [screenHeight, setScreenHeight] = useState(window.innerHeight);
+
+  const set = (): void => {
+    setRect(reference.current?.getBoundingClientRect());
+  };
+
+  useEffectInEvent(event, true, set);
+  const handleResize = () => {
+    setScreenHeight(window.innerHeight);
+  };
+
+  useEffect(() => {
+    window.addEventListener(event, handleResize);
+    return () => {
+      window.removeEventListener(event, handleResize);
+    };
+  }, [event]);
+
+  return [rect, reference, screenHeight];
+};