@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
122 lines (116 loc) • 4.5 kB
JavaScript
"use client";
;
var jsxRuntime = require('react/jsx-runtime');
var hooks = require('@nex-ui/hooks');
var utils = require('@nex-ui/utils');
var react$1 = require('motion/react');
var m = require('motion/react-m');
var react = require('react');
var client = require('react-dom/client');
var index = require('../motionFeatures/index.cjs');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var m__namespace = /*#__PURE__*/_interopNamespace(m);
const useRippleMotion = (props)=>{
const { motionProps, motionStyle } = props ?? {};
const rootRef = react.useRef(null);
const ripplesRef = react.useRef([]);
return hooks.useEvent((event)=>{
const trigger = event.currentTarget;
if (!rootRef.current) {
const div = document.createElement('div');
div.style.position = 'absolute';
div.style.left = '0';
div.style.top = '0';
const root = client.createRoot(div);
trigger.insertBefore(div, trigger.firstChild);
// @ts-expect-error
root.stateNode = div;
rootRef.current = root;
}
const { width, height, top, left } = trigger.getBoundingClientRect();
const rippleSize = Math.max(width, height);
let x;
let y;
if (event.clientX !== 0 && event.clientY !== 0) {
x = event.clientX - left;
y = event.clientY - top;
} else {
x = width / 2;
y = height / 2;
}
ripplesRef.current.push({
key: `${Math.random()}`,
size: rippleSize,
x: x - rippleSize / 2,
y: y - rippleSize / 2
});
rootRef.current.render(/*#__PURE__*/ jsxRuntime.jsx(react$1.LazyMotion, {
features: index.motionFeatures,
children: ripplesRef.current.map((ripple)=>{
const duration = utils.clamp(0.01 * ripple.size, 0.2, ripple.size > 100 ? 0.75 : 0.5);
return /*#__PURE__*/ jsxRuntime.jsx(react$1.AnimatePresence, {
mode: "popLayout",
children: /*#__PURE__*/ jsxRuntime.jsx(m__namespace.span, {
animate: {
transform: 'scale(2)',
opacity: 0
},
className: "nui-ripple",
exit: {
opacity: 0
},
initial: {
transform: 'scale(0)',
opacity: 0.35
},
style: {
position: 'absolute',
backgroundColor: 'currentcolor',
borderRadius: '100%',
transformOrigin: 'center',
pointerEvents: 'none',
overflow: 'hidden',
inset: 0,
zIndex: 0,
top: ripple.y,
left: ripple.x,
width: `${ripple.size}px`,
height: `${ripple.size}px`,
...motionStyle
},
transition: {
duration
},
onAnimationComplete: ()=>{
ripplesRef.current = ripplesRef.current.filter(({ key })=>ripple.key !== key);
if (!ripplesRef.current.length) {
rootRef.current?.unmount();
// @ts-expect-error
trigger.removeChild(rootRef.current.stateNode);
rootRef.current = null;
}
},
...motionProps
})
}, ripple.key);
})
}));
});
};
exports.useRippleMotion = useRippleMotion;