@phazr/custom-cursor
Version:
A lightweight and highly customizable React component for creating unique and interactive cursor experiences.
148 lines (143 loc) • 5.67 kB
JavaScript
'use client';
;
var jsxRuntime = require('react/jsx-runtime');
var react = require('react');
var react$1 = require('motion/react');
const CursorContext = react.createContext(null);
const useCursor = () => {
const context = react.useContext(CursorContext);
if (!context) {
throw new Error('useCursor must be used within a CursorProvider');
}
return context;
};
function CursorProvider({ children, className = '', enableOnTouch = false, }) {
const [variant, setVariant] = react.useState('default');
const [customConfig, setCustomConfig] = react.useState();
const [isTouchDevice, setIsTouchDevice] = react.useState(false);
react.useEffect(() => {
const checkTouchDevice = () => {
setIsTouchDevice('ontouchstart' in window || navigator.maxTouchPoints > 0);
};
checkTouchDevice();
window.addEventListener('resize', checkTouchDevice);
return () => window.removeEventListener('resize', checkTouchDevice);
}, []);
react.useEffect(() => {
if (isTouchDevice && !enableOnTouch) {
return;
}
if (variant !== 'input') {
document.body.classList.add('phazr-cursor-none');
}
else {
document.body.classList.remove('phazr-cursor-none');
}
return () => {
document.body.classList.remove('phazr-cursor-none');
};
}, [variant, isTouchDevice, enableOnTouch]);
const setVariantCallback = react.useCallback((newVariant) => {
setVariant(newVariant);
}, []);
const setCustomConfigCallback = react.useCallback((config) => {
setCustomConfig(config);
}, []);
if (isTouchDevice && !enableOnTouch) {
return jsxRuntime.jsx("div", { className: className, children: children });
}
return (jsxRuntime.jsx(CursorContext.Provider, { value: {
variant,
setVariant: setVariantCallback,
customConfig,
setCustomConfig: setCustomConfigCallback,
}, children: jsxRuntime.jsx("div", { className: className, children: children }) }));
}
function Cursor({ className = '', springConfig = { damping: 28, stiffness: 500 }, }) {
const { variant, customConfig } = useCursor();
const [isTouchDevice, setIsTouchDevice] = react.useState(false);
const cursorX = react$1.useMotionValue(-100);
const cursorY = react$1.useMotionValue(-100);
const cursorXSpring = react$1.useSpring(cursorX, springConfig);
const cursorYSpring = react$1.useSpring(cursorY, springConfig);
react.useEffect(() => {
setIsTouchDevice('ontouchstart' in window || navigator.maxTouchPoints > 0);
}, []);
react.useEffect(() => {
if (isTouchDevice)
return;
const mouseMove = (e) => {
cursorX.set(e.clientX);
cursorY.set(e.clientY);
};
window.addEventListener('mousemove', mouseMove);
return () => {
window.removeEventListener('mousemove', mouseMove);
};
}, [cursorX, cursorY, isTouchDevice]);
if (isTouchDevice) {
return null;
}
const cursorVariants = {
default: {
height: 16,
width: 16,
backgroundColor: '#fff',
mixBlendMode: 'difference',
},
link: {
height: 64,
width: 64,
backgroundColor: '#fff',
mixBlendMode: 'difference',
},
text: {
height: 8,
width: 8,
backgroundColor: '#fff',
mixBlendMode: 'difference',
},
input: {
height: 0,
width: 0,
opacity: 0,
},
sayHi: {
height: 90,
width: 90,
backgroundColor: '#fff',
mixBlendMode: 'difference',
},
custom: {
height: customConfig?.size || 32,
width: customConfig?.size || 32,
backgroundColor: customConfig?.backgroundColor || '#fff',
mixBlendMode: customConfig?.mixBlendMode || 'difference',
},
};
const textVariants = {
default: { opacity: 0, transition: { duration: 0.1 } },
link: { opacity: 0, transition: { duration: 0.1 } },
text: { opacity: 0, transition: { duration: 0.1 } },
input: { opacity: 0, transition: { duration: 0.1 } },
sayHi: { opacity: 1, transition: { delay: 0.1 } },
custom: {
opacity: customConfig?.text ? 1 : 0,
transition: { delay: customConfig?.text ? 0.1 : 0 },
},
};
return (jsxRuntime.jsx(react$1.motion.div, { variants: cursorVariants, animate: variant, style: {
left: cursorXSpring,
top: cursorYSpring,
x: '-50%',
y: '-50%',
}, className: `phazr-cursor-container ${className}`, children: jsxRuntime.jsxs(react$1.motion.div, { variants: textVariants, animate: variant, className: "phazr-cursor-text", style: {
color: customConfig?.textColor || '#000',
fontSize: customConfig?.fontSize || '16px',
fontFamily: customConfig?.fontFamily || 'inherit',
}, children: [variant === 'sayHi' && (jsxRuntime.jsxs("div", { className: "phazr-cursor-sayhi", children: [jsxRuntime.jsx("span", { children: "Say" }), jsxRuntime.jsx("span", { children: "Hi" })] })), variant === 'custom' && customConfig?.text && (jsxRuntime.jsx("span", { children: customConfig.text }))] }) }));
}
exports.Cursor = Cursor;
exports.CursorProvider = CursorProvider;
exports.useCursor = useCursor;
//# sourceMappingURL=index.js.map