NoticeTransition.tsx 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // @ts-ignore Currently there is no types for semi-animation-react
  2. import { Transition } from '@douyinfe/semi-animation-react';
  3. import React, { CSSProperties, JSXElementConstructor } from 'react';
  4. import { NoticePosition } from '@douyinfe/semi-foundation/notification/notificationFoundation';
  5. import { Motion } from '../_base/base';
  6. export type ArgsType<T> = T extends (...args: infer A) => any ? A : never;
  7. export interface NoticeTransitionProps{
  8. position?: NoticePosition;
  9. motion?: Motion<NoticeTransitionProps>;
  10. children?: React.ReactNode | ((TransitionProps?: any) => React.ReactNode);
  11. }
  12. type NoticeTransitionFormatFuncType = (styles: { translate: string;opacity: string | number }) => any;
  13. export default function NoticeTransition(props: NoticeTransitionProps = {}) {
  14. let { motion = {} } = props;
  15. const { position = 'topRight' } = props;
  16. const formatStyle = function formatStyle({ translate, opacity }: ArgsType<NoticeTransitionFormatFuncType>[0]) {
  17. let transform = `translateX(${translate}%)`;
  18. if (position && typeof position === 'string') {
  19. if (/left/i.test(position)) {
  20. transform = `translateX(${-translate}%)`;
  21. } else if (/right/i.test(position)) {
  22. transform = `translateX(${translate}%)`;
  23. } else if (/top/i.test(position)) {
  24. transform = `translateY(${-translate}%)`;
  25. } else {
  26. transform = `translateY(${translate}%)`;
  27. }
  28. }
  29. return {
  30. transform,
  31. opacity,
  32. };
  33. };
  34. if (typeof motion === 'function') {
  35. motion = motion(props);
  36. } else if (!motion || typeof motion !== 'object') {
  37. motion = {};
  38. }
  39. return (
  40. <Transition
  41. // onFrame={style => console.log(formatStyle(style))}
  42. from={{ translate: 100, opacity: 0 }}
  43. enter={{ translate: { val: 0, tension: 560, friction: 32 }, opacity: { val: 1, duration: 200 } } as any}
  44. leave={{
  45. translate: { val: 100, easing: 'easeOutCubic', duration: 300 },
  46. opacity: { val: 0, duration: 200 },
  47. } as any}
  48. {...motion}
  49. >
  50. {typeof props.children === 'function' ?
  51. (transitionStyle: ArgsType<NoticeTransitionFormatFuncType>[0]) =>
  52. (props.children as ({ transform, opacity }:
  53. { transform: CSSProperties['transform'];opacity: number | string }) => any)(
  54. formatStyle(transitionStyle)
  55. ) :
  56. props.children}
  57. </Transition>
  58. );
  59. }