apex-ui-kit 2.0.5

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.
Files changed (40) hide show
  1. package/Licence.md +21 -0
  2. package/ReadMe.md +75 -0
  3. package/dist/ApexUI-Kit/templates/Avatar/Avatar.jsx +81 -0
  4. package/dist/ApexUI-Kit/templates/BeamBar/BeamBar.jsx +101 -0
  5. package/dist/ApexUI-Kit/templates/Cards/BasicCard.jsx +60 -0
  6. package/dist/ApexUI-Kit/templates/Carousel/Carousel.jsx +95 -0
  7. package/dist/ApexUI-Kit/templates/Carousel/DragCarousel.jsx +105 -0
  8. package/dist/ApexUI-Kit/templates/Carousel/ParallaxCarousel.jsx +161 -0
  9. package/dist/ApexUI-Kit/templates/DragCarousel/DragCarousel.jsx +105 -0
  10. package/dist/ApexUI-Kit/templates/EdgeGlowForm/EdgeGlowFrom.jsx +297 -0
  11. package/dist/ApexUI-Kit/templates/FlipProfile/FlipProfile.jsx +125 -0
  12. package/dist/ApexUI-Kit/templates/GlareCard/GlareCard.jsx +146 -0
  13. package/dist/ApexUI-Kit/templates/GlassCardStack/GlassCardStack.jsx +111 -0
  14. package/dist/ApexUI-Kit/templates/HoverText/HoverText.jsx +371 -0
  15. package/dist/ApexUI-Kit/templates/HyperCard/HyperCard.jsx +183 -0
  16. package/dist/ApexUI-Kit/templates/KineticThreadsBackground/KineticThreadBackground.jsx +249 -0
  17. package/dist/ApexUI-Kit/templates/LensFlareBackground/LensFlareBackground.jsx +268 -0
  18. package/dist/ApexUI-Kit/templates/LuminousParticleOcean/LuminousParticleOcean.jsx +155 -0
  19. package/dist/ApexUI-Kit/templates/NavDropDown/NavDropDown.jsx +114 -0
  20. package/dist/ApexUI-Kit/templates/NavMenu/NavMenu.jsx +153 -0
  21. package/dist/ApexUI-Kit/templates/OrbsBackground/FloatingOrbs.jsx +96 -0
  22. package/dist/ApexUI-Kit/templates/ParallaxCard/ParallaxCard.jsx +127 -0
  23. package/dist/ApexUI-Kit/templates/ParallaxCarousel/ParallaxCarousel.jsx +161 -0
  24. package/dist/ApexUI-Kit/templates/ParallaxProfile/ParallaxProfile.jsx +107 -0
  25. package/dist/ApexUI-Kit/templates/PointerFollower/PointerFollower.jsx +126 -0
  26. package/dist/ApexUI-Kit/templates/RainBackground/RainBackground.jsx +109 -0
  27. package/dist/ApexUI-Kit/templates/RippleBackground/RippleBackground.jsx +160 -0
  28. package/dist/ApexUI-Kit/templates/ScrollMarquee/ScrollMarquee.jsx +174 -0
  29. package/dist/ApexUI-Kit/templates/SmartGridCard/SmartGridCard.jsx +241 -0
  30. package/dist/ApexUI-Kit/templates/SmokeBackground/SmokeBackground.jsx +216 -0
  31. package/dist/ApexUI-Kit/templates/Testimonials/Testimonials.jsx +117 -0
  32. package/dist/ApexUI-Kit/templates/ThemeToggle/ThemeAnimation.js +252 -0
  33. package/dist/ApexUI-Kit/templates/ThemeToggle/ThemeConfig.js +8 -0
  34. package/dist/ApexUI-Kit/templates/ThemeToggle/ThemeToggle.css +560 -0
  35. package/dist/ApexUI-Kit/templates/ThemeToggle/ThemeToggle.jsx +118 -0
  36. package/dist/ApexUI-Kit/templates/ToolTip/ToolTip.jsx +85 -0
  37. package/dist/ApexUI-Kit/templates/WaterDropReveal/WaterDropReveal.jsx +151 -0
  38. package/dist/cli/index.d.ts +2 -0
  39. package/dist/cli/index.js +145 -0
  40. package/package.json +56 -0
@@ -0,0 +1,249 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import * as THREE from 'three';
3
+
4
+ // --- GLSL Shader Code ---
5
+ // Vertex shader (simple, just positions the plane)
6
+ const vertexShader = `
7
+ varying vec2 vUv;
8
+ void main() {
9
+ vUv = uv;
10
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
11
+ }
12
+ `;
13
+
14
+ // Fragment shader "Kinetic Threads" ke liye
15
+ const fragmentShader = `
16
+ precision highp float;
17
+
18
+ uniform float uTime;
19
+ uniform vec2 uResolution;
20
+ uniform vec3 uColor;
21
+ uniform float uAmplitude;
22
+ uniform float uDistance;
23
+ uniform vec2 uMouse;
24
+ uniform int u_line_count; // Line count ab uniform hai
25
+
26
+ #define PI 3.1415926538
27
+
28
+ const float u_line_width = 7.0;
29
+ const float u_line_blur = 10.0;
30
+
31
+ // Perlin Noise function for organic movement
32
+ float Perlin2D(vec2 P) {
33
+ vec2 Pi = floor(P);
34
+ vec4 Pf_Pfmin1 = P.xyxy - vec4(Pi, Pi + 1.0);
35
+ vec4 Pt = vec4(Pi.xy, Pi.xy + 1.0);
36
+ Pt = Pt - floor(Pt * (1.0 / 71.0)) * 71.0;
37
+ Pt += vec2(26.0, 161.0).xyxy;
38
+ Pt *= Pt;
39
+ Pt = Pt.xzxz * Pt.yyww;
40
+ vec4 hash_x = fract(Pt * (1.0 / 951.135664));
41
+ vec4 hash_y = fract(Pt * (1.0 / 642.949883));
42
+ vec4 grad_x = hash_x - 0.49999;
43
+ vec4 grad_y = hash_y - 0.49999;
44
+ vec4 grad_results = inversesqrt(grad_x * grad_x + grad_y * grad_y)
45
+ * (grad_x * Pf_Pfmin1.xzxz + grad_y * Pf_Pfmin1.yyww);
46
+ grad_results *= 1.4142135623730950;
47
+ vec2 blend = Pf_Pfmin1.xy * Pf_Pfmin1.xy * Pf_Pfmin1.xy
48
+ * (Pf_Pfmin1.xy * (Pf_Pfmin1.xy * 6.0 - 15.0) + 10.0);
49
+ vec4 blend2 = vec4(blend, vec2(1.0 - blend));
50
+ return dot(grad_results, blend2.zxzx * blend2.wwyy);
51
+ }
52
+
53
+ float pixel(float count, vec2 resolution) {
54
+ return (1.0 / max(resolution.x, resolution.y)) * count;
55
+ }
56
+
57
+ // Function to draw a single animated line
58
+ float lineFn(vec2 st, float width, float perc, float offset, vec2 mouse, float time, float amplitude, float distance) {
59
+ float split_offset = (perc * 0.4);
60
+ float split_point = 0.1 + split_offset;
61
+
62
+ float amplitude_normal = smoothstep(split_point, 0.7, st.x);
63
+ float amplitude_strength = 0.5;
64
+ float finalAmplitude = amplitude_normal * amplitude_strength
65
+ * amplitude * (1.0 + (mouse.y - 0.5) * 0.2);
66
+
67
+ float time_scaled = time / 10.0 + (mouse.x - 0.5) * 1.0;
68
+ float blur = smoothstep(split_point, split_point + 0.05, st.x) * perc;
69
+
70
+ float xnoise = mix(
71
+ Perlin2D(vec2(time_scaled, st.x + perc) * 2.5),
72
+ Perlin2D(vec2(time_scaled, st.x + time_scaled) * 3.5) / 1.5,
73
+ st.x * 0.3
74
+ );
75
+
76
+ float y = 0.5 + (perc - 0.5) * distance + xnoise / 2.0 * finalAmplitude;
77
+
78
+ float line_start = smoothstep(
79
+ y + (width / 2.0) + (u_line_blur * pixel(1.0, uResolution.xy) * blur),
80
+ y,
81
+ st.y
82
+ );
83
+
84
+ float line_end = smoothstep(
85
+ y,
86
+ y - (width / 2.0) - (u_line_blur * pixel(1.0, uResolution.xy) * blur),
87
+ st.y
88
+ );
89
+
90
+ return clamp(
91
+ (line_start - line_end) * (1.0 - smoothstep(0.0, 1.0, pow(perc, 0.3))),
92
+ 0.0,
93
+ 1.0
94
+ );
95
+ }
96
+
97
+ void main() {
98
+ vec2 uv = gl_FragCoord.xy / uResolution.xy;
99
+ float line_strength1 = 1.0;
100
+ for (int i = 0; i < u_line_count; i++) {
101
+ float p = float(i) / float(u_line_count);
102
+ line_strength1 *= (1.0 - lineFn(
103
+ uv,
104
+ u_line_width * pixel(1.0, uResolution.xy) * (1.0 - p),
105
+ p,
106
+ (PI * 1.0) * p,
107
+ uMouse,
108
+ uTime,
109
+ uAmplitude,
110
+ uDistance
111
+ ));
112
+ }
113
+
114
+ float line_strength2 = 1.0;
115
+ vec2 mirroredUv = vec2(1.0 - uv.x, uv.y);
116
+ vec2 mirroredMouse = vec2(1.0 - uMouse.x, uMouse.y);
117
+ for (int i = 0; i < u_line_count; i++) {
118
+ float p = float(i) / float(u_line_count);
119
+ line_strength2 *= (1.0 - lineFn(
120
+ mirroredUv,
121
+ u_line_width * pixel(1.0, uResolution.xy) * (1.0 - p),
122
+ p,
123
+ (PI * 1.0) * p,
124
+ mirroredMouse,
125
+ uTime,
126
+ uAmplitude,
127
+ uDistance
128
+ ));
129
+ }
130
+
131
+ float final_strength = line_strength1 * line_strength2;
132
+ float colorVal = 1.0 - final_strength;
133
+ gl_FragColor = vec4(uColor * colorVal, colorVal);
134
+ }
135
+ `;
136
+
137
+
138
+ // --- KineticThreadsBackground Component ---
139
+ const KineticThreadsBackground = ({
140
+ color = "#a3e635", // lime
141
+ amplitude = 1.0,
142
+ distance = 0.5,
143
+ speed = 1.0,
144
+ mouseInteraction = true,
145
+ }) => {
146
+ const mountRef = useRef(null);
147
+ const mouseRef = useRef({ x: 0.5, y: 0.5 });
148
+ const targetMouseRef = useRef({ x: 0.5, y: 0.5 });
149
+
150
+ useEffect(() => {
151
+ const mountNode = mountRef.current;
152
+
153
+ // Scene, Camera, Renderer
154
+ const scene = new THREE.Scene();
155
+ const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
156
+ const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
157
+ mountNode.appendChild(renderer.domElement);
158
+
159
+ // Shader Material
160
+ const uniforms = {
161
+ uTime: { value: 0 },
162
+ uResolution: { value: new THREE.Vector2() },
163
+ uMouse: { value: new THREE.Vector2(0.5, 0.5) },
164
+ uColor: { value: new THREE.Color(color) },
165
+ uAmplitude: { value: amplitude },
166
+ uDistance: { value: distance },
167
+ u_line_count: { value: 40 } // Default line count
168
+ };
169
+ const material = new THREE.ShaderMaterial({
170
+ vertexShader,
171
+ fragmentShader,
172
+ uniforms,
173
+ transparent: true,
174
+ });
175
+
176
+ // Fullscreen Plane
177
+ const geometry = new THREE.PlaneGeometry(2, 2);
178
+ const plane = new THREE.Mesh(geometry, material);
179
+ scene.add(plane);
180
+
181
+ // Mouse move handler
182
+ const handleMouseMove = (event) => {
183
+ if (!mouseInteraction) return;
184
+ const rect = mountNode.getBoundingClientRect();
185
+ targetMouseRef.current.x = (event.clientX - rect.left) / rect.width;
186
+ targetMouseRef.current.y = 1.0 - (event.clientY - rect.top) / rect.height;
187
+ };
188
+ const handleMouseLeave = () => {
189
+ targetMouseRef.current.x = 0.5;
190
+ targetMouseRef.current.y = 0.5;
191
+ };
192
+ if (mouseInteraction) {
193
+ window.addEventListener('mousemove', handleMouseMove);
194
+ window.addEventListener('mouseleave', handleMouseLeave);
195
+ }
196
+
197
+ // Resize handler with mobile optimization
198
+ const handleResize = () => {
199
+ const { clientWidth, clientHeight } = mountNode;
200
+ renderer.setSize(clientWidth, clientHeight);
201
+
202
+ // --- Mobile Optimization ---
203
+ const isMobile = clientWidth < 768;
204
+
205
+ // 1. Adjust pixel ratio for performance on small screens
206
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, isMobile ? 1.5 : 2));
207
+
208
+ // 2. Reduce shader complexity (line count) on mobile
209
+ uniforms.u_line_count.value = isMobile ? 20 : 40;
210
+
211
+ uniforms.uResolution.value.set(clientWidth, clientHeight);
212
+ };
213
+ window.addEventListener('resize', handleResize);
214
+ handleResize(); // Initial call
215
+
216
+ // Animation loop
217
+ const clock = new THREE.Clock();
218
+ let animationFrameId;
219
+ const animate = () => {
220
+ uniforms.uTime.value = clock.getElapsedTime() * speed;
221
+
222
+ // Smoothly update mouse position (lerping)
223
+ mouseRef.current.x += (targetMouseRef.current.x - mouseRef.current.x) * 0.05;
224
+ mouseRef.current.y += (targetMouseRef.current.y - mouseRef.current.y) * 0.05;
225
+ uniforms.uMouse.value.set(mouseRef.current.x, mouseRef.current.y);
226
+
227
+ renderer.render(scene, camera);
228
+ animationFrameId = requestAnimationFrame(animate);
229
+ };
230
+ animate();
231
+
232
+ // Cleanup function
233
+ return () => {
234
+ cancelAnimationFrame(animationFrameId);
235
+ window.removeEventListener('resize', handleResize);
236
+ window.removeEventListener('mousemove', handleMouseMove);
237
+ window.removeEventListener('mouseleave', handleMouseLeave);
238
+ if (mountNode && renderer.domElement) {
239
+ mountNode.removeChild(renderer.domElement);
240
+ }
241
+ geometry.dispose();
242
+ material.dispose();
243
+ renderer.dispose();
244
+ };
245
+ }, [color, amplitude, distance, speed, mouseInteraction]);
246
+
247
+ return <div ref={mountRef} className="absolute inset-0 z-0 w-full h-full -translate-y-20"/>;
248
+ };
249
+ export default KineticThreadsBackground;
@@ -0,0 +1,268 @@
1
+ /* eslint-disable no-unused-vars */
2
+ import { react, useRef, useEffect } from "react";
3
+ import * as THREE from "three";
4
+ const hexToRgb = (hex) => {
5
+ const m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
6
+ return m
7
+ ? [
8
+ parseInt(m[1], 16) / 255,
9
+ parseInt(m[2], 16) / 255,
10
+ parseInt(m[3], 16) / 255,
11
+ ]
12
+ : [1, 1, 1];
13
+ };
14
+
15
+ const getAnchorAndDir = (w, h) => {
16
+ // Always center for this effect
17
+ return { anchor: [0.5 * w, 0.2 * h], dir: [0, 3] };
18
+ };
19
+
20
+ // Only add the selected props for lens flare effect, no other changes
21
+ const LensFlareBackground = ({
22
+ flareColor = "#fbbf24", // Main color of the lens flare
23
+ intensity = 1.0, // Intensity of the flare
24
+ animationSpeed = 1.0, // Animation speed
25
+ rayLengthValue = 1,
26
+ }) => {
27
+ const mountRef = useRef();
28
+ const uniformsRef = useRef();
29
+ const mouseRef = useRef({ x: 0.5, y: 0.5 });
30
+ const smoothMouseRef = useRef({ x: 0.5, y: 0.5 });
31
+
32
+ useEffect(() => {
33
+ if (!mountRef.current) return;
34
+ let renderer, scene, camera, material, mesh, frameId;
35
+ let dpr = Math.min(window.devicePixelRatio, 2);
36
+
37
+ const getDims = () => {
38
+ if (!mountRef.current) return [0, 0];
39
+ return [mountRef.current.clientWidth * dpr, mountRef.current.clientHeight * dpr];
40
+ };
41
+
42
+ const setupRenderer = () => {
43
+ renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
44
+ renderer.setClearColor(0x000000, 0);
45
+ if (mountRef.current) {
46
+ renderer.setSize(mountRef.current.clientWidth, mountRef.current.clientHeight, false);
47
+ mountRef.current.appendChild(renderer.domElement);
48
+ }
49
+ };
50
+
51
+ const setupScene = () => {
52
+ camera = new THREE.OrthographicCamera(0, 1, 1, 0, -1, 1);
53
+ scene = new THREE.Scene();
54
+ const geometry = new THREE.PlaneGeometry(1, 2);
55
+ const [w, h] = getDims();
56
+ const uniforms = {
57
+ iTime: { value: 0 },
58
+ iResolution: { value: new THREE.Vector2(w, h) },
59
+ rayPos: { value: new THREE.Vector2(0, 0) },
60
+ rayDir: { value: new THREE.Vector2(0, 1) },
61
+ raysColor: { value: new THREE.Color(...hexToRgb(flareColor)) },
62
+ raysSpeed: { value: animationSpeed },
63
+ lightSpread: { value: 4 },
64
+ rayLength: { value: 1 },
65
+ pulsating: { value: 0.0 },
66
+ fadeDistance: { value: 1.0 },
67
+ saturation: { value: 1.0 },
68
+ mousePos: { value: new THREE.Vector2(0.5, 0.5) },
69
+ mouseInfluence: { value: 0.1 },
70
+ noiseAmount: { value: 0.0 },
71
+ distortion: { value: 0.0 },
72
+ intensity: { value: intensity },
73
+ };
74
+ uniformsRef.current = uniforms;
75
+
76
+ const vertexShader = `
77
+ varying vec2 vUv;
78
+ void main() {
79
+ vUv = uv;
80
+ gl_Position = vec4(position, 1.0);
81
+ }
82
+ `;
83
+
84
+ const fragmentShader = `
85
+ precision highp float;
86
+ uniform float iTime;
87
+ uniform vec2 iResolution;
88
+ uniform vec2 rayPos;
89
+ uniform vec2 rayDir;
90
+ uniform vec3 raysColor;
91
+ uniform float raysSpeed;
92
+ uniform float lightSpread;
93
+ uniform float rayLength;
94
+ uniform float pulsating;
95
+ uniform float fadeDistance;
96
+ uniform float saturation;
97
+ uniform vec2 mousePos;
98
+ uniform float mouseInfluence;
99
+ uniform float noiseAmount;
100
+ uniform float distortion;
101
+ uniform float intensity;
102
+ varying vec2 vUv;
103
+
104
+ float noise(vec2 st) {
105
+ return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
106
+ }
107
+
108
+ float rayStrength(vec2 raySource, vec2 rayRefDirection, vec2 coord,
109
+ float seedA, float seedB, float speed) {
110
+ vec2 sourceToCoord = coord - raySource;
111
+ vec2 dirNorm = normalize(sourceToCoord);
112
+ float cosAngle = dot(dirNorm, rayRefDirection);
113
+ float distortedAngle = cosAngle + distortion * sin(iTime * 2.0 + length(sourceToCoord) * 0.01) * 0.2;
114
+ float spreadFactor = pow(max(distortedAngle, 0.0), 1.0 / max(lightSpread, 0.001));
115
+ float distance = length(sourceToCoord);
116
+ float maxDistance = iResolution.x * rayLength;
117
+ float lengthFalloff = clamp((maxDistance - distance) / maxDistance, 0.0, 1.0);
118
+ float fadeFalloff = clamp((iResolution.x * fadeDistance - distance) / (iResolution.x * fadeDistance), 0.5, 1.0);
119
+ float pulse = pulsating > 0.5 ? (0.8 + 0.2 * sin(iTime * speed * 3.0)) : 1.0;
120
+ float baseStrength = clamp(
121
+ (0.45 + 0.15 * sin(distortedAngle * seedA + iTime * speed)) +
122
+ (0.3 + 0.2 * cos(-distortedAngle * seedB + iTime * speed)),
123
+ 0.0, 1.0
124
+ );
125
+ return baseStrength * lengthFalloff * fadeFalloff * spreadFactor * pulse;
126
+ }
127
+
128
+ float dotGlow(vec2 uv, vec2 pos, float size) {
129
+ float d = length(uv - pos);
130
+ return exp(-pow(d / size, 2.5));
131
+ }
132
+
133
+ void main() {
134
+ vec2 fragCoord = vUv * iResolution.xy;
135
+ vec2 coord = vec2(fragCoord.x, iResolution.y - fragCoord.y);
136
+ vec2 finalRayDir = rayDir;
137
+
138
+ if (mouseInfluence > 0.0) {
139
+ vec2 mouseScreenPos = mousePos * iResolution.xy;
140
+ vec2 mouseDirection = normalize(mouseScreenPos - rayPos);
141
+ finalRayDir = normalize(mix(rayDir, mouseDirection, mouseInfluence));
142
+ }
143
+
144
+ vec4 rays1 = vec4(1.0) * rayStrength(rayPos, finalRayDir, coord, 36.2214, 21.11349, 1.5 * raysSpeed);
145
+ vec4 rays2 = vec4(1.0) * rayStrength(rayPos, finalRayDir, coord, 22.3991, 18.0234, 1.1 * raysSpeed);
146
+ vec4 fragColor = (rays1 * 0.7 + rays2 * 0.6) * 1.5;
147
+
148
+ if (noiseAmount > 0.0) {
149
+ float n = noise(coord * 0.01 + iTime * 0.1);
150
+ fragColor.rgb *= (1.0 - noiseAmount + noiseAmount * n);
151
+ }
152
+
153
+ float brightness = 1.0 - (coord.y / iResolution.y);
154
+ fragColor.x *= 0.1 + brightness * 0.8;
155
+ fragColor.y *= 0.3 + brightness * 0.6;
156
+ fragColor.z *= 0.5 + brightness * 0.5;
157
+
158
+ if (saturation != 1.0) {
159
+ float gray = dot(fragColor.rgb, vec3(0.299, 0.587, 0.114));
160
+ fragColor.rgb = mix(vec3(gray), fragColor.rgb, saturation);
161
+ }
162
+
163
+ fragColor.rgb *= raysColor;
164
+ fragColor.rgb *= intensity;
165
+
166
+ float t = iTime;
167
+ vec2 uvNorm = fragCoord / iResolution.xy;
168
+ float dots = 0.0;
169
+ dots += dotGlow(uvNorm, vec2(0.3 + 0.1 * sin(t), 0.4 + 0.1 * cos(t)), 0.04 + 0.01 * sin(t * 1.2));
170
+ dots += dotGlow(uvNorm, vec2(0.7 + 0.08 * cos(t * 1.1), 0.6 + 0.09 * sin(t * 0.9)), 0.035 + 0.01 * cos(t * 1.3));
171
+ dots += dotGlow(uvNorm, vec2(0.5 + 0.12 * sin(t * 0.7), 0.7 + 0.07 * cos(t * 1.5)), 0.03 + 0.01 * sin(t * 1.7));
172
+ dots += dotGlow(uvNorm, vec2(0.4 + 0.09 * cos(t * 1.4), 0.3 + 0.08 * sin(t * 1.1)), 0.025 + 0.01 * cos(t * 1.9));
173
+ dots += dotGlow(uvNorm, vec2(0.6 + 0.07 * sin(t * 1.6), 0.5 + 0.1 * cos(t * 1.2)), 0.03 + 0.01 * sin(t * 1.5));
174
+ vec3 dotColor = vec3(1.0, 0.95, 0.8);
175
+ fragColor.rgb += dots * dotColor * 0.7 * intensity;
176
+
177
+ gl_FragColor = fragColor;
178
+ }
179
+ `;
180
+
181
+ material = new THREE.ShaderMaterial({
182
+ uniforms,
183
+ vertexShader,
184
+ fragmentShader,
185
+ transparent: true,
186
+ depthWrite: false,
187
+ });
188
+ mesh = new THREE.Mesh(geometry, material);
189
+ scene.add(mesh);
190
+ return { uniforms };
191
+ };
192
+
193
+ let uniforms;
194
+ setupRenderer();
195
+ ({ uniforms } = setupScene());
196
+
197
+ const updatePlacement = () => {
198
+ dpr = Math.min(window.devicePixelRatio, 2);
199
+ if (!mountRef.current) return;
200
+ const w = mountRef.current.clientWidth * dpr;
201
+ const h = mountRef.current.clientHeight * dpr;
202
+ renderer.setSize(mountRef.current.clientWidth, mountRef.current.clientHeight, false);
203
+ uniforms.iResolution.value.set(w, h);
204
+ const { anchor, dir } = getAnchorAndDir(w, h);
205
+ uniforms.rayPos.value.set(anchor[0], anchor[1]);
206
+ uniforms.rayDir.value.set(dir[0], dir[1]);
207
+ };
208
+ updatePlacement();
209
+ window.addEventListener("resize", updatePlacement);
210
+
211
+ const handleMouseMove = (e) => {
212
+ if (!mountRef.current) return;
213
+ const rect = mountRef.current.getBoundingClientRect();
214
+ const x = (e.clientX - rect.left) / rect.width;
215
+ const y = (e.clientY - rect.top) / rect.height;
216
+ mouseRef.current = { x, y };
217
+ };
218
+ window.addEventListener("mousemove", handleMouseMove);
219
+
220
+ const animate = (now) => {
221
+ uniforms.iTime.value = now * 0.001;
222
+ const smoothing = 0.92;
223
+ smoothMouseRef.current.x =
224
+ smoothMouseRef.current.x * smoothing + mouseRef.current.x * (1 - smoothing);
225
+ smoothMouseRef.current.y =
226
+ smoothMouseRef.current.y * smoothing + mouseRef.current.y * (1 - smoothing);
227
+ uniforms.mousePos.value.set(smoothMouseRef.current.x, smoothMouseRef.current.y);
228
+ renderer.render(scene, camera);
229
+ frameId = requestAnimationFrame(animate);
230
+ };
231
+ frameId = requestAnimationFrame(animate);
232
+
233
+ return () => {
234
+ if (frameId) cancelAnimationFrame(frameId);
235
+ window.removeEventListener("resize", updatePlacement);
236
+ window.removeEventListener("mousemove", handleMouseMove);
237
+ renderer.dispose();
238
+ if (mountRef.current && renderer.domElement.parentNode === mountRef.current) {
239
+ mountRef.current.removeChild(renderer.domElement);
240
+ }
241
+ };
242
+ }, [flareColor, intensity, animationSpeed]);
243
+
244
+ useEffect(() => {
245
+ if (!uniformsRef.current) return;
246
+ uniformsRef.current.raysColor.value.set(...hexToRgb(flareColor));
247
+ uniformsRef.current.raysSpeed.value = animationSpeed;
248
+ uniformsRef.current.intensity.value = intensity;
249
+ }, [flareColor, animationSpeed, intensity]);
250
+
251
+ return (
252
+ <div
253
+ ref={mountRef}
254
+ // Corrected the className and ensured overflow is hidden
255
+ className="pointer-events-none w-[135vw] overflow-hidden"
256
+ style={{
257
+ position: "absolute",
258
+ bottom: 0,
259
+ height: "100vh",
260
+ // Add these two lines to center the element horizontally
261
+ left: "50%",
262
+ transform: "translateX(-50%)",
263
+ }}
264
+ />
265
+ );
266
+ };
267
+
268
+ export default LensFlareBackground;
@@ -0,0 +1,155 @@
1
+ import React, { useRef, useMemo } from 'react';
2
+ import { Canvas, useFrame } from '@react-three/fiber';
3
+ import * as THREE from 'three';
4
+ // Helper function to convert hex color to rgba for CSS
5
+ function hexToRgba(hex, alpha) {
6
+ const r = parseInt(hex.slice(1, 3), 16);
7
+ const g = parseInt(hex.slice(3, 5), 16);
8
+ const b = parseInt(hex.slice(5, 7), 16);
9
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
10
+ }
11
+
12
+ // Internal component to create and animate the flowing spheres
13
+ function FlowingSpheres({ count, sep, color, pushStrength }) {
14
+ const instancedMeshRef = useRef();
15
+
16
+ // A dummy object to reuse for matrix calculations for performance
17
+ const dummy = useMemo(() => new THREE.Object3D(), []);
18
+
19
+ // Generate the initial positions and data for each instance
20
+ const particles = useMemo(() => {
21
+ const temp = [];
22
+ for (let xi = 0; xi < count; xi++) {
23
+ for (let zi = 0; zi < count; zi++) {
24
+ const x = sep * (xi - count / 2);
25
+ const z = sep * (zi - count / 2);
26
+ temp.push({ x, y: 0, z });
27
+ }
28
+ }
29
+ return temp;
30
+ }, [count, sep]);
31
+
32
+ // useFrame runs on every rendered frame
33
+ useFrame(({ clock, mouse }) => {
34
+ if (!instancedMeshRef.current) return;
35
+ const elapsedTime = clock.getElapsedTime();
36
+
37
+ // Map mouse position (-1 to 1) to the grid's world coordinates
38
+ const mouseXWorld = mouse.x * (count * sep / 4);
39
+ const mouseZWorld = -mouse.y * (count * sep / 4);
40
+
41
+ // Animate each sphere's y-position and update its matrix
42
+ particles.forEach((particle, i) => {
43
+ const { x, z } = particle;
44
+
45
+ // --- 1. Wave Animation ---
46
+ const timeFactor = Math.sin(elapsedTime * 0.5);
47
+ const wave1 = Math.sin(x * 0.15 + timeFactor * Math.PI);
48
+ const wave2 = Math.sin(z * 1 + timeFactor * Math.PI);
49
+ let y = (wave1 + wave2) * 7;
50
+
51
+ // --- 2. Mouse Movement Interaction ---
52
+ const dx = x - mouseXWorld;
53
+ const dz = z - mouseZWorld;
54
+ const distance = Math.sqrt(dx * dx + dz * dz);
55
+
56
+ const maxDist = 50; // The radius of the interaction effect
57
+
58
+ const pushFactor = Math.max(0, 1 - distance / maxDist);
59
+ const smoothPush = Math.pow(pushFactor, 3);
60
+
61
+ y -= smoothPush * pushStrength;
62
+
63
+ dummy.position.set(x, y, z);
64
+ dummy.updateMatrix();
65
+
66
+ instancedMeshRef.current.setMatrixAt(i, dummy.matrix);
67
+ });
68
+
69
+ instancedMeshRef.current.instanceMatrix.needsUpdate = true;
70
+ });
71
+
72
+ return (
73
+ <group rotation={[0, 0, 0]}>
74
+ <instancedMesh
75
+ ref={instancedMeshRef}
76
+ args={[null, null, count * count]}
77
+ >
78
+ <sphereGeometry args={[0.2, 19, 19]} />
79
+ <meshStandardMaterial
80
+ color={color}
81
+ emissive={color}
82
+ emissiveIntensity={1.5}
83
+ roughness={0.4}
84
+ metalness={0.1}
85
+ />
86
+ </instancedMesh>
87
+ </group>
88
+ );
89
+ }
90
+
91
+ // The main component, now named LuminousParticleOcean
92
+ // You can pass props to this component to customize the background
93
+ const LuminousParticleOcean = ({
94
+ sphereCount = 100,
95
+ sphereColor = "#00aaff",
96
+ interactionStrength = 15,
97
+ separation = 4,
98
+ bgColor1 = "#010a2d",
99
+ bgColor2 = "#001133",
100
+
101
+ }) => {
102
+
103
+ const lightColorRgba = useMemo(() => hexToRgba(sphereColor, 0.5), [sphereColor]);
104
+
105
+ return (
106
+ <div
107
+ className="relative w-screen h-[60vh] lg:h-[80vh] overflow-hidden"
108
+ style={{
109
+ background: `linear-gradient(to bottom, ${bgColor1}, ${bgColor2})`
110
+ }}
111
+ >
112
+ {/* Sunlight Effect: Now uses the sphereColor prop */}
113
+ <div
114
+ className="absolute -top-10 left-0 w-full h-1/2 z-[999]"
115
+ style={{
116
+ background: `radial-gradient(circle at top center, ${lightColorRgba} 0%, transparent 90%)`,
117
+ filter: 'blur(40px)',
118
+ pointerEvents: 'none',
119
+ }}
120
+ />
121
+
122
+ {/* Vignette Effect */}
123
+ <div
124
+ className="absolute inset-0"
125
+ style={{
126
+ boxShadow: 'inset 0 0 150px rgba(0,0,0,0.7)',
127
+ pointerEvents: 'none',
128
+ }}
129
+ />
130
+
131
+ <Canvas
132
+ camera={{ position: [0, 60, 150], fov: 55 }}
133
+ >
134
+ {/* Sunlight: Also uses the sphereColor prop */}
135
+ <pointLight
136
+ color={sphereColor}
137
+ intensity={4000}
138
+ distance={300}
139
+ position={[-150, 100, -100]}
140
+ />
141
+ <ambientLight intensity={0.2} />
142
+
143
+ {/* Render the animated flowing spheres component with the passed props */}
144
+ <FlowingSpheres
145
+ count={sphereCount}
146
+ sep={separation}
147
+ color={sphereColor}
148
+ pushStrength={interactionStrength}
149
+ />
150
+ </Canvas>
151
+ </div>
152
+ );
153
+ }
154
+
155
+ export default LuminousParticleOcean;