react-spring#useTransition TypeScript Examples

The following examples show how to use react-spring#useTransition. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From gobarber-web with MIT License 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,
    message => message.id,
    {
      from: { right: '-120%', opacity: 0 },
      enter: { right: '0%', opacity: 1 },
      leave: { right: '-120%', opacity: 0 },
    },
  );

  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} message={item} style={props} />
      ))}
    </Container>
  );
}
Example #2
Source File: index.tsx    From ecoleta with MIT License 6 votes vote down vote up
ToastContainer: React.FC<IToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,
    message => message.id,
    {
      from: { right: '-120%', opacity: 0 },
      enter: { right: '0%', opacity: 1 },
      leave: { right: '-120%', opacity: 0 },
    },
  );

  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} message={item} style={props} />
      ))}
    </Container>
  );
}
Example #3
Source File: index.tsx    From front-entenda-direito with GNU General Public License v3.0 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,
    (message) => message.id,
    {
      from: { right: '-120%', opacity: 0, transform: 'rotateZ(0deg)' },
      enter: { right: '0%', opacity: 1, transform: 'rotateZ(360deg)' },
      leave: { right: '-120%', opacity: 0, transform: 'rotateZ(0deg)' },
    },
  );

  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} style={props} message={item} />
      ))}
    </Container>
  );
}
Example #4
Source File: index.tsx    From front-entenda-direito with GNU General Public License v3.0 6 votes vote down vote up
ToastContainerModal: React.FC<ToastContainerModalProps> = ({
  messages,
}) => {
  const messagesWithTransitions = useTransition(
    messages,
    (message) => message.id,
    {
      from: { right: '-120%', opacity: 0, transform: 'rotateZ(0deg)' },
      enter: { right: '0%', opacity: 1, transform: 'rotateZ(360deg)' },
      leave: { right: '-120%', opacity: 0, transform: 'rotateZ(0deg)' },
    },
  );

  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <ToastModal key={key} style={props} message={item} />
      ))}
    </Container>
  );
}
Example #5
Source File: Routes.tsx    From react-pokedex with MIT License 6 votes vote down vote up
Routes: React.FC = () => {
  const location = useLocation();
  const transitions = useTransition(location, (location) => location.pathname, {
    config: {
      duration: 250,
    },
    from: {
      opacity: 0.25,
    },
    enter: {
      opacity: 1,
    },
    leave: {
      opacity: 0.25,
    },
  });

  return (
    <React.Suspense fallback={<SplashScreen />}>
      {transitions.map(({ item: location, props, key }) => (
        <animated.div
          key={key}
          style={{
            ...props,
            width: "100%",
            position: "absolute",
          }}
        >
          <Switch location={location}>
            <Route path="/pokemons/:id" component={PokemonDetailsPage} />
            <Route exact path="/" component={PokemonsPage} />
          </Switch>
        </animated.div>
      ))}
    </React.Suspense>
  );
}
Example #6
Source File: index.tsx    From cheeseswap-interface with GNU General Public License v3.0 6 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 50,
  initialFocusRef,
  children
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #7
Source File: index.tsx    From rocketredis with MIT License 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ toasts }) => {
  const visibleToasts = useMemo(() => {
    if (toasts.length > 5) {
      return toasts.slice(toasts.length - 5, toasts.length)
    }

    return toasts
  }, [toasts])

  const transitions = useTransition(visibleToasts, toast => toast.id, {
    from: { right: '-120%' },
    enter: { right: '0%' },
    leave: { right: '-120%' },
    config: {
      duration: 200
    }
  })

  return createPortal(
    <Container>
      {transitions.map(({ item, key, props }) => (
        <Toast key={key} style={props} toast={item} />
      ))}
    </Container>,
    document.body
  )
}
Example #8
Source File: index.tsx    From panther-frontend-dex with GNU General Public License v3.0 6 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 50,
  initialFocusRef,
  children,
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {/* eslint-disable */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {/* eslint-enable */}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #9
Source File: index.tsx    From goose-frontend-amm with GNU General Public License v3.0 6 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 50,
  initialFocusRef,
  children,
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {/* eslint-disable */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {/* eslint-enable */}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #10
Source File: index.tsx    From vagasExplorer with MIT License 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,

    (message) => message.id,
    {
      from: { right: '-120%', opacity: 0 },
      enter: { right: '0%', opacity: 1 },
      leave: { right: '-120%', opacity: 0 },
    },
  );
  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} style={props} message={item} />
      ))}
    </Container>
  );
}
Example #11
Source File: SideDrawer.tsx    From nyxo-website with MIT License 6 votes vote down vote up
SideDrawer: FC<Props> = ({ showMenu, toggleMenu }) => {
  const handleClick = () => {
    toggleMenu()
  }

  const transitions = useTransition(showMenu, null, {
    from: { transform: "translateX(-100%)" },
    enter: { transform: "translateX(0%)" },
    leave: { transform: "translateX(-100%)" },
  })

  return (
    <>
      {transitions.map(({ item, key, props }) =>
        item ? (
          <SideDrawerWrap key={key} style={props}>
            <Ul>
              {links.map((link, index) => (
                <Li key={index}>
                  <ClickLink
                    onClick={handleClick}
                    to={`/${link.path}`}
                    title={link.title}>
                    {link.title}
                  </ClickLink>
                </Li>
              ))}
            </Ul>
          </SideDrawerWrap>
        ) : null
      )}
    </>
  )
}
Example #12
Source File: index.tsx    From gobarber-project with MIT License 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,
    message => message.id,
    {
      from: { right: '-120%', opacity: 0 },
      enter: { right: '0%', opacity: 1 },
      leave: { right: '-120%', opacity: 0 },
    },
  );

  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} style={props} message={item} />
      ))}
    </Container>
  );
}
Example #13
Source File: index.tsx    From GoBarber with MIT License 6 votes vote down vote up
ToastContainer: React.FC<ToastContainerProps> = ({ messages }) => {
  const messagesWithTransitions = useTransition(
    messages,
    (message) => message.id,
    {
      from: { right: '-120%', opacity: 0 },
      enter: { right: '0%', opacity: 1 },
      leave: { right: '-120%', opacity: 0 },
    },
  );
  return (
    <Container>
      {messagesWithTransitions.map(({ item, key, props }) => (
        <Toast key={key} style={props} message={item} />
      ))}
    </Container>
  );
}
Example #14
Source File: index.tsx    From luaswap-interface with GNU General Public License v3.0 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss = () => {},
  minHeight = false,
  maxHeight = 90,
  initialFocusRef,
  children
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  })

  const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } }))
  const bind = useGesture({
    onDrag: state => {
      set({
        y: state.down ? state.movement[1] : 0
      })
      if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) {
        onDismiss()
      }
    }
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: { transform: y.interpolate(y => `translateY(${y > 0 ? y : 0}px)`) }
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #15
Source File: index.tsx    From sushiswap-exchange with GNU General Public License v3.0 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 50,
  initialFocusRef,
  children
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  })

  const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } }))
  const bind = useGesture({
    onDrag: state => {
      set({
        y: state.down ? state.movement[1] : 0
      })
      if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) {
        onDismiss()
      }
    }
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: { transform: y.interpolate(y => `translateY(${y > 0 ? y : 0}px)`) }
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #16
Source File: Skeleton.tsx    From game-store-monorepo-app with MIT License 5 votes vote down vote up
Skeleton: React.FC<SkeletonProps> = ({ isLoading = true, theme, children }) => {
  const transitions = useTransition(isLoading, {
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    delay: 200,
  });

  const renderContentLoader = () => {
    switch (theme) {
      case 'FACEBOOK':
        return <Facebook />;
      case 'INSTAGRAM':
        return <Instagram />;
      case 'CODE':
        return <Code height={50} backgroundColor="#979797" foregroundColor="#aeaeae" />;
      case 'LIST':
        return <List />;
      case 'BULLET_LIST':
        return <BulletList />;
      case 'GAME_LIST_ITEM':
        return <GameListItemSkeleton />;
      case 'GAME_CARD_ITEM':
        return <GameCardItemSkeleton />;
      case 'PROFILE_INFO_CARD':
        return <ProfileInfoCardSkeleton />;
      case 'TEXT':
        return <TextSkeleton />;
      default:
        return null;
    }
  };

  return transitions(({ opacity }, item) => {
    return item ? (
      <animated.div
        style={{
          opacity: opacity.to({ range: [0.0, 1.0], output: [0, 1] }),
        }}
      >
        {renderContentLoader()}
      </animated.div>
    ) : (
      <animated.div
        style={{
          opacity: opacity.to({ range: [1.0, 0.0], output: [1, 0] }),
        }}
      >
        {children}
      </animated.div>
    );
  });
}
Example #17
Source File: useModalTransition.ts    From react-simple-hook-modal with MIT License 5 votes vote down vote up
useModalTransition = (
  transition: ModalTransition = ModalTransition.SCALE,
  isOpen: boolean
) => {
  return useTransition(isOpen, null, ModalTransitionConfig[transition]);
}
Example #18
Source File: index.tsx    From limit-orders-lib with GNU General Public License v3.0 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 90,
  initialFocusRef,
  children,
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
  });

  const [{ y }, set] = useSpring(() => ({
    y: 0,
    config: { mass: 1, tension: 210, friction: 20 },
  }));
  const bind = useGesture({
    onDrag: (state) => {
      set({
        y: state.down ? state.movement[1] : 0,
      });
      if (
        state.movement[1] > 300 ||
        (state.velocity > 3 && state.direction[1] > 0)
      ) {
        onDismiss();
      }
    },
  });

  return (
    <Fragment>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay
              key={key}
              style={props}
              onDismiss={onDismiss}
              initialFocusRef={initialFocusRef}
              unstable_lockFocusAcrossFrames={false}
            >
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: {
                        transform: y.interpolate(
                          (y) => `translateY(${(y as number) > 0 ? y : 0}px)`
                        ),
                      },
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </Fragment>
  );
}
Example #19
Source File: index.tsx    From dyp with Do What The F*ck You Want To Public License 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 90,
  initialFocusRef,
  children
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  })

  const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } }))
  const bind = useGesture({
    onDrag: state => {
      set({
        y: state.down ? state.movement[1] : 0
      })
      if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) {
        onDismiss()
      }
    }
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: { transform: y.interpolate(y => `translateY(${y > 0 ? y : 0}px)`) }
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #20
Source File: index.tsx    From sybil-interface with GNU General Public License v3.0 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 90,
  initialFocusRef,
  children,
}: ModalProps): JSX.Element {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
  })

  const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } }))
  const bind = useGesture({
    onDrag: (state) => {
      set({
        y: state.down ? state.movement[1] : 0,
      })
      if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) {
        onDismiss()
      }
    },
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: { transform: y.interpolate((y: any) => `translateY(${y > 0 ? y : 0}px)`) },
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #21
Source File: index.tsx    From cuiswap with GNU General Public License v3.0 5 votes vote down vote up
export default function Modal({
  isOpen,
  onDismiss,
  minHeight = false,
  maxHeight = 50,
  initialFocusRef = null,
  children
}: ModalProps) {
  const fadeTransition = useTransition(isOpen, null, {
    config: { duration: 200 },
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  })

  const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } }))
  const bind = useGesture({
    onDrag: state => {
      set({
        y: state.down ? state.movement[1] : 0
      })
      if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) {
        onDismiss()
      }
    }
  })

  return (
    <>
      {fadeTransition.map(
        ({ item, key, props }) =>
          item && (
            <StyledDialogOverlay key={key} style={props} onDismiss={onDismiss} initialFocusRef={initialFocusRef}>
              <StyledDialogContent
                {...(isMobile
                  ? {
                      ...bind(),
                      style: { transform: y.interpolate(y => `translateY(${y > 0 ? y : 0}px)`) }
                    }
                  : {})}
                aria-label="dialog content"
                minHeight={minHeight}
                maxHeight={maxHeight}
                mobile={isMobile}
              >
                {/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
                {!initialFocusRef && isMobile ? <div tabIndex={1} /> : null}
                {children}
              </StyledDialogContent>
            </StyledDialogOverlay>
          )
      )}
    </>
  )
}
Example #22
Source File: PokemonDetailsPage.tsx    From react-pokedex with MIT License 4 votes vote down vote up
PokemonDetailsPage = ({ match }: RouteComponentProps<MatchParams>) => {
  const { id } = match.params;
  const dispatch = useDispatch();
  const history = useHistory();
  const [activeTab, setActiveTab] = useState<PokemonTabs>("biography");
  const transitions = useTransition(activeTab, (p) => p, {
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    config: {
      duration: 250,
    },
  });

  const pokemons = useSelector(pokemonsSelector);
  const species = useSelector(speciesSelector);
  const evolutionChain = useSelector(evolutionChainSelector);
  const [chainLinks, setChainLinks] = useState<ChainLink[]>([]);
  const [
    selectedEvolutionPokemonIds,
    setSelectedEvolutionPokemonIds,
  ] = useState<number[]>([]);

  const selectedPokemon = pokemons.data.find(
    (pokemon) => pokemon !== null && pokemon.id === Number(id)
  );
  const selectedSpecies = species.data.find((s) => s.id === Number(id));
  const evolutionChainId =
    selectedSpecies?.evolutionChain?.url.split("/").slice(-2)[0] || null;
  const selectedEvolutionChain =
    evolutionChainId !== null
      ? evolutionChain.data.find((e) => e.id === Number(evolutionChainId))
      : null;

  const getPokemonEvolution = useCallback(
    (chain: ChainLink | null): ChainLink[] => {
      if (!chain) {
        return [];
      } else {
        return [chain].concat(getPokemonEvolution(chain.evolvesTo[0]));
      }
    },
    []
  );

  useEffect(() => {
    if (selectedEvolutionChain?.chain) {
      const pokemons: ChainLink[] = getPokemonEvolution(
        selectedEvolutionChain.chain
      );
      const pokemonIds = pokemons.map(({ species }) =>
        Number(species.url.split("/").slice(-2)[0])
      );
      dispatch(getPokemonsDynamically({ pokemonIds }));
      setSelectedEvolutionPokemonIds(pokemonIds);
      setChainLinks(pokemons);
    }
    //eslint-disable-next-line
  }, [selectedEvolutionChain]);

  useEffect(() => {
    if (pokemons.data.length === 0) {
      dispatch(getPokemonById({ pokemonId: id }));
    }
    dispatch(getSpeciesById({ pokemonId: id }));
    //eslint-disable-next-line
  }, [id, pokemons.data.length]);

  useEffect(() => {
    if (evolutionChainId) {
      dispatch(getEvolutionChainById({ id: Number(evolutionChainId) }));
    }
    //eslint-disable-next-line
  }, [selectedPokemon, evolutionChainId]);

  const backgroundColors = selectedPokemon?.types.map(({ type }) => {
    const [[, backgroundColor]] = Object.entries(PokemonTypeColors).filter(
      ([key, _]) => key === type.name
    );

    return backgroundColor;
  });

  const selectedBackgroundColor = backgroundColors && backgroundColors[0];

  const isPageLoading =
    species.status.state === SliceStatus.IDLE ||
    species.status.state === SliceStatus.LOADING ||
    evolutionChain.status.state === SliceStatus.IDLE ||
    evolutionChain.status.state === SliceStatus.LOADING ||
    pokemons.status.state === SliceStatus.IDLE ||
    pokemons.status.state === SliceStatus.LOADING;

  return (
    <Layout title={capitalize(selectedPokemon?.name)}>
      {isPageLoading ? (
        <div className="text-center mx-auto mt-12">
          <ScaleLoader color="#E3350D" radius={16} />
        </div>
      ) : (
        <>
          <>
            {selectedPokemon &&
              selectedSpecies &&
              selectedBackgroundColor &&
              selectedEvolutionChain && (
                <div className="pb-8">
                  <button
                    className="text-primary font-semibold transform hover:-translate-y-1 transition-transform ease-in duration-150 focus:outline-none"
                    onClick={() => history.push("/")}
                  >
                    <span className="text-primary font-semibold">Go Back</span>
                  </button>
                  <div
                    className="flex flex-col lg:flex-row justify-center items-start w-full mx-auto my-4 rounded-lg shadow-lg"
                    style={{
                      backgroundColor:
                        selectedBackgroundColor &&
                        selectedBackgroundColor.medium,
                    }}
                  >
                    <PokemonDetailsHeader
                      pokemon={selectedPokemon}
                      species={selectedSpecies}
                      selectedBackgroundColor={selectedBackgroundColor}
                    />
                    <div className="bg-white lg:mt-0 rounded-t-3xl rounded-b-lg lg:rounded-t-none lg:rounded-b-none lg:rounded-r-lg overflow-hidden w-full pt-16 lg:pt-8 px-6 md:px-12 lg:px-24">
                      <div className="flex flex-row justify-between w-full">
                        <Tab
                          handleSelect={() => setActiveTab("biography")}
                          isSelected={activeTab === "biography"}
                        >
                          Biography
                        </Tab>
                        <Tab
                          handleSelect={() => setActiveTab("stats")}
                          isSelected={activeTab === "stats"}
                        >
                          Stats
                        </Tab>
                        <Tab
                          handleSelect={() => setActiveTab("evolutions")}
                          isSelected={activeTab === "evolutions"}
                        >
                          Evolutions
                        </Tab>
                      </div>
                      <div className="relative mt-8 lg:h-178">
                        {transitions.map(({ item, key, props }) => {
                          let page: JSX.Element = (
                            <PokemonDetailsBiography
                              species={selectedSpecies}
                              pokemon={selectedPokemon}
                            />
                          );

                          switch (item) {
                            case "biography":
                              page = (
                                <PokemonDetailsBiography
                                  species={selectedSpecies}
                                  pokemon={selectedPokemon}
                                />
                              );
                              break;
                            case "stats":
                              page = (
                                <PokemonDetailsStats
                                  pokemon={selectedPokemon}
                                />
                              );
                              break;
                            case "evolutions":
                              page = (
                                <PokemonDetailsEvolutions
                                  selectedIds={selectedEvolutionPokemonIds}
                                  chainLinks={chainLinks}
                                  selectedBackgroundColor={
                                    selectedBackgroundColor
                                  }
                                />
                              );
                              break;
                            default:
                              break;
                          }
                          return (
                            <animated.div
                              key={key}
                              style={{
                                ...props,
                                position: "relative",
                                width: "100%",
                                height: "100%",
                              }}
                            >
                              {page}
                            </animated.div>
                          );
                        })}
                      </div>
                    </div>
                  </div>
                </div>
              )}
          </>
        </>
      )}
    </Layout>
  );
}
Example #23
Source File: FileSelect.tsx    From atlas with GNU General Public License v3.0 3 votes vote down vote up
FileSelect: React.FC<FileSelectProps> = ({
  onUploadFile,
  fileType,
  maxSize,
  title,
  paragraph,
  thumbnailUrl,
  onReAdjustThumbnail,
  onDropRejected,
  onError,
  error,
  isLoading,
}) => {
  const selectedFileTransition = useTransition(isLoading, {
    from: { opacity: 0, transform: 'scale(1.5)', x: '0%' },
    enter: { opacity: 1, transform: 'scale(1)', x: '0%' },
    leave: { opacity: 0, transform: 'scale(1)', x: '-200%' },
    config: {
      duration: 400,
      easing: beazierEasing(0, 0, 0.58, 1),
    },
  })

  const innerContainerTransition = useTransition(fileType, {
    from: { x: '200%' },
    enter: { x: '0%' },
    leave: { x: '-200%' },
    immediate: fileType === 'video',
    config: {
      duration: 400,
      easing: beazierEasing(0, 0, 0.58, 1),
    },
  })

  const onDropAccepted: DropzoneOptions['onDropAccepted'] = useCallback(
    (acceptedFiles) => {
      const [file] = acceptedFiles
      onUploadFile(file)
    },
    [onUploadFile]
  )

  const { getRootProps, getInputProps, isDragAccept, isFileDialogActive, open, acceptedFiles } = useDropzone({
    onDropAccepted,
    onDropRejected,
    maxFiles: 1,
    multiple: false,
    accept: fileType + '/*',
    maxSize,
    noClick: true,
    noKeyboard: true,
  })

  const [openErrorDialog, closeErrorDialog] = useConfirmationModal()

  useEffect(() => {
    if (!error) {
      return
    }
    openErrorDialog({
      title: 'Unsupported file type selected',
      description: error,
      iconType: 'warning',
      primaryButton: {
        onClick: () => {
          closeErrorDialog()
          onError?.(null, fileType)
          open()
        },
        text: 'Reselect file',
      },
      secondaryButton: {
        text: 'Cancel',
        onClick: () => {
          onError?.(null, fileType)
          closeErrorDialog()
        },
      },
    })
  }, [closeErrorDialog, error, fileType, onError, open, openErrorDialog])

  const handleReAdjustThumbnail = (e: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
    e.stopPropagation()
    onReAdjustThumbnail?.()
  }

  return (
    <DragAndDropArea {...getRootProps()} isDragAccept={isDragAccept} isFileDialogActive={isFileDialogActive}>
      <input {...getInputProps()} />
      {selectedFileTransition(
        (styles, item) =>
          item && (
            <SelectedFileInfo style={{ opacity: styles.opacity }}>
              <SelectedFileInfoBackground />
              <SelectedFileInfoInnerContainer style={{ transform: styles.transform, x: styles.x }}>
                <SvgIllustrativeFileSelected />
                <SelectedFileInfoHeading variant="t100">selected</SelectedFileInfoHeading>
                {acceptedFiles.length !== 0 && <Text variant="t200">{acceptedFiles[0].name}</Text>}
              </SelectedFileInfoInnerContainer>
            </SelectedFileInfo>
          )
      )}
      {innerContainerTransition((style, item) =>
        thumbnailUrl && fileType === 'image' ? (
          <Thumbnail
            isLoading={isLoading}
            src={thumbnailUrl}
            alt="video thumbnail"
            onClick={handleReAdjustThumbnail}
            title="Click to readjust"
          />
        ) : (
          <InnerContainer key={item} style={style} isLoading={isLoading}>
            {fileType === 'video' ? <SvgIllustrativeVideo /> : <SvgIllustrativeImage />}
            <Title variant="h400">{title}</Title>
            <Paragraph variant="t200" as="p" secondary>
              {paragraph}
            </Paragraph>
            <ButtonsGroup>
              <DragDropText variant="t100" secondary>
                Drag and drop or
              </DragDropText>
              <Button size="medium" onClick={() => open()} icon={<SvgActionUpload />}>
                Select a file
              </Button>
            </ButtonsGroup>
          </InnerContainer>
        )
      )}
    </DragAndDropArea>
  )
}