diff --git a/src/components/ui/backgrounds/background-beams-collision.tsx b/src/components/ui/backgrounds/background-beams-collision.tsx index 4e2f58d..e92b60a 100644 --- a/src/components/ui/backgrounds/background-beams-collision.tsx +++ b/src/components/ui/backgrounds/background-beams-collision.tsx @@ -1,6 +1,7 @@ import React, { useRef, useState, useEffect, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { cn } from '@/lib/utils'; +import { sanitizeColor } from './types'; import { useAnimationPause } from '@/hooks/useAnimationLoop'; interface Props { @@ -26,7 +27,11 @@ const BEAMS: BeamOptions[] = [ { initialX: 1200, translateX: 1200, duration: 6, repeatDelay: 4, delay: 2, className: 'h-6' }, ]; -function Explosion(props: React.HTMLProps) { +function Explosion({ + beamColor, + explosionColor, + ...props +}: React.HTMLProps & { beamColor: string; explosionColor: string }) { const spans = Array.from({ length: 20 }, (_, i) => ({ id: i, directionX: Math.floor(Math.random() * 80 - 40), @@ -40,7 +45,10 @@ function Explosion(props: React.HTMLProps) { animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 1.5, ease: 'easeOut' }} - className="absolute -inset-x-10 top-0 m-auto h-2 w-10 rounded-full bg-gradient-to-r from-transparent via-indigo-500 to-transparent blur-sm" + className="absolute -inset-x-10 top-0 m-auto h-2 w-10 rounded-full blur-sm" + style={{ + background: `linear-gradient(to right, transparent, ${explosionColor}, transparent)`, + }} /> {spans.map((span) => ( ) { initial={{ x: 0, y: 0, opacity: 1 }} animate={{ x: span.directionX, y: span.directionY, opacity: 0 }} transition={{ duration: Math.random() * 1.5 + 0.5, ease: 'easeOut' }} - className="absolute h-1 w-1 rounded-full bg-gradient-to-b from-indigo-500 to-purple-500" + className="absolute h-1 w-1 rounded-full" + style={{ + background: `linear-gradient(to bottom, ${beamColor}, ${explosionColor})`, + }} /> ))} @@ -59,10 +70,14 @@ function CollisionMechanism({ containerRef, parentRef, beamOptions, + beamColor, + explosionColor, }: { containerRef: React.RefObject; parentRef: React.RefObject; beamOptions: BeamOptions; + beamColor: string; + explosionColor: string; }) { const beamRef = useRef(null); const [collision, setCollision] = useState<{ @@ -92,8 +107,6 @@ function CollisionMechanism({ } }, [containerRef, parentRef]); - // Throttled collision detection loop. - // Parent unmounts this component when paused, so no visibility handling needed here. useEffect(() => { let animId = 0; let lastCheck = 0; @@ -114,7 +127,6 @@ function CollisionMechanism({ }; }, [checkCollision]); - // Collision reset with proper timeout cleanup useEffect(() => { if (!collision.detected || !collision.coordinates) return; @@ -154,14 +166,19 @@ function CollisionMechanism({ repeatDelay: beamOptions.repeatDelay, }} className={cn( - 'absolute left-0 top-20 m-auto h-14 w-px rounded-full bg-gradient-to-t from-indigo-500 via-purple-500 to-transparent', + 'absolute left-0 top-20 m-auto h-14 w-px rounded-full', beamOptions.className, )} + style={{ + background: `linear-gradient(to top, ${beamColor}, ${explosionColor}, transparent)`, + }} /> {collision.detected && collision.coordinates && ( (null); const parentRef = useRef(null); const paused = useAnimationPause(); + const beamColor = sanitizeColor(settings.beamColor, '#6366f1'); + const explosionColor = sanitizeColor(settings.explosionColor, '#a855f7'); + return (
{!paused && @@ -188,9 +208,10 @@ export default function BackgroundBeamsCollision({ settings: _settings }: Props) beamOptions={beam} containerRef={containerRef} parentRef={parentRef} + beamColor={beamColor} + explosionColor={explosionColor} /> ))} - {/* Bottom collision line */}
{ ensureStyles(); }, []); @@ -117,7 +122,6 @@ export default React.memo(function BackgroundBeams({ settings: _settings }: Prop fill="none" xmlns="http://www.w3.org/2000/svg" > - {/* Static background — all paths at very low opacity */} - {/* Animated beams — only every 3rd path (17 beams), pure stroke-dashoffset */} {animatedPaths.map(({ path, paramIndex }) => ( - {/* Single shared gradient for all beams (cyan → purple → magenta) */} - - - - + + + + - {/* Radial gradient for static background */} - - - + + + diff --git a/src/components/ui/backgrounds/registry.ts b/src/components/ui/backgrounds/registry.ts index d3e168f..8cff2db 100644 --- a/src/components/ui/backgrounds/registry.ts +++ b/src/components/ui/backgrounds/registry.ts @@ -234,14 +234,37 @@ export const backgroundRegistry: BackgroundDefinition[] = [ labelKey: 'admin.backgrounds.beams', descriptionKey: 'admin.backgrounds.beamsDesc', category: 'svg', - settings: [], + settings: [ + { + key: 'gradientStart', + label: 'admin.backgrounds.color1', + type: 'color', + default: '#18CCFC', + }, + { key: 'gradientMid', label: 'admin.backgrounds.color2', type: 'color', default: '#6344F5' }, + { key: 'gradientEnd', label: 'admin.backgrounds.color3', type: 'color', default: '#AE48FF' }, + { + key: 'staticColor', + label: 'admin.backgrounds.fillColor', + type: 'color', + default: '#d4d4d4', + }, + ], }, { type: 'background-beams-collision', labelKey: 'admin.backgrounds.beamsCollision', descriptionKey: 'admin.backgrounds.beamsCollisionDesc', category: 'svg', - settings: [], + settings: [ + { key: 'beamColor', label: 'admin.backgrounds.beamColor', type: 'color', default: '#6366f1' }, + { + key: 'explosionColor', + label: 'admin.backgrounds.explosionColor', + type: 'color', + default: '#a855f7', + }, + ], }, { type: 'gradient-animation', diff --git a/src/locales/en.json b/src/locales/en.json index 1fc760c..c0c7413 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1170,6 +1170,8 @@ "trailColor": "Trail Color", "bgStarColor": "Background Stars Color", "pointerColor": "Pointer Color", + "beamColor": "Beam Color", + "explosionColor": "Explosion Color", "bgColor": "Background Color", "fillColor": "Fill Color", "color1": "Color 1", diff --git a/src/locales/ru.json b/src/locales/ru.json index a3504bf..fe4a894 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1200,6 +1200,8 @@ "trailColor": "Цвет следа", "bgStarColor": "Цвет фоновых звёзд", "pointerColor": "Цвет курсорного блоба", + "beamColor": "Цвет лучей", + "explosionColor": "Цвет взрыва", "bgColor": "Цвет фона", "fillColor": "Цвет заливки", "color1": "Цвет 1",