{"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"}