@wbe/react-transition
Version:
   
{"version":3,"file":"index.modern.mjs","sources":["../src/index.ts"],"sourcesContent":["import React, { ReactElement, useLayoutEffect, useRef, useState } from \"react\";\n\n/**\n * TPlay type is used in order to get/set current transtion step\n * hidden: Transition playOut is completed\n * play-out: Transition playOut is in perfoming\n * play-in: Transition playIn is in perfoming\n * visible: Transition playIn is completed\n */\nexport type TPlay = \"hidden\" | \"play-out\" | \"play-in\" | \"visible\";\n\ntype TProps = {\n /**\n * If\n * toggle start play-in / play-out children with transition\n * @default true\n */\n if?: boolean;\n\n /**\n * React children to transit\n */\n children?: ReactElement;\n\n /**\n * playIn transition\n * @param {HTMLElement} el DOM element to animate\n * @param {()=> void} done Execute function on transition end\n */\n playIn?: (el: HTMLElement, done: () => any) => void;\n\n /**\n * When playIn transition complete, execute callback\n */\n onPlayInComplete?: () => void;\n\n /**\n * playOut transition\n * @param {HTMLElement} el DOM element to animate\n * @param {()=> void} done Execute function on transition end\n */\n playOut?: (el: HTMLElement, done: () => any) => void;\n\n /**\n * When playOut transition complete, execute callback\n */\n onPlayOutComplete?: () => void;\n\n /**\n * Start transition on first mount\n * if false, children is visible but transition start only when \"if\" props change\n * @default false\n */\n appear?: boolean;\n\n /**\n * Unmount children React element after playOut transition\n * @default true\n */\n unmountAfterPlayOut?: boolean;\n\n /**\n * Dispatch current TPlay string type\n * @param play\n */\n dispatchPlayState?: (play: TPlay) => void;\n};\n\nTransition.defaultProps = {\n if: true,\n children: null,\n appear: false,\n unmountAfterPlayOut: true,\n} as TProps;\n\n/**\n * @name Transition\n */\n// prettier-ignore\nexport function Transition (props: TProps) {\n\n const rootRef = useRef<HTMLElement>(null)\n // curent play state\n const [playState, setPlayState] = useState<TPlay>(()=> {\n if (!props.appear) return props.if ? \"visible\" : \"hidden\"\n else return null\n })\n // allow to know if is first render\n const initialMountRef = useRef<boolean>(true)\n\n /**\n * 1. Listen toggle \"if\" props and mute playState\n */\n useLayoutEffect(() =>\n {\n if (!props.appear && initialMountRef.current)\n {\n initialMountRef.current = false\n return\n }\n setPlayState(props.if ? \"play-in\" : \"play-out\")\n\n }, [props.if, props.appear])\n\n\n\n /**\n * 2. Play transition depend of current playState\n */\n const rejectRef = useRef<Function>(null);\n\n useLayoutEffect(() =>\n {\n const ref = rootRef.current\n if (!ref) return\n\n // reject current pending promise\n if (playState === \"play-in\" || playState === \"play-out\")\n {\n rejectRef.current?.();\n }\n\n const asyncProcess = async ():Promise<void> =>\n {\n if (playState === \"play-in\")\n {\n await new Promise((resolve: any, reject) => {\n props.playIn?.(ref, resolve)\n rejectRef.current = reject\n })\n props.onPlayInComplete?.();\n setPlayState(\"visible\")\n }\n\n if (playState === \"play-out\")\n {\n await new Promise((resolve: any, reject) => {\n props.playOut?.(ref, resolve)\n rejectRef.current = reject\n })\n props.onPlayOutComplete?.();\n // need to manually dispatch this state\n props.dispatchPlayState?.(\"hidden\")\n setPlayState(\"hidden\")\n }\n\n }\n\n asyncProcess();\n props.dispatchPlayState?.(playState)\n\n }, [playState])\n\n /**\n * 3. Render\n */\n // Destroy children when transition state is hidden\n if (playState === \"hidden\" && props.unmountAfterPlayOut) return null\n\n // Return clone of props.children element with attached local ref\n return React.cloneElement(props.children, {\n className: [props.children.props.className || null, `transition-${playState}`].filter( e => e).join(\" \"),\n ref: (r) => (rootRef.current = r),\n })\n\n}\n"],"names":["Transition","props","rootRef","useRef","playState","setPlayState","useState","appear","if","useLayoutEffect","initialMountRef","current","rejectRef","ref","async","Promise","resolve","reject","playIn","onPlayInComplete","playOut","onPlayOutComplete","dispatchPlayState","asyncProcess","unmountAfterPlayOut","React","cloneElement","children","className","filter","e","join","r","defaultProps"],"mappings":"qEA+EgBA,SAAAA,EAAYC,GAE1B,MAAMC,EAAUC,EAAoB,OAE7BC,EAAWC,GAAgBC,EAAgB,IAC3CL,EAAMM,OAEZ,OAFiCC,GAAK,UAAY,YAI3BL,GAAgB,GAKxCM,EAAgB,KAETR,EAAMM,SAAUG,EAAgBC,QAKrCN,EAAaJ,EAAMO,GAAK,UAAY,YAHlCE,EAAgBC,SAAU,CAK7B,EAAE,CAACV,EAAMO,GAAIP,EAAMM,SAOpB,MAAMK,EAAYT,EAAiB,MAgDnC,OA9CAM,EAAgB,KAEd,QAAYP,EAAQS,QACfE,IAGa,YAAdT,GAAyC,aAAdA,SAE7BQ,EAAUD,SAAVC,EAAUD,UAGSG,WAED,YAAdV,UAEQW,IAAAA,QAAQ,CAACC,EAAcC,KAC/BhB,MAAAA,EAAMiB,QAANjB,EAAMiB,OAASL,EAAKG,GACpBJ,EAAUD,QAAUM,CACrB,GACDhB,MAAAA,EAAMkB,kBAANlB,EAAMkB,mBACNd,EAAa,YAGG,aAAdD,UAEQW,IAAAA,QAAQ,CAACC,EAAcC,KAC/BhB,MAAAA,EAAMmB,SAANnB,EAAMmB,QAAUP,EAAKG,GACrBJ,EAAUD,QAAUM,CAAAA,SAEtBhB,EAAMoB,mBAANpB,EAAMoB,oBAEN,MAAApB,EAAMqB,mBAANrB,EAAMqB,kBAAoB,UAC1BjB,EAAa,UACd,EAIHkB,GACAtB,MAAAA,EAAMqB,mBAANrB,EAAMqB,kBAAoBlB,GAA1B,EAEC,CAACA,IAMc,WAAdA,GAA0BH,EAAMuB,oBAAqB,kBAGlDC,EAAMC,aAAazB,EAAM0B,SAAU,CACxCC,UAAW,CAAC3B,EAAM0B,SAAS1B,MAAM2B,WAAa,KAAoB,cAAAxB,KAAayB,OAAQC,GAAKA,GAAGC,KAAK,KACpGlB,IAAMmB,GAAO9B,EAAQS,QAAUqB,GAGlC,CAjGDhC,EAAWiC,aAAe,CACxBzB,IAAI,EACJmB,SAAU,KACVpB,QAAQ,EACRiB,qBAAqB"}