nuxt-ripple
Version:
Add simple ripple effects to your elements
115 lines (114 loc) • 5.01 kB
JavaScript
var RippleEvent = /* @__PURE__ */ ((RippleEvent2) => {
RippleEvent2["CLICK"] = "mousedown";
RippleEvent2["HOVER"] = "mouseover";
RippleEvent2["TRANSITION_END"] = "transitionend";
return RippleEvent2;
})(RippleEvent || {});
const cssTextBuilder = (options) => Object.entries(options).filter(([_, value]) => value !== void 0).map(([key, value]) => `${key}: ${value};`).join("");
const applyEffects = (el, styles, endTransition) => {
el.style.cssText = cssTextBuilder(styles);
if (endTransition) {
el.addEventListener("transitionend" /* TRANSITION_END */, (event) => {
const target = event.target;
if (event.propertyName === "opacity" && target.className === "nuxt-ripple-animation")
el.remove();
}, { once: true });
} else void el.offsetTop;
};
export const addHeadStyles = (config) => {
const styleId = "nuxt-ripple-styles";
const styleContent = `[data-ripple-bound="true"]{overflow: ${config.overflow === true ? "visible" : "hidden"};}[data-ripple-bound="true"] .nuxt-ripple-animation{background-color: var(--nuxt-ripple-background-color, ${config.color});transition: calc(var(--t, 0) * var(--nuxt-ripple-duration, ${config.duration}ms)) linear;transform: translate(-50%, -50%) scale(var(--s, ${config.scale}));}[data-ripple-bound="true"].nuxt-ripple-pulse .nuxt-ripple-animation{background-color: var(--nuxt-ripple-background-color, ${config.color});}`;
const rippeStyles = document.getElementById(styleId);
if (!rippeStyles) {
const addStyle = document.createElement("style");
addStyle.id = styleId;
addStyle.innerHTML = styleContent;
document.head.appendChild(addStyle);
} else {
rippeStyles.innerHTML = styleContent;
}
};
const addRippleElement = (el) => {
const ripple = document.createElement("span");
el.appendChild(ripple);
ripple.classList.add("nuxt-ripple-animation");
return ripple;
};
export const animationHandler = (e, el) => {
const { clientX, clientY } = e.touches?.[0] || e;
const { left, top, width, height } = el.getBoundingClientRect();
const rippleColor = el.getAttribute("data-ripple-color");
const rippleDuration = el.getAttribute("data-ripple-duration");
const rippleScale = el.getAttribute("data-ripple-scale");
const rippleEl = addRippleElement(el);
applyEffects(rippleEl, {
"--s": 0,
"--o": 1,
...rippleColor ? { "--nuxt-ripple-background-color": rippleColor } : {}
});
applyEffects(rippleEl, {
"--t": 1,
"--o": 0,
"--d": Math.sqrt(width ** 2 + height ** 2) * 2,
"--x": clientX - left,
"--y": clientY - top,
...rippleScale ? { "--s": Number(rippleScale) } : {},
...rippleColor ? { "--nuxt-ripple-background-color": rippleColor } : {},
...rippleDuration ? { "--nuxt-ripple-duration": String(rippleDuration) + "ms" } : {}
}, true);
};
export const unmountListeners = (el, listeners, intervals) => {
if (listeners.has(el) || intervals.has(el)) {
const removeListener = listeners.get(el);
if (removeListener) {
el.removeEventListener("mouseover" /* HOVER */, removeListener);
el.removeEventListener("mousedown" /* CLICK */, removeListener);
listeners.delete(el);
}
const interval = intervals.get(el);
if (intervals.get(el)) {
clearInterval(interval);
intervals.delete(el);
}
}
};
export const modeHandler = (el, config, listeners, intervals) => {
if (listeners.has(el)) return;
el.classList.remove("nuxt-ripple-pulse");
const rippleMode = el.getAttribute("data-ripple-mode");
const ripplepulseInterval = Number(el.getAttribute("data-ripple-pulseInterval")) || config.pulseInterval;
const rippleColor = el.getAttribute("data-ripple-color");
const rippleScale = el.getAttribute("data-ripple-scale");
const eventHandler = (e) => animationHandler(e, el);
if (config.mode === "hover" && !rippleMode || rippleMode === "hover") {
el.addEventListener("mouseover" /* HOVER */, eventHandler);
listeners.set(el, eventHandler);
} else if (config.mode === "pulse" && !rippleMode || rippleMode === "pulse") {
el.classList.add("nuxt-ripple-pulse");
intervals.set(el, setInterval(() => {
const { width, height } = el.getBoundingClientRect();
const rippleEl = addRippleElement(el);
applyEffects(rippleEl, {
"--s": 0,
"--o": 1,
...rippleColor ? { "--nuxt-ripple-background-color": rippleColor } : {}
});
applyEffects(rippleEl, {
"--t": 1,
"--o": 0,
"--d": Math.sqrt(width ** 2 + height ** 2) * 2,
...rippleScale ? { "--s": Number(rippleScale) } : {},
...rippleColor ? { "--nuxt-ripple-background-color": rippleColor } : {}
}, true);
}, ripplepulseInterval));
} else {
el.addEventListener("mousedown" /* CLICK */, eventHandler);
listeners.set(el, eventHandler);
}
};
export const setAttributes = (el, values) => {
if (!values) return;
for (const [key, value] of Object.entries(values)) {
el.setAttribute(`data-ripple-${key}`, String(value));
}
};