-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/#324 feature becom to auther #344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,155 @@ | ||||||||||||||||||||||||||||||||
| "use client"; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import { cn } from "@repo/ui/lib/utils"; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import React, { | ||||||||||||||||||||||||||||||||
| createContext, | ||||||||||||||||||||||||||||||||
| useState, | ||||||||||||||||||||||||||||||||
| useContext, | ||||||||||||||||||||||||||||||||
| useRef, | ||||||||||||||||||||||||||||||||
| useEffect, | ||||||||||||||||||||||||||||||||
| } from "react"; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const MouseEnterContext = createContext< | ||||||||||||||||||||||||||||||||
| [boolean, React.Dispatch<React.SetStateAction<boolean>>] | undefined | ||||||||||||||||||||||||||||||||
| >(undefined); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| export const CardContainer = ({ | ||||||||||||||||||||||||||||||||
| children, | ||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||
| containerClassName, | ||||||||||||||||||||||||||||||||
| }: { | ||||||||||||||||||||||||||||||||
| children?: React.ReactNode; | ||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||
| containerClassName?: string; | ||||||||||||||||||||||||||||||||
| }) => { | ||||||||||||||||||||||||||||||||
| const containerRef = useRef<HTMLDivElement>(null); | ||||||||||||||||||||||||||||||||
| const [isMouseEntered, setIsMouseEntered] = useState(false); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => { | ||||||||||||||||||||||||||||||||
| if (!containerRef.current) return; | ||||||||||||||||||||||||||||||||
| const { left, top, width, height } = | ||||||||||||||||||||||||||||||||
| containerRef.current.getBoundingClientRect(); | ||||||||||||||||||||||||||||||||
| const x = (e.clientX - left - width / 2) / 25; | ||||||||||||||||||||||||||||||||
| const y = (e.clientY - top - height / 2) / 25; | ||||||||||||||||||||||||||||||||
| containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`; | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) => { | ||||||||||||||||||||||||||||||||
| setIsMouseEntered(true); | ||||||||||||||||||||||||||||||||
| if (!containerRef.current) return; | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const handleMouseLeave = (e: React.MouseEvent<HTMLDivElement>) => { | ||||||||||||||||||||||||||||||||
| if (!containerRef.current) return; | ||||||||||||||||||||||||||||||||
| setIsMouseEntered(false); | ||||||||||||||||||||||||||||||||
| containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`; | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||
| <MouseEnterContext.Provider value={[isMouseEntered, setIsMouseEntered]}> | ||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||
| "w-full flex items-center justify-center", | ||||||||||||||||||||||||||||||||
| containerClassName | ||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||
| style={{ | ||||||||||||||||||||||||||||||||
| perspective: "1000px", | ||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||
| ref={containerRef} | ||||||||||||||||||||||||||||||||
| onMouseEnter={handleMouseEnter} | ||||||||||||||||||||||||||||||||
| onMouseMove={handleMouseMove} | ||||||||||||||||||||||||||||||||
| onMouseLeave={handleMouseLeave} | ||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||
| "flex w-full items-center justify-center relative transition-all duration-200 ease-linear", | ||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||
| style={{ | ||||||||||||||||||||||||||||||||
| transformStyle: "preserve-3d", | ||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||
| {children} | ||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||
| </MouseEnterContext.Provider> | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| export const CardBody = ({ | ||||||||||||||||||||||||||||||||
| children, | ||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||
| }: { | ||||||||||||||||||||||||||||||||
| children: React.ReactNode; | ||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||
| }) => { | ||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||
| className={cn( | ||||||||||||||||||||||||||||||||
| "[transform-style:preserve-3d] [&>*]:[transform-style:preserve-3d]", | ||||||||||||||||||||||||||||||||
| className | ||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||
| {children} | ||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| export const CardItem = ({ | ||||||||||||||||||||||||||||||||
| as: Tag = "div", | ||||||||||||||||||||||||||||||||
| children, | ||||||||||||||||||||||||||||||||
| className, | ||||||||||||||||||||||||||||||||
| translateX = 0, | ||||||||||||||||||||||||||||||||
| translateY = 0, | ||||||||||||||||||||||||||||||||
| translateZ = 0, | ||||||||||||||||||||||||||||||||
| rotateX = 0, | ||||||||||||||||||||||||||||||||
| rotateY = 0, | ||||||||||||||||||||||||||||||||
| rotateZ = 0, | ||||||||||||||||||||||||||||||||
| ...rest | ||||||||||||||||||||||||||||||||
| }: { | ||||||||||||||||||||||||||||||||
| as?: React.ElementType; | ||||||||||||||||||||||||||||||||
| children: React.ReactNode; | ||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||
| translateX?: number | string; | ||||||||||||||||||||||||||||||||
| translateY?: number | string; | ||||||||||||||||||||||||||||||||
| translateZ?: number | string; | ||||||||||||||||||||||||||||||||
| rotateX?: number | string; | ||||||||||||||||||||||||||||||||
| rotateY?: number | string; | ||||||||||||||||||||||||||||||||
| rotateZ?: number | string; | ||||||||||||||||||||||||||||||||
| [key: string]: any; | ||||||||||||||||||||||||||||||||
| }) => { | ||||||||||||||||||||||||||||||||
| const ref = useRef<HTMLDivElement>(null); | ||||||||||||||||||||||||||||||||
| const [isMouseEntered] = useMouseEnter(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||
| handleAnimations(); | ||||||||||||||||||||||||||||||||
| }, [isMouseEntered]); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| const handleAnimations = () => { | ||||||||||||||||||||||||||||||||
| if (!ref.current) return; | ||||||||||||||||||||||||||||||||
| if (isMouseEntered) { | ||||||||||||||||||||||||||||||||
| ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`; | ||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||
| ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+124
to
+136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider dependencies in useEffect The useEffect(() => {
handleAnimations();
- }, [isMouseEntered]);
+ }, [isMouseEntered, translateX, translateY, translateZ, rotateX, rotateY, rotateZ]);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||
| <Tag | ||||||||||||||||||||||||||||||||
| ref={ref} | ||||||||||||||||||||||||||||||||
| className={cn(" transition duration-200 ease-linear", className)} | ||||||||||||||||||||||||||||||||
| {...rest} | ||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||
| {children} | ||||||||||||||||||||||||||||||||
| </Tag> | ||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Create a hook to use the context | ||||||||||||||||||||||||||||||||
| export const useMouseEnter = () => { | ||||||||||||||||||||||||||||||||
| const context = useContext(MouseEnterContext); | ||||||||||||||||||||||||||||||||
| if (context === undefined) { | ||||||||||||||||||||||||||||||||
| throw new Error("useMouseEnter must be used within a MouseEnterProvider"); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
| return context; | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle units consistently for transform values
The component accepts numbers or strings for translation and rotation values, but applies them directly with fixed units (px/deg). This could cause issues if string values already include units.
const handleAnimations = () => { if (!ref.current) return; if (isMouseEntered) { - ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`; + ref.current.style.transform = `translateX(${typeof translateX === 'number' ? translateX + 'px' : translateX}) translateY(${typeof translateY === 'number' ? translateY + 'px' : translateY}) translateZ(${typeof translateZ === 'number' ? translateZ + 'px' : translateZ}) rotateX(${typeof rotateX === 'number' ? rotateX + 'deg' : rotateX}) rotateY(${typeof rotateY === 'number' ? rotateY + 'deg' : rotateY}) rotateZ(${typeof rotateZ === 'number' ? rotateZ + 'deg' : rotateZ})`; } else { ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`; } };📝 Committable suggestion
🤖 Prompt for AI Agents