UNPKG

@easy-shadcn/react

Version:

Use shadcn/ui easy&enhance like component library

161 lines (158 loc) 4.86 kB
import { Button } from './chunk-KWT7SCRZ.mjs'; import * as React from 'react'; import React__default, { useState } from 'react'; import { cn } from '@easy-shadcn/utils'; import { AnimatePresence, motion } from 'motion/react'; import { jsxs, jsx } from 'react/jsx-runtime'; var Ripple = ({ color = "rgb(255 255 255 / 0.5)", rippleRef }) => { const [ripples, setRipples] = React.useState([]); const showRipple = React.useCallback((event) => { const container = event.currentTarget; if (!container) return; const rect = container.getBoundingClientRect(); const x = event.clientX - rect.left; const y = event.clientY - rect.top; const size = Math.max(rect.width, rect.height) * 2; setRipples((prev) => [ ...prev, { x, y, size, id: Date.now() } ]); }, []); React.useImperativeHandle(rippleRef, () => ({ showRipple })); React.useEffect(() => { const timeouts = ripples.map((ripple) => { return setTimeout(() => { setRipples((prev) => prev.filter((r) => r.id !== ripple.id)); }, 1e3); }); return () => { timeouts.forEach(clearTimeout); }; }, [ripples]); return /* @__PURE__ */ jsx("div", { className: cn("absolute inset-0 pointer-events-none z-10"), role: "presentation", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "sync", children: ripples.map((ripple) => /* @__PURE__ */ jsx( motion.span, { className: "absolute rounded-full", style: { left: ripple.x - ripple.size / 2, top: ripple.y - ripple.size / 2, width: `${ripple.size}px`, height: `${ripple.size}px`, backgroundColor: color }, initial: { scale: 0, opacity: 0.5 }, animate: { scale: 1, opacity: 0 }, transition: { duration: 0.75, ease: [0.4, 0, 0.2, 1] }, exit: { opacity: 0 } }, ripple.id )) }) }); }; Ripple.displayName = "Ripple"; var BlackRipple = "rgb(0 0 0 / 0.3)"; var WhiteRipple = "rgb(255 255 255 / 0.3)"; var getRippleColor = (variant) => { if (["outline", "ghost", "secondary"].includes(variant || "")) { return BlackRipple; } return WhiteRipple; }; var RippleButton = React.forwardRef( ({ className, children, onMouseDown, variant, ...props }, ref) => { const rippleRef = React.useRef(null); return /* @__PURE__ */ jsxs( Button, { ref, className: cn("relative overflow-hidden", className), onMouseDown: (e) => { onMouseDown?.(e); rippleRef.current?.showRipple(e); }, variant, ...props, children: [ /* @__PURE__ */ jsx(Ripple, { color: getRippleColor(variant), rippleRef }), children ] } ); } ); RippleButton.displayName = "RippleButton"; var LoadingIcon = (props) => /* @__PURE__ */ jsx( "svg", { xmlns: "http://www.w3.org/2000/svg", width: "1em", height: "1em", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", ...props, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) } ); var Button2 = React__default.forwardRef( ({ icon, iconPosition, loading, disabled, onClick, children, size, className, ...resetProps }, ref) => { const [isLoading, setIsLoading] = useState(false); const handleClick = (e) => { if (onClick) { const clickPromise = onClick(e); if (clickPromise instanceof Promise) { setIsLoading(true); clickPromise.catch(() => { }).finally(() => { setIsLoading(false); }); } } }; const innerLoading = loading || isLoading; let iconNode = null; let content = null; if (size === "icon") { iconNode = innerLoading ? /* @__PURE__ */ jsx(LoadingIcon, { className: "animate-spin" }) : children; } else { iconNode = innerLoading ? /* @__PURE__ */ jsx(LoadingIcon, { className: "animate-spin" }) : icon; content = children; } return /* @__PURE__ */ jsxs( RippleButton, { ref, ...resetProps, size, disabled: innerLoading || disabled, onClick: handleClick, className: cn( iconPosition === "end" && "flex-row-reverse", "[&_svg]:size-[1em]", className ), children: [ iconNode ? /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx("span", { role: "img", className: "inline-flex items-center align-[-0.125em]", children: iconNode }) }) : null, content ? /* @__PURE__ */ jsx("span", { className: "truncate", children: content }) : null ] } ); } ); Button2.displayName = "Button"; export { Button2 as Button };