OpenIconTransition.tsx 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import React, { useEffect, useState } from 'react';
  2. import { Transition } from '@douyinfe/semi-animation-react';
  3. import PropTypes from 'prop-types';
  4. const formatStyle = function formatStyle({ rotate = 0 }) {
  5. return {
  6. transform: `rotate(${Math.ceil(rotate)}deg)`,
  7. };
  8. };
  9. export interface OpenIconTransitionProps {
  10. children?: React.ReactNode;
  11. isOpen?: boolean;
  12. }
  13. function OpenIconTransition(props: OpenIconTransitionProps = {}) {
  14. const { children, isOpen } = props;
  15. const [immediate, setImmediate] = useState(true);
  16. useEffect(() => {
  17. setImmediate(false);
  18. }, []);
  19. return (
  20. <Transition
  21. immediate={immediate}
  22. state={isOpen ? 'enter' : 'leave'}
  23. from={{ rotate: 0 }}
  24. enter={{ rotate: { val: 180, duration: 200, easing: 'cubic-bezier(.62, .05, .36, .95)' } }}
  25. leave={{ rotate: { val: 0, duration: 200, easing: 'cubic-bezier(.62, .05, .36, .95)' } }}
  26. >
  27. {(transitionStyle: any) => {
  28. const formatedStyle = formatStyle(transitionStyle);
  29. if (typeof children === 'function') {
  30. return children(formatedStyle);
  31. }
  32. if (React.isValidElement(children)) {
  33. return React.cloneElement(children, {
  34. style: {
  35. ...(children.props && children.props.style),
  36. ...formatedStyle,
  37. },
  38. });
  39. }
  40. return children;
  41. }}
  42. </Transition>
  43. );
  44. }
  45. OpenIconTransition.propTypes = {
  46. isOpen: PropTypes.bool.isRequired,
  47. children: PropTypes.any.isRequired,
  48. };
  49. export default OpenIconTransition;