From 87d21fdde6e817a4feebcd755da7b5b7bd297f89 Mon Sep 17 00:00:00 2001 From: ChanLee_KR Date: Thu, 1 Aug 2024 21:59:25 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=82=AC=EC=9A=A9=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=ED=9B=85=20=EC=A0=95=EB=A6=AC=20=EB=B0=8F=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20(#ATR-597)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../packages/hooks/.eslintrc.cjs | 14 +++++++++ .../design-system/packages/hooks/src/index.ts | 5 +++ .../packages/hooks/src/use-debounce/index.ts | 1 + .../hooks/src/use-debounce/useDebounce.ts | 15 +++++++++ .../hooks/src/use-outside-click/index.ts | 1 + .../src/use-outside-click/useOutsideClick.ts | 21 +++++++++++++ .../hooks/src/use-scroll-observer/index.ts | 1 + .../use-scroll-observer/useScrollObserver.ts | 31 +++++++++++++++++++ .../hooks/src/use-scroll-progress/index.ts | 1 + .../use-scroll-progress/useScrollProgress.ts | 16 ++++++++++ .../hooks/src/use-window-event/index.ts | 1 + .../src/use-window-event/useWindowEvent.ts | 14 +++++++++ .../packages/hooks/tsconfig.json | 5 +-- 13 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 packages/design-system/packages/hooks/.eslintrc.cjs create mode 100644 packages/design-system/packages/hooks/src/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-debounce/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-debounce/useDebounce.ts create mode 100644 packages/design-system/packages/hooks/src/use-outside-click/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-outside-click/useOutsideClick.ts create mode 100644 packages/design-system/packages/hooks/src/use-scroll-observer/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-scroll-observer/useScrollObserver.ts create mode 100644 packages/design-system/packages/hooks/src/use-scroll-progress/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-scroll-progress/useScrollProgress.ts create mode 100644 packages/design-system/packages/hooks/src/use-window-event/index.ts create mode 100644 packages/design-system/packages/hooks/src/use-window-event/useWindowEvent.ts diff --git a/packages/design-system/packages/hooks/.eslintrc.cjs b/packages/design-system/packages/hooks/.eslintrc.cjs new file mode 100644 index 00000000..49ab1966 --- /dev/null +++ b/packages/design-system/packages/hooks/.eslintrc.cjs @@ -0,0 +1,14 @@ +module.exports = { + parserOptions: { + project: ['./tsconfig.json'], + tsconfigRootDir: __dirname, + }, + rules: { + 'import/no-unresolved': [2, { caseSensitive: false }], + }, + settings: { + 'import/resolver': { + typescript: {}, + }, + }, +} diff --git a/packages/design-system/packages/hooks/src/index.ts b/packages/design-system/packages/hooks/src/index.ts new file mode 100644 index 00000000..78f7a3b3 --- /dev/null +++ b/packages/design-system/packages/hooks/src/index.ts @@ -0,0 +1,5 @@ +export * from './use-outside-click' +export * from './use-debounce' +export * from './use-window-event' +export * from './use-scroll-observer' +export * from './use-scroll-progress' diff --git a/packages/design-system/packages/hooks/src/use-debounce/index.ts b/packages/design-system/packages/hooks/src/use-debounce/index.ts new file mode 100644 index 00000000..a6758264 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-debounce/index.ts @@ -0,0 +1 @@ +export { default as useDebounce } from './useDebounce' diff --git a/packages/design-system/packages/hooks/src/use-debounce/useDebounce.ts b/packages/design-system/packages/hooks/src/use-debounce/useDebounce.ts new file mode 100644 index 00000000..5505b313 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-debounce/useDebounce.ts @@ -0,0 +1,15 @@ +import React from 'react' + +export default function useDebounce(value: T, delay: number) { + const [debouncedValue, setDebouncedValue] = React.useState(value) + + React.useEffect(() => { + const timeoutId = setTimeout(() => { + setDebouncedValue(value) + }, delay) + + return () => clearTimeout(timeoutId) + }, [value, delay]) + + return debouncedValue +} diff --git a/packages/design-system/packages/hooks/src/use-outside-click/index.ts b/packages/design-system/packages/hooks/src/use-outside-click/index.ts new file mode 100644 index 00000000..499d4fa7 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-outside-click/index.ts @@ -0,0 +1 @@ +export { default as useOutsideClick } from './useOutsideClick' diff --git a/packages/design-system/packages/hooks/src/use-outside-click/useOutsideClick.ts b/packages/design-system/packages/hooks/src/use-outside-click/useOutsideClick.ts new file mode 100644 index 00000000..e7632313 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-outside-click/useOutsideClick.ts @@ -0,0 +1,21 @@ +import React from 'react' + +export default function useOutsideClick(callback: () => void) { + const targetAreaRef = React.useRef(null) + + React.useEffect(() => { + const clickHandler = (e: MouseEvent) => { + if (!targetAreaRef.current) return + if (targetAreaRef.current.contains(e.target as Node | null)) { + return + } + callback() + } + document.addEventListener('click', clickHandler) + return () => { + document.removeEventListener('click', clickHandler) + } + }, [callback]) + + return targetAreaRef +} diff --git a/packages/design-system/packages/hooks/src/use-scroll-observer/index.ts b/packages/design-system/packages/hooks/src/use-scroll-observer/index.ts new file mode 100644 index 00000000..a7f42100 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-scroll-observer/index.ts @@ -0,0 +1 @@ +export { default as useScrollObserver } from './useScrollObserver' diff --git a/packages/design-system/packages/hooks/src/use-scroll-observer/useScrollObserver.ts b/packages/design-system/packages/hooks/src/use-scroll-observer/useScrollObserver.ts new file mode 100644 index 00000000..e18fa369 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-scroll-observer/useScrollObserver.ts @@ -0,0 +1,31 @@ +import React from 'react' + +export default function useScrollObserver( + callback: () => void, + options?: IntersectionObserverInit, +) { + const targetRef = React.useRef(null) + const observerRef = React.useRef(null) + const defaultOptions = { root: null, rootMargin: '0px', threshold: 1.0 } + + React.useEffect(() => { + if (!observerRef.current) { + observerRef.current = new IntersectionObserver(([target]) => { + if (target.isIntersecting) { + callback() + } + }, options ?? defaultOptions) + } + + if (targetRef.current) { + observerRef.current.observe(targetRef.current) + } + + return () => { + observerRef.current?.disconnect() + observerRef.current = null + } + }, [targetRef, callback]) + + return targetRef +} diff --git a/packages/design-system/packages/hooks/src/use-scroll-progress/index.ts b/packages/design-system/packages/hooks/src/use-scroll-progress/index.ts new file mode 100644 index 00000000..9929fed9 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-scroll-progress/index.ts @@ -0,0 +1 @@ +export { default as useScrollProgress } from './useScrollProgress' diff --git a/packages/design-system/packages/hooks/src/use-scroll-progress/useScrollProgress.ts b/packages/design-system/packages/hooks/src/use-scroll-progress/useScrollProgress.ts new file mode 100644 index 00000000..d8454fbe --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-scroll-progress/useScrollProgress.ts @@ -0,0 +1,16 @@ +import React from 'react' +import { useWindowEvent } from '../use-window-event' + +export default function useScrollProgress() { + const [scrollProgress, setScrollProgress] = React.useState(0) + const handleScroll = () => { + const currentScroll = window.scrollY + const totalHeight = document.body.scrollHeight - window.innerHeight + const progress = Math.round((currentScroll / totalHeight) * 100) + setScrollProgress(progress) + } + + useWindowEvent('scroll', handleScroll) + + return { scrollProgress } +} diff --git a/packages/design-system/packages/hooks/src/use-window-event/index.ts b/packages/design-system/packages/hooks/src/use-window-event/index.ts new file mode 100644 index 00000000..c14175f4 --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-window-event/index.ts @@ -0,0 +1 @@ +export { default as useWindowEvent } from './useWindowEvent' diff --git a/packages/design-system/packages/hooks/src/use-window-event/useWindowEvent.ts b/packages/design-system/packages/hooks/src/use-window-event/useWindowEvent.ts new file mode 100644 index 00000000..dbeeecfa --- /dev/null +++ b/packages/design-system/packages/hooks/src/use-window-event/useWindowEvent.ts @@ -0,0 +1,14 @@ +import React from 'react' + +export default function useWindowEvent( + type: K, + listener: (this: Window, e: DocumentEventMap[K]) => void, + option?: boolean | AddEventListenerOptions, +) { + React.useEffect(() => { + window.addEventListener(type as any, listener, option) + return () => { + window.removeEventListener(type as any, listener, option) + } + }, [type, listener, option]) +} diff --git a/packages/design-system/packages/hooks/tsconfig.json b/packages/design-system/packages/hooks/tsconfig.json index 4d1fbc5a..83f0758b 100644 --- a/packages/design-system/packages/hooks/tsconfig.json +++ b/packages/design-system/packages/hooks/tsconfig.json @@ -2,10 +2,7 @@ "extends": "@attraction/config/tsconfig.base.json", "main": "index.ts", "compilerOptions": { - "jsx": "preserve", - "paths": { - "@/*": ["./src/*"] - } + "jsx": "preserve" }, "include": ["**/*.ts", "**/*.tsx"], "exclude": ["node_modules"]