OpenIconTransition.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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 | ((transitionArgus?: any) => React.ReactNode);
  11. isCollapsed?: boolean;
  12. isOpen?: boolean;
  13. }
  14. function OpenIconTransition(props: OpenIconTransitionProps = {}) {
  15. const { children, isOpen } = props;
  16. const [immediate, setImmediate] = useState(true);
  17. useEffect(() => {
  18. setImmediate(false);
  19. }, []);
  20. return (
  21. <Transition
  22. immediate={immediate}
  23. state={isOpen ? 'enter' : 'leave'}
  24. from={{ rotate: 0 }}
  25. enter={{ rotate: { val: 180, duration: 200, easing: 'cubic-bezier(.62, .05, .36, .95)' } }}
  26. leave={{ rotate: { val: 0, duration: 200, easing: 'cubic-bezier(.62, .05, .36, .95)' } }}
  27. >
  28. {(transitionStyle: any) => {
  29. const formatedStyle = formatStyle(transitionStyle);
  30. if (typeof children === 'function') {
  31. return children(formatedStyle);
  32. }
  33. if (React.isValidElement(children)) {
  34. return React.cloneElement(children, {
  35. style: {
  36. ...(children.props && children.props.style),
  37. ...formatedStyle,
  38. },
  39. });
  40. }
  41. return children;
  42. }}
  43. </Transition>
  44. );
  45. }
  46. OpenIconTransition.propTypes = {
  47. isOpen: PropTypes.bool.isRequired,
  48. children: PropTypes.any.isRequired,
  49. };
  50. export default OpenIconTransition;