computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
1.5 KiB
69 lines
1.5 KiB
import { useEffect, useState } from 'react'; |
|
import ReactConfetti from 'react-confetti'; |
|
|
|
type ConfettiPosition = { |
|
x: number; |
|
y: number; |
|
w: number; |
|
h: number; |
|
}; |
|
|
|
type ConfettiProps = { |
|
pieces?: number; |
|
element?: HTMLElement | null; |
|
onDone?: () => void; |
|
}; |
|
|
|
export function Confetti(props: ConfettiProps) { |
|
const { element = document.body, onDone = () => null, pieces = 40 } = props; |
|
|
|
const [confettiPos, setConfettiPos] = useState< |
|
undefined | ConfettiPosition |
|
>(); |
|
|
|
function populateConfettiPosition(element: HTMLElement) { |
|
const elRect = element.getBoundingClientRect(); |
|
|
|
// set confetti position, keeping in mind the scroll values |
|
setConfettiPos({ |
|
x: elRect?.x || 0, |
|
y: (elRect?.y || 0) + window.scrollY, |
|
w: elRect?.width || 0, |
|
h: elRect?.height || 0, |
|
}); |
|
} |
|
|
|
useEffect(() => { |
|
if (!element) { |
|
setConfettiPos(undefined); |
|
return; |
|
} |
|
|
|
populateConfettiPosition(element); |
|
}, [element]); |
|
|
|
if (!confettiPos) { |
|
return null; |
|
} |
|
|
|
return ( |
|
<ReactConfetti |
|
height={document.body.scrollHeight} |
|
numberOfPieces={pieces} |
|
recycle={false} |
|
onConfettiComplete={(confettiInstance) => { |
|
setConfettiPos(undefined); |
|
onDone(); |
|
}} |
|
initialVelocityX={4} |
|
initialVelocityY={8} |
|
tweenDuration={10} |
|
confettiSource={{ |
|
x: confettiPos.x, |
|
y: confettiPos.y, |
|
w: confettiPos.w, |
|
h: confettiPos.h, |
|
}} |
|
/> |
|
); |
|
}
|
|
|