Skip to content

Commit

Permalink
Merge pull request #1 from Adnan-S-Husain/zustand-store-implementation
Browse files Browse the repository at this point in the history
zustand store implementation
  • Loading branch information
adnan-td committed Nov 23, 2023
2 parents be0b8ed + 16c4e1e commit cdc0b5b
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 273 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-mouse-follower",
"version": "1.1.7",
"version": "2.0.1",
"description": "React mouse follower is a package based on react and framer motion. It provides components to add and customise cool mouse follower to your cursor",
"repository": {
"type": "git",
Expand All @@ -25,7 +25,8 @@
"chromatic": "chromatic --exit-zero-on-changes"
},
"dependencies": {
"framer-motion": "^10.12.18"
"framer-motion": "^10.12.18",
"zustand": "^4.4.1"
},
"peerDependencies": {
"react": "^18.2.0",
Expand Down
5 changes: 5 additions & 0 deletions src/component/follower.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FollowerInitialiserComponent } from './follower_init.js';

export function Follower() {
return <FollowerInitialiserComponent />;
}
70 changes: 42 additions & 28 deletions src/component/follower_div.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { MousePosition, MouseSettings } from '../types/index.js';
import { motion } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';

export function FollowerDiv({ pos, options }: { pos: MousePosition; options: MouseSettings }) {
const calculatePosition = (): MousePosition => {
if (options.customLocation != undefined) {
if (options.customLocation != null) {
return { x: options.customLocation.x, y: options.customLocation.y };
} else if (options.customPosition != undefined) {
} else if (options.customPosition != null) {
const rect = options.customPosition.current.getBoundingClientRect();
const x = rect.left + rect.width / 2 - options.radius;
const y = rect.top + rect.height / 2 - options.radius;
const radius = options.radius ? options.radius : 12 / 2;
const x = rect.left + rect.width / 2 - radius;
const y = rect.top + rect.height / 2 - radius;
return { x, y };
} else {
return { x: pos.x, y: pos.y };
Expand All @@ -20,22 +21,20 @@ export function FollowerDiv({ pos, options }: { pos: MousePosition; options: Mou
x: pos.x,
y: pos.y,
scale: 0,
backgroundColor: options.backgroundColor || 'black',
zIndex: options.zIndex || -5,
mixBlendMode: options.mixBlendMode || 'initial',
}}
animate={{
x: calculatePosition().x,
y: calculatePosition().y,
scale: options.scale || 1,
scale: options.scale != null ? options.scale : 1,
rotate: options.rotate || 0,
}}
exit={{
x: pos.x,
y: pos.y,
scale: 0,
}}
style={{
backgroundColor: options.backgroundColor || 'black',
mixBlendMode: options.mixBlendMode || 'initial',
zIndex: options.zIndex || -5,
mixBlendMode: options.mixBlendMode || 'initial',
}}
style={{
position: 'fixed',
inset: 0,
pointerEvents: 'none',
Expand Down Expand Up @@ -72,21 +71,36 @@ export function FollowerDiv({ pos, options }: { pos: MousePosition; options: Mou
}}
>
{options.text && !options.backgroundElement ? (
<p
style={{
width: '85%',
textAlign: 'center',
lineHeight: options.textLineHeight,
letterSpacing: options.textLetterSpacing,
fontFamily: options.textFontFamily,
fontSize: options.textFontSize ? options.textFontSize : '12px',
color: options.textColor ? options.textColor : 'white',
}}
>
{options.text}
</p>
<AnimatePresence mode="wait">
<motion.p
animate={{ opacity: 1 }}
exit={{ opacity: 0.3 }}
transition={{ type: 'tween', duration: options.followSpeed ? 0.3 / options.followSpeed : 0.3, ease: 'circOut' }}
style={{
width: '85%',
textAlign: 'center',
lineHeight: options.textLineHeight,
letterSpacing: options.textLetterSpacing,
fontFamily: options.textFontFamily,
fontSize: options.textFontSize ? options.textFontSize : '12px',
color: options.textColor ? options.textColor : 'white',
}}
>
{options.text}
</motion.p>
</AnimatePresence>
) : null}
{options.backgroundElement ? options.backgroundElement : null}
<AnimatePresence mode="wait">
{options.backgroundElement ? (
<motion.div
animate={{ opacity: 1 }}
exit={{ opacity: 0.3 }}
transition={{ type: 'tween', duration: options.followSpeed ? 0.3 / options.followSpeed : 0.3, ease: 'circOut' }}
>
{options.backgroundElement}
</motion.div>
) : null}
</AnimatePresence>
</div>
</div>
</motion.div>
Expand Down
39 changes: 29 additions & 10 deletions src/component/follower_init.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useEffect, useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import type { MousePosition, MouseSettings } from '../types/index.js';
import { MouseSettings, type MousePosition } from '../types/index.js';
import { FollowerDiv } from './follower_div.js';
import useMouseStore from '../store/index.js';
import { AnimatePresence } from 'framer-motion';

const defaultRadius = 12 / 2;

export function FollowerInitialiserComponent({ options }: { options: MouseSettings }) {
export function FollowerInitialiserComponent() {
const [isHovering, setIsHovering] = useState<boolean>(false);
const options = useMouseStore((store) => store.curSettings);

useEffect(() => {
const handleMouseLeave = () => {
Expand All @@ -25,26 +29,41 @@ export function FollowerInitialiserComponent({ options }: { options: MouseSettin
};
}, []);

return <PositionHandler options={options} show={isHovering && options.visible !== false} />;
return (
<ManagePosition options={!isHovering ? { ...options, scale: 0, customLocation: null, customPosition: null } : options} />
);
}

function PositionHandler({ options, show }: { options: MouseSettings; show: boolean }) {
function ManagePosition({ options }: { options: MouseSettings }) {

const [pos, setPos] = useState<MousePosition>({
x: 0,
y: 0,
});

useEffect(() => {
const mouseMove = (event: any) => {
setPos({
x: event.clientX - options.radius,
y: event.clientY - options.radius,
});
if (options.radius != null) {
setPos({
x: event.clientX - options.radius,
y: event.clientY - options.radius,
});
} else {
setPos({
x: event.clientX - defaultRadius,
y: event.clientY - defaultRadius,
});
}
};
window.addEventListener('mousemove', mouseMove);
return () => {
window.removeEventListener('mousemove', mouseMove);
};
}, [options?.radius]);

return <AnimatePresence mode="wait">{show ? <FollowerDiv options={options} pos={pos} /> : null}</AnimatePresence>;
return (
<AnimatePresence mode="wait">
{options.visible !== false ? <FollowerDiv options={options} pos={pos} /> : null}
</AnimatePresence>
);
}
1 change: 1 addition & 0 deletions src/component/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './update_follower.js';
export * from './follower.js';
4 changes: 2 additions & 2 deletions src/component/update_follower.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CSSProperties, ReactNode, useContext } from 'react';
import { MousePropertiesContext } from '../context/mouse.context.js';
import { MouseSettings } from '../types/index.js';
import useMouseStore from '../store/index.js';

export function UpdateFollower({
mouseOptions,
Expand All @@ -19,7 +19,7 @@ export function UpdateFollower({
onClick?: () => void;
children?: ReactNode;
}) {
const { addLayer, removeLayer } = useContext(MousePropertiesContext);
const { addLayer, removeLayer } = useMouseStore((state) => ({ addLayer: state.pushLayer, removeLayer: state.popLayer }));
function handleMouseEnter() {
addLayer(mouseOptions);
if (onMouseEnter) {
Expand Down
3 changes: 0 additions & 3 deletions src/context/index.ts

This file was deleted.

41 changes: 0 additions & 41 deletions src/context/mouse.context.tsx

This file was deleted.

17 changes: 9 additions & 8 deletions src/hook/control_options.hook.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useContext } from 'react';
import { MousePropertiesContext } from '../context/mouse.context.js';
import useMouseStore from '../store/index.js';

export function useControlOptions() {
const { addLayer, removeLayer, clearStack, logStack, peekStack } = useContext(MousePropertiesContext);
const store = useMouseStore((state) => ({
addOptionLayer: state.pushLayer,
removePreviousLayer: state.popLayer,
clearLayers: state.clearLayers,
}));

return {
addOptionLayer: addLayer,
removePreviousLayer: removeLayer,
clearLayers: clearStack,
logLayers: logStack,
topLayer: peekStack,
// logLayers: logStack,
...store,
};
}
80 changes: 0 additions & 80 deletions src/hook/stack.hook.tsx

This file was deleted.

1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './component/index.js';
export * from './context/index.js';
export * from './hook/index.js';
Loading

0 comments on commit cdc0b5b

Please sign in to comment.