OpenIconTransition.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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. // @ts-ignore
  36. style: {
  37. ...(children.props && children.props.style),
  38. ...formatedStyle,
  39. },
  40. });
  41. }
  42. return children;
  43. }}
  44. </Transition>
  45. );
  46. }
  47. OpenIconTransition.propTypes = {
  48. isOpen: PropTypes.bool.isRequired,
  49. children: PropTypes.any.isRequired,
  50. };
  51. export default OpenIconTransition;