@pelatform/ui 1.5.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,196 @@
1
+ 'use client';
2
+
3
+ import {
4
+ cn
5
+ } from "./chunk-RQHJBTEU.js";
6
+
7
+ // src/ui/animation/hover-background.tsx
8
+ import * as React from "react";
9
+ import { motion, useMotionValue, useSpring } from "motion/react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function HoverBackground({
12
+ className,
13
+ objectCount = 12,
14
+ children,
15
+ colors = {},
16
+ ...props
17
+ }) {
18
+ const {
19
+ background = "bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900",
20
+ objects = [
21
+ "bg-cyan-400/20",
22
+ "bg-purple-400/20",
23
+ "bg-fuchsia-400/20",
24
+ "bg-violet-400/20",
25
+ "bg-blue-400/20",
26
+ "bg-indigo-400/20"
27
+ ],
28
+ glow = "shadow-cyan-400/50"
29
+ } = colors;
30
+ const [isHovered, setIsHovered] = React.useState(false);
31
+ const mouseX = useMotionValue(0);
32
+ const mouseY = useMotionValue(0);
33
+ const springX = useSpring(mouseX, {
34
+ stiffness: 300,
35
+ damping: 30,
36
+ // Slower return to center when hover ends
37
+ restSpeed: 0.1,
38
+ restDelta: 0.1
39
+ });
40
+ const springY = useSpring(mouseY, {
41
+ stiffness: 300,
42
+ damping: 30,
43
+ restSpeed: 0.1,
44
+ restDelta: 0.1
45
+ });
46
+ const animatedObjects = React.useMemo(
47
+ () => Array.from({ length: objectCount }, (_, i) => {
48
+ const shape = Math.random() > 0.5 ? "circle" : "square";
49
+ return {
50
+ id: i,
51
+ x: Math.random() * 90 + 5,
52
+ // 5-95% to avoid edges
53
+ y: Math.random() * 90 + 5,
54
+ size: Math.random() * 60 + 20,
55
+ // 20-80px
56
+ color: objects[i % objects.length],
57
+ delay: Math.random() * 2,
58
+ shape,
59
+ floatDirection: Math.random() > 0.5 ? 1 : -1,
60
+ breathDuration: Math.random() * 3 + 3,
61
+ // 3-6 seconds
62
+ parallaxStrength: Math.random() * 0.5 + 0.3,
63
+ // 0.3-0.8 for more varied parallax depth
64
+ baseRotation: Math.random() * 360
65
+ // Random starting rotation offset
66
+ };
67
+ }),
68
+ [objectCount, objects]
69
+ );
70
+ const handleMouseMove = (event) => {
71
+ if (!isHovered) return;
72
+ const rect = event.currentTarget.getBoundingClientRect();
73
+ const centerX = rect.width / 2;
74
+ const centerY = rect.height / 2;
75
+ const x = (event.clientX - rect.left - centerX) / centerX;
76
+ const y = (event.clientY - rect.top - centerY) / centerY;
77
+ mouseX.set(x * 15);
78
+ mouseY.set(y * 15);
79
+ };
80
+ const handleHoverStart = () => {
81
+ setIsHovered(true);
82
+ };
83
+ const handleHoverEnd = () => {
84
+ setIsHovered(false);
85
+ mouseX.set(0);
86
+ mouseY.set(0);
87
+ };
88
+ return /* @__PURE__ */ jsxs(
89
+ motion.div,
90
+ {
91
+ "data-slot": "hover-background",
92
+ className: cn("relative size-full overflow-hidden", background, className),
93
+ onHoverStart: handleHoverStart,
94
+ onHoverEnd: handleHoverEnd,
95
+ onMouseMove: handleMouseMove,
96
+ whileHover: { scale: 1.02 },
97
+ transition: { duration: 0.3, ease: "easeOut" },
98
+ animate: {
99
+ backgroundPosition: ["0% 50%", "100% 50%", "0% 50%"]
100
+ },
101
+ style: {
102
+ backgroundSize: "200% 200%"
103
+ },
104
+ ...props,
105
+ children: [
106
+ /* @__PURE__ */ jsx(
107
+ motion.div,
108
+ {
109
+ className: "absolute inset-0 bg-gradient-radial from-white/5 via-transparent to-transparent",
110
+ animate: {
111
+ opacity: [0.3, 0.6, 0.3],
112
+ scale: [1, 1.1, 1]
113
+ },
114
+ transition: {
115
+ duration: 4,
116
+ repeat: Infinity,
117
+ ease: "easeInOut"
118
+ }
119
+ }
120
+ ),
121
+ animatedObjects.map((obj) => /* @__PURE__ */ jsx(
122
+ motion.div,
123
+ {
124
+ className: cn(
125
+ "absolute border border-white/10 backdrop-blur-sm",
126
+ obj.color,
127
+ obj.shape === "circle" ? "rounded-full" : "rotate-45 rounded-lg"
128
+ ),
129
+ style: {
130
+ left: `${obj.x}%`,
131
+ top: `${obj.y}%`,
132
+ width: obj.size,
133
+ height: obj.size,
134
+ // Apply parallax with individual object strength
135
+ x: springX.get() * obj.parallaxStrength,
136
+ y: springY.get() * obj.parallaxStrength
137
+ },
138
+ initial: {
139
+ scale: 0.6,
140
+ opacity: 0.4,
141
+ rotate: obj.baseRotation
142
+ },
143
+ animate: {
144
+ // Default state animations - breathing with base rotation offset
145
+ scale: [0.6, 0.8, 0.6],
146
+ opacity: [0.4, 0.6, 0.4],
147
+ rotate: obj.shape === "circle" ? [obj.baseRotation, obj.baseRotation + 10, obj.baseRotation] : [obj.baseRotation, obj.baseRotation + 5, obj.baseRotation],
148
+ y: [0, obj.floatDirection * 15, 0],
149
+ x: [0, obj.floatDirection * 8, 0]
150
+ },
151
+ transition: {
152
+ duration: obj.breathDuration,
153
+ delay: obj.delay,
154
+ ease: "easeInOut",
155
+ repeat: Infinity,
156
+ repeatType: "reverse"
157
+ },
158
+ whileHover: {
159
+ scale: 1.5,
160
+ boxShadow: `0 0 30px ${glow.replace("shadow-", "").replace("/50", "")}`
161
+ }
162
+ },
163
+ obj.id
164
+ )),
165
+ isHovered && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0", children: Array.from({ length: 20 }).map((_, i) => /* @__PURE__ */ jsx(
166
+ motion.div,
167
+ {
168
+ className: "absolute h-1 w-1 rounded-full bg-white/60",
169
+ style: {
170
+ left: `${Math.random() * 100}%`,
171
+ top: `${Math.random() * 100}%`
172
+ },
173
+ initial: { opacity: 0, scale: 0 },
174
+ animate: {
175
+ opacity: [0, 1, 0],
176
+ scale: [0, 1, 0],
177
+ y: [0, -50, -100]
178
+ },
179
+ transition: {
180
+ duration: 3,
181
+ delay: Math.random() * 2,
182
+ repeat: Infinity,
183
+ ease: "easeOut"
184
+ }
185
+ },
186
+ `particle-${i}`
187
+ )) }),
188
+ /* @__PURE__ */ jsx("div", { className: "relative z-10 size-full", children })
189
+ ]
190
+ }
191
+ );
192
+ }
193
+
194
+ export {
195
+ HoverBackground
196
+ };