Skip to content

Commit

Permalink
logic and basic stories added
Browse files Browse the repository at this point in the history
  • Loading branch information
adnan-td committed Jun 24, 2023
1 parent d0c8484 commit f602e14
Show file tree
Hide file tree
Showing 12 changed files with 415 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"singleQuote": true,
"printWidth": 200,
"printWidth": 130,
"proseWrap": "always",
"tabWidth": 2,
"useTabs": false,
Expand Down
67 changes: 67 additions & 0 deletions src/component/follower_div.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { MousePosition, MouseSettings } from '../types';
import { motion } from 'framer-motion';

export function FollowerDiv({ pos, options, radius }: { pos: MousePosition; options: MouseSettings; radius?: number }) {
return (
<motion.div
initial={{
x: pos.x,
y: pos.y,
scale: 0,
}}
animate={{
x: options.customPosition ? options.customPosition.x : pos.x,
y: options.customPosition ? options.customPosition.y : pos.y,
scale: options.scale || 1,
rotate: options.rotate || 0,
}}
exit={{
x: pos.x,
y: pos.y,
scale: 0,
}}
style={{
backgroundColor: options.inverted ? 'white' : options.backgroundColor || 'black',
mixBlendMode: options.mixBlendMode || 'initial',
zIndex: options.zIndex || -5,
position: 'fixed',
inset: 0,
pointerEvents: 'none',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 'min-content',
height: 'min-content',
borderRadius: '9999px',
overflow: 'hidden',
}}
transition={{ type: 'tween', duration: 0.3, ease: 'circOut' }}
id="mouse-follower"
>
<div
style={{
width: `${radius ? radius * 2 : 12}px`,
height: `${radius ? radius * 2 : 12}px`,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent',
}}
>
<div
style={{
width: '100%',
height: '100%',
borderRadius: '9999px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
}}
>
{options.backgroundElement ? options.backgroundElement : null}
</div>
</div>
</motion.div>
);
}
50 changes: 50 additions & 0 deletions src/component/follower_init.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect, useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import type { MousePosition, MouseSettings } from '../types';
import { FollowerDiv } from './follower_div';

export function FollowerInitialiserComponent({ options, radius }: { options: MouseSettings; radius: number }) {
const [isHovering, setIsHovering] = useState<boolean>(false);
const [pos, setPos] = useState<MousePosition>({
x: 0,
y: 0,
});

useEffect(() => {
const handleMouseLeave = () => {
setIsHovering(false);
};

const handleMouseEnter = () => {
setIsHovering(true);
};

const body = document.querySelector('body');
body.addEventListener('mouseleave', handleMouseLeave);
body.addEventListener('mouseenter', handleMouseEnter);

return () => {
body.removeEventListener('mouseleave', handleMouseLeave);
body.removeEventListener('mouseenter', handleMouseEnter);
};
}, []);

useEffect(() => {
function mouseMove(event: any) {
setPos({
x: event.clientX - radius,
y: event.clientY - radius,
});
}
window.addEventListener('mousemove', mouseMove);
return () => {
window.removeEventListener('mousemove', mouseMove);
};
}, []);

return (
<AnimatePresence mode="wait">
{isHovering ? <FollowerDiv options={options} pos={pos} radius={radius} /> : null}
</AnimatePresence>
);
}
5 changes: 3 additions & 2 deletions src/component/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './Button';
export * from './mouse_circle';
export * from './follower_init';
export * from './update_follower';
export * from './follower_div';
83 changes: 0 additions & 83 deletions src/component/mouse_circle.tsx

This file was deleted.

30 changes: 30 additions & 0 deletions src/component/update_follower.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CSSProperties, ReactNode, useContext, useState } from 'react';
import { MousePropertiesContext } from '..';
import { MouseSettings } from '../types';

export function UpdateFollower({
mouseOptions,
style,
className,
children,
}: {
mouseOptions: MouseSettings;
style: CSSProperties;
className: string;
children: ReactNode;
}) {
const { addLayer, removeLayer } = useContext(MousePropertiesContext);
const [id, setId] = useState(1000);
function handleMouseEnter() {
const id = addLayer(mouseOptions);
setId(id);
}
function handleMouseLeave() {
removeLayer(id);
}
return (
<div style={style} className={className} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
{children}
</div>
);
}
58 changes: 37 additions & 21 deletions src/context/mouse.context.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,52 @@
import { useState, createContext, ReactNode, CSSProperties } from 'react';
import type { MousePosition, Props } from '../types';
import { useState, createContext } from 'react';
import { FollowerInitialiserComponent } from '..';
import { Stack } from '../util/stack';

import type { Props, MouseSettings } from '../types';

interface ContextInterface {
options: MouseSettings;
setOptions: (options: MouseSettings) => void;
radius: number;
addLayer: (options: MouseSettings) => number;
removeLayer: (id: number) => void;
}

export interface MouseSettings {
zIndex?: CSSProperties['zIndex'];
backgroundColor?: CSSProperties['backgroundColor'];
backgroundElement?: JSX.Element;
scale?: number;
rotate?: number;
customPosition?: MousePosition;
mixBlendMode?: CSSProperties['mixBlendMode'];
invert?: boolean;
}
const defaultProperties = {
inverted: false,
};

export const MousePropertiesContext = createContext<ContextInterface>(null);

export const MousePropertiesProvider = ({ children }: Props) => {
const radius = 12 / 2;
export const FollowerProvider = ({ children }: Props) => {
const radius: number = 12 / 2;
const layerStack = new Stack();
const [options, setOptions] = useState<MouseSettings>(defaultProperties);

const [options, setOptions] = useState<MouseSettings>({
invert: false,
});
const addLayer = (layerOptions: MouseSettings): number => {
const properties = { ...options, ...layerOptions };
const id = layerStack.push(properties);
setOptions(properties);
return id;
};

const value = {
const removeLayer = (id: number) => {
const previousOptions = layerStack.pop(id);
if (previousOptions) {
setOptions(previousOptions);
}
};

const value: ContextInterface = {
options,
setOptions,
radius,
addLayer,
removeLayer,
};
return <MousePropertiesContext.Provider value={value}>{children}</MousePropertiesContext.Provider>;

return (
<MousePropertiesContext.Provider value={value}>
<FollowerInitialiserComponent options={options} radius={radius} />
{children}
</MousePropertiesContext.Provider>
);
};
Binary file added src/stories/assets/main_bg.mp4
Binary file not shown.
32 changes: 32 additions & 0 deletions src/stories/follower_basic.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';

import { FollowerProvider, FollowerInitialiserComponent, FollowerDiv } from '../index';

const meta: Meta<typeof FollowerInitialiserComponent> = {
component: FollowerInitialiserComponent,
decorators: [
(Story) => (
<div
style={{
width: '100vw',
height: '100vh',
overflow: 'hidden',
}}
>
<FollowerProvider>
<Story />
</FollowerProvider>
</div>
),
],
};

export default meta;
type Story = StoryObj<typeof FollowerDiv>;

export const Default: Story = {
render: () => {
return <div></div>;
},
};
Loading

0 comments on commit f602e14

Please sign in to comment.