UNPKG

@front-ui/use-ripple

Version:

This hook is used to add ripple effect in all elements except void elements

93 lines (91 loc) 3.17 kB
"use client"; "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { useRipple: () => useRipple }); module.exports = __toCommonJS(src_exports); var import_react = require("react"); var useRipple = (props = { duration: 500, timingFunction: "cubic-bezier(.42,.36,.28,.88)", disabled: false, completedFactor: 0.5 }) => { const ref = (0, import_react.useRef)(null); const { disabled, duration, completedFactor } = props; const event = (0, import_react.useCallback)((event2) => { if (!ref.current || disabled || event2.button !== 0) return; const target = ref.current; requestAnimationFrame(() => { const begun = Date.now(); const ripple = createRipple(target, event2, props); target.appendChild(ripple); const removeRipple = () => { const now = Date.now(); const diff = now - begun; setTimeout( () => { ripple.style.opacity = "0"; ripple.addEventListener("transitionend", (e) => { if (e.propertyName === "opacity") ripple.remove(); }); }, diff > completedFactor * duration ? 0 : completedFactor * duration - diff ); }; document.addEventListener("pointerup", removeRipple, { once: true }); }); }, []); return [ref, event]; }; var createRipple = (target, event, options) => { const { clientX, clientY } = event; const { height, width, top, left } = target.getBoundingClientRect(); const maxHeight = Math.max(clientY - top, height - clientY + top); const maxWidth = Math.max(clientX - left, width - clientX + left); const size = Math.hypot(maxHeight, maxWidth) * 2; const element = document.createElement("span"); const { duration, timingFunction } = options; element.style.cssText = ` position: absolute; top: ${event.clientY - top}px; left: ${event.clientX - left}px; height: ${size}px; width: ${size}px; translate: -50% -50%; pointer-events: none; border-radius: 50%; background-color: var(--rippleBg); scale: 0; transition: scale ${duration}ms ${timingFunction}, opacity ${duration * 0.7}ms ease-in-out; `; requestAnimationFrame(() => { element.style.scale = "1"; }); return element; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { useRipple });