UNPKG

@poupe/vue

Version:

Vue component library for Poupe UI framework with theme customization and accessibility support

77 lines (73 loc) 2.2 kB
import { onMounted, onUnmounted, ref, unref } from "vue"; export function useRipple(elementReference, options = {}) { const { color = "currentColor", opacity = .12, duration = 600, bounded = true, disabled = false } = options; const ripples = ref([]); let rippleId = 0; const addRipple = (event) => { if (unref(disabled) || !elementReference.value) return; const element = elementReference.value; const rect = element.getBoundingClientRect(); let x; let y; if (event instanceof MouseEvent) { x = event.clientX - rect.left; y = event.clientY - rect.top; } else { const touch = event.touches[0]; if (!touch) return; x = touch.clientX - rect.left; y = touch.clientY - rect.top; } const sizeX = Math.max(x, rect.width - x); const sizeY = Math.max(y, rect.height - y); const size = Math.hypot(sizeX, sizeY) * 2; const id = rippleId++; const ripple = { x, y, size, id }; ripples.value.push(ripple); setTimeout(() => { ripples.value = ripples.value.filter((r) => r.id !== id); }, duration); }; const handleMouseDown = (event) => { addRipple(event); }; const handleTouchStart = (event) => { addRipple(event); }; onMounted(() => { if (!elementReference.value || unref(disabled)) return; elementReference.value.addEventListener("mousedown", handleMouseDown); elementReference.value.addEventListener("touchstart", handleTouchStart, { passive: true }); elementReference.value.style.position = "relative"; elementReference.value.style.overflow = bounded ? "hidden" : "visible"; }); onUnmounted(() => { if (!elementReference.value) return; elementReference.value.removeEventListener("mousedown", handleMouseDown); elementReference.value.removeEventListener("touchstart", handleTouchStart); }); const getRippleStyle = (ripple) => { return { position: "absolute", left: `${ripple.x}px`, top: `${ripple.y}px`, width: `${ripple.size}px`, height: `${ripple.size}px`, transform: "translate(-50%, -50%)", borderRadius: "50%", backgroundColor: color, opacity, pointerEvents: "none", animation: `ripple ${duration}ms ease-out` }; }; return { ripples, getRippleStyle }; }