diff --git a/.vscode/settings.json b/.vscode/settings.json index 7344e62..daf7808 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,6 @@ }, "[typescript]": { "editor.defaultFormatter": "dbaeumer.vscode-eslint" - } -} \ No newline at end of file + }, + "editor.formatOnSave": true +} diff --git a/src/Transition.tsx b/src/Transition.tsx new file mode 100644 index 0000000..3097c52 --- /dev/null +++ b/src/Transition.tsx @@ -0,0 +1,13 @@ +import {Stage, useTransition} from './useTransition'; + +type TransitionProps = { + state: boolean; + timeout: number; + children: (stage: Stage, shouldMount: boolean) => React.ReactNode; +}; + +export function Transition({state, timeout, children}: TransitionProps) { + const {stage, shouldMount} = useTransition(state, timeout); + + return children(stage, shouldMount); +} diff --git a/src/index.ts b/src/index.ts index db1553e..6f6f7e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,2 @@ -console.log('init project for npm package register'); -export {}; +export {useTransition} from './useTransition'; +export {Transition} from './Transition'; diff --git a/src/useTransition.ts b/src/useTransition.ts new file mode 100644 index 0000000..8e4343e --- /dev/null +++ b/src/useTransition.ts @@ -0,0 +1,39 @@ +import {useEffect, useRef, useState} from 'react'; + +export type Stage = 'from' | 'enter' | 'leave'; + +export function useTransition(state: boolean, timeout: number) { + // the stage of transition - 'from' | 'enter' | 'leave' + const [stage, setStage] = useState(state ? 'enter' : 'from'); + + // the timer for should mount + const timer = useRef(); + const [shouldMount, setShouldMount] = useState(state); + + useEffect( + function handleStateChange() { + clearTimeout(timer.current); + + // when true - trans from to enter + // when false - trans enter to leave, unmount after timeout + if (state === true) { + setStage('from'); + setShouldMount(true); + setTimeout(() => { + setStage('enter'); + }); + } else { + setStage('leave'); + timer.current = setTimeout(() => { + setShouldMount(false); + }, timeout); + } + }, + [state, timeout] + ); + + return { + stage, + shouldMount, + }; +}