Migrate to twenty-ui - utilities/animation (#7951)
This PR was created by [GitStart](https://gitstart.com/) to address the requirements from this ticket: [TWNTY-7538](https://clients.gitstart.com/twenty/5449/tickets/TWNTY-7538). --- ### Description - Move animation components to `twenty-ui` \ \ \ Fixes #7538 Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
GitHub
parent
edc36c707d
commit
113e9fc8c7
@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut';
|
||||
import { AnimatedEaseInOut } from 'twenty-ui';
|
||||
|
||||
const StyledThreadMessageBody = styled(motion.div)`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn';
|
||||
import React from 'react';
|
||||
import { AnimatedEaseIn } from 'twenty-ui';
|
||||
|
||||
type TitleProps = React.PropsWithChildren & {
|
||||
animate?: boolean;
|
||||
|
||||
@ -20,7 +20,6 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { LightIconButton } from '@/ui/input/button/components/LightIconButton';
|
||||
import { Checkbox, CheckboxVariant } from '@/ui/input/components/Checkbox';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { RecordBoardScrollWrapperContext } from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
@ -28,7 +27,12 @@ import styled from '@emotion/styled';
|
||||
import { ReactNode, useContext, useState } from 'react';
|
||||
import { useInView } from 'react-intersection-observer';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { AvatarChipVariant, IconEye, IconEyeOff } from 'twenty-ui';
|
||||
import {
|
||||
AnimatedEaseInOut,
|
||||
AvatarChipVariant,
|
||||
IconEye,
|
||||
IconEyeOff,
|
||||
} from 'twenty-ui';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import { useAddNewCard } from '../../record-board-column/hooks/useAddNewCard';
|
||||
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
import { AnimatedContainer, IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
import { AnimatedContainer } from '@/ui/utilities/animation/components/AnimatedContainer';
|
||||
|
||||
const StyledInlineCellButtonContainer = styled.div`
|
||||
align-items: center;
|
||||
|
||||
@ -3,6 +3,7 @@ import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import {
|
||||
AnimatedEaseInOut,
|
||||
IconChevronDown,
|
||||
IconComponent,
|
||||
IconDotsVertical,
|
||||
@ -38,7 +39,6 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledListItem = styled(RecordDetailRecordsListItem)<{
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
import { AnimatedContainer, IconComponent } from 'twenty-ui';
|
||||
|
||||
import { FloatingIconButton } from '@/ui/input/button/components/FloatingIconButton';
|
||||
import { AnimatedContainer } from '@/ui/utilities/animation/components/AnimatedContainer';
|
||||
|
||||
const StyledButtonContainer = styled.div`
|
||||
margin: ${({ theme }) => theme.spacing(1)};
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { ReactElement, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Chip, ChipVariant } from 'twenty-ui';
|
||||
import { AnimatedContainer, Chip, ChipVariant } from 'twenty-ui';
|
||||
|
||||
import { ExpandedListDropdown } from '@/ui/layout/expandable-list/components/ExpandedListDropdown';
|
||||
import { isFirstOverflowingChildElement } from '@/ui/layout/expandable-list/utils/isFirstOverflowingChildElement';
|
||||
import { AnimatedContainer } from '@/ui/utilities/animation/components/AnimatedContainer';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
import { motion } from 'framer-motion';
|
||||
import React from 'react';
|
||||
|
||||
export const AnimatedContainer = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
@ -1,29 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { AnimationDuration } from 'twenty-ui';
|
||||
|
||||
type AnimatedEaseInProps = Omit<
|
||||
React.ComponentProps<typeof motion.div>,
|
||||
'initial' | 'animated' | 'transition'
|
||||
> & {
|
||||
duration?: AnimationDuration;
|
||||
};
|
||||
|
||||
export const AnimatedEaseIn = ({
|
||||
children,
|
||||
duration = 'normal',
|
||||
}: AnimatedEaseInProps) => {
|
||||
const theme = useTheme();
|
||||
const initial = { opacity: 0 };
|
||||
const animate = { opacity: 1 };
|
||||
const transition = {
|
||||
ease: 'linear',
|
||||
duration: theme.animation.duration[duration],
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.div initial={initial} animate={animate} transition={transition}>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
@ -1,46 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { AnimationDuration } from 'twenty-ui';
|
||||
|
||||
type AnimatedEaseInOutProps = {
|
||||
isOpen: boolean;
|
||||
children: React.ReactNode;
|
||||
duration?: AnimationDuration;
|
||||
marginBottom?: string;
|
||||
marginTop?: string;
|
||||
initial?: boolean;
|
||||
};
|
||||
|
||||
export const AnimatedEaseInOut = ({
|
||||
children,
|
||||
isOpen,
|
||||
marginBottom,
|
||||
marginTop,
|
||||
duration = 'normal',
|
||||
initial = true,
|
||||
}: AnimatedEaseInOutProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<AnimatePresence initial={initial}>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{
|
||||
marginBottom: marginBottom ?? 0,
|
||||
marginTop: marginTop ?? 0,
|
||||
height: 0,
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{ height: 'fit-content', opacity: 1 }}
|
||||
exit={{ height: 0, opacity: 0, marginBottom: 0, marginTop: 0 }}
|
||||
transition={{
|
||||
duration: theme.animation.duration[duration],
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
@ -1,41 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { AnimationDuration } from 'twenty-ui';
|
||||
|
||||
type AnimatedFadeOutProps = {
|
||||
isOpen: boolean;
|
||||
children: React.ReactNode;
|
||||
duration?: AnimationDuration;
|
||||
marginBottom?: string;
|
||||
marginTop?: string;
|
||||
};
|
||||
|
||||
export const AnimatedFadeOut = ({
|
||||
isOpen,
|
||||
children,
|
||||
duration = 'normal',
|
||||
marginBottom,
|
||||
marginTop,
|
||||
}: AnimatedFadeOutProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
initial={{
|
||||
opacity: 1,
|
||||
marginBottom: marginBottom ?? 0,
|
||||
marginTop: marginTop ?? 0,
|
||||
}}
|
||||
exit={{ opacity: 0, height: 0, marginBottom: 0, marginTop: 0 }}
|
||||
transition={{
|
||||
duration: theme.animation.duration[duration],
|
||||
ease: 'easeOut',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
@ -1,72 +0,0 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
const StyledContainer = styled(motion.div)`
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const StyledWord = styled(motion.span)`
|
||||
white-space: pre;
|
||||
`;
|
||||
|
||||
type AnimatedTextWordProps = Omit<
|
||||
React.ComponentProps<typeof motion.div>,
|
||||
'children'
|
||||
> & {
|
||||
text: string;
|
||||
};
|
||||
|
||||
const containerAnimation = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: (i = 1) => ({
|
||||
opacity: 1,
|
||||
transition: { staggerChildren: 0.12, delayChildren: 0.04 * i },
|
||||
}),
|
||||
};
|
||||
|
||||
const childAnimation = {
|
||||
visible: {
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
transition: {
|
||||
type: 'spring',
|
||||
damping: 12,
|
||||
stiffness: 100,
|
||||
},
|
||||
},
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
x: 20,
|
||||
transition: {
|
||||
type: 'spring',
|
||||
damping: 12,
|
||||
stiffness: 100,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const AnimatedTextWord = ({ text = '' }: AnimatedTextWordProps) => {
|
||||
const words = useMemo(() => {
|
||||
const words = text.split(' ');
|
||||
|
||||
return words.map((value, index) =>
|
||||
index === words.length - 1 ? value : value + ' ',
|
||||
);
|
||||
}, [text]);
|
||||
|
||||
return (
|
||||
<StyledContainer
|
||||
variants={containerAnimation}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{words.map((word, index) => (
|
||||
<StyledWord variants={childAnimation} key={index}>
|
||||
{word}
|
||||
</StyledWord>
|
||||
))}
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
@ -1,33 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
type AnimatedTranslationProps = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export const AnimatedTranslation = ({ children }: AnimatedTranslationProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={{
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
y: -20,
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: theme.animation.duration.normal, // Replace this with your theme's duration
|
||||
ease: 'easeInOut',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user