Source: templates/AnimationOqt.js

import React, { useEffect, useState } from "react";
import { useMemo } from "react";
import { emptyObject, processOptions } from "../..";

/**
 * Componente genera una animación a partir de un elemento div. Los efectos se pueden testear en <a href="https://xsgames.co/animatiss/" target="_new">AnimatiSS</a>
 * @name Reactor.Components.Templates.AnimationOqt
 * @param {JsonString} div_options Atributos que van a enviarse al div root
 * @param {string?} delay Tiempo de espera en ms para que se inicialice el componente y la animación
 * @param {string|EffectList} effect Uno de los efectos posibles con seteo de tiempo de duración y estilo de linea de tiempo
 * @param {HtmlElement} children Body del componente con el contenido que va a animarse
 * @paramloop = null, on_click = "false", on_load = "true", on_leave = "false"
 * @param {string?} loop Se establece un loop en ms para repetir indefinidamente la animación
 * @param {BooleanString} [on_load = "true"] Establece si la animación se va a ejecutar inmediatamente despues de la carga del componente
 * @param {BooleanString} [on_click = "false"] Establece si la animación se va a ejecutar cada vez que el usuario haga un click sobre el elemento
 * @param {BooleanString} [on_leave = "false"] Establece si la animación se va a ejecutar al descargar el elemento
 * @class 
 * @example 
Animación pasando una clase al div root
<animation div_options='{"className":"d-flex pb-1"}' effect="slide-right 0.3s linear both">
  <div>
    <h3>Sin notificaciones aún!</h3>
    <h6 class="mt-n2  opacity-80 color-highlight">Pronto las recibirás</h6>
  </div>
  <i class="bi bi-envelope-exclamation-fill font-24 color-yellow-dark"></i>
</animation>
Animación que se retrasa 300ms
<animation effect="slide-bottom 0.2s linear both" delay="300">
  <div class="align-self-center ms-auto">
    <p>Aquí podrás leer las notificaciones generadas por otros usuarios de Appfin en su interacción con vos.</p>
  </div>
</animation>
Animación que no se muestra en el load pero se ejecuta cada 6 segundos
<animation effect="shake-horizontal .4s linear both" on_load="false" loop="6000">
  <div class="{{divConMensajes}}">
    {{CampoMensaje}}
  </div>
</animation>
*/

export const AnimationOqt = ({div_options, delay, effect = "slide-right .3s", loop = null, on_load = "true", on_click = "false", on_leave = "false", children}) => {

  const stages = useMemo(()=>({
    loop: loop !== null, 
    click: on_click === "true", 
    load: on_load === "true", 
    leave: on_leave === "true",
    mount: false
  }), [loop, on_click, on_load, on_leave])

  const [fireEvent, setFireEvent] = useState({type: "mount", id: 0});
  const [animation, setAnimation] = useState("");
  const [loaded, setLoaded] = useState(false);
  
  useEffect(() => {
    if(!stages[fireEvent.type]) return;
    setAnimation(effect);
  }, [fireEvent, effect, stages]);

  const fireNewEvent = (type) => {
    setAnimation("");
    setFireEvent(ev => ({type, id: ev.id + 1}));
  }

  useEffect(()=>{
    fireNewEvent("load");
    if(delay){
      const delayTimer = setTimeout(() => {
        setLoaded(true);
      }, parseInt(delay));
      return ()=>{
        clearTimeout(delayTimer);
      }
    }else{
      setLoaded(true);
    }
    if(loop){
      const timer = setInterval(() => {
        fireNewEvent("loop");
      }, parseInt(loop));
      return ()=>{
        fireNewEvent("leave");
        clearInterval(timer);
      }
    }else{
      return ()=>{
        fireNewEvent("leave");
      }
    }
  }, [loop, delay]);

  const options = useMemo(()=>{
    const tempOptions = processOptions(div_options);
    return {...tempOptions, style: {...(tempOptions.style || emptyObject), animation} };
  }, [div_options, animation])
  
  const handleClick = () => {
    fireNewEvent("click");
  }

  return (
    <>
      {loaded && 
        <div {...options} onClick={stages.click ? handleClick : undefined} >
          {children}
        </div>      
      }
    </>
  )
}

/*
scale-up-center
scale-up-bottom-left
scale-up-bottom-right
scale-up-top-left
scale-up-top-right
scale-up-vertical-center
scale-up-horizontal-center
scale-up-top
scale-up-bottom
scale-up-left
scale-up-right
scale-up-vertical-top
scale-up-vertical-top
scale-up-horizontal-left
scale-up-horizontal-right
scale-up-horizontal-right
scale-down-center
scale-down-top
scale-down-bottom
scale-down-left
scale-down-right
scale-down-bottom-left
scale-down-bottom-right
scale-down-top-left
scale-down-top-right
scale-down-horizontal-center
scale-down-horizontal-left
scale-down-horizontal-right
scale-down-vertical-center
scale-down-vertical-top
scale-down-vertical-bottom
rotate-center
rotate-top
rotate-bottom
rotate-right
rotate-left
rotate-top-right
rotate-top-left
rotate-bottom-left
rotate-bottom-right
rotate-horizontal-center
rotate-horizontal-top
rotate-horizontal-bottom
rotate-vertical-center
rotate-vertical-left
rotate-vertical-right
rotate-diagonal-right
rotate-diagonal-left
rotate-diagonal-top-right
rotate-diagonal-top-left
rotate-diagonal-bottom-left
rotate-diagonal-bottom-right
rotate-scale-up
rotate-scale-down
rotate-scale-up-horizontal
rotate-scale-down-horizontal
rotate-scale-up-vertical
rotate-scale-down-vertical
rotate-scale-up-diagonal-left
rotate-scale-down-diagonal-right
rotate-scale-down-diagonal-left
rotate-scale-down-diagonal-right
swing-top
swing-bottom
swing-left
swing-right
swing-top-right
swing-top-left
swing-bottom-right
swing-bottom-left
slide-top
slide-bottom
slide-right
slide-left
slide-top-right
slide-top-left
slide-bottom-right
slide-bottom-left
slide-rotate-horizontal-top
slide-rotate-horizontal-bottom
slide-rotate-vertical-left
slide-rotate-vertical-right
shadow-drop-center
shadow-drop-top
shadow-drop-right
shadow-drop-bottom
shadow-drop-left
shadow-drop-left-right
shadow-drop-top-bottom
shadow-drop-top-right
shadow-drop-bottom-right
shadow-drop-bottom-left
shadow-drop-top-left
shadow-pop-top-right
shadow-pop-bottom-right
shadow-pop-bottom-left
shadow-pop-top-left
shadow-inset-center
shadow-inset-top
shadow-inset-right
shadow-inset-bottom
shadow-inset-left
shadow-inset-top-right
shadow-inset-bottom-right
shadow-inset-bottom-left
shadow-inset-top-left
tracking-in-expand
tracking-in-expand-forward-top
tracking-in-expand-forward-bottom
tracking-in-contract
tracking-out-contract
tracking-out-expand-forward-top
tracking-out-expand-forward-bottom
blur-in
blur-in-expand
blur-out
blur-out-expand
blur-out-contract
vibrate
flicker
shake-horizontal
shake-vertical
shake-left-right
shake-right
shake-left
jello-horizontal
jello-vertical
jello-diagonal
wobble-horizontal-bottom
wobble-horizontal-top
wobble-vertical-left
wobble-vertical-right
bounce-top
bounce-bottom
bounce-left
bounce-right
*/