11'use client' ;
22import { trackUser } from '@/utils/tracking' ;
3- import type { ReactNode } from 'react' ;
3+ import InteractiveViewer from '@/components/InteractiveViewer' ;
4+
45import Link from 'next/link' ;
56import { useRef , useState , useEffect } from 'react' ;
67import { AnimatePresence , motion } from 'framer-motion' ;
@@ -11,7 +12,7 @@ import { CustomizeCTA } from './components/CustomizeCTA';
1112import { useRecentSearches } from '@/hooks/useRecentSearches' ;
1213import { useDebounce } from '@/hooks/useDebounce' ;
1314import { Footer } from '@/app/components/Footer' ;
14- import InteractiveViewer from '@/components/InteractiveViewer' ;
15+
1516import { FeatureCard , FeatureCardsSection } from '@/components/FeatureCards' ;
1617import { DiscordButton } from '@/components/DiscordButton' ;
1718
@@ -140,6 +141,39 @@ export default function LandingPage() {
140141 setTimeout ( ( ) => setCopied ( false ) , 50000 ) ;
141142 } ;
142143
144+ const handleRotate3D = ( dx : number , dy : number ) => {
145+ const towersGroup = document . getElementById ( 'cp-towers' ) ;
146+ if ( ! towersGroup ) return ;
147+
148+ // Remove any transition so dragging feels instant and responsive
149+ towersGroup . style . transition = 'none' ;
150+
151+ let currentX = 0 ;
152+ let currentY = 0 ;
153+
154+ const transformStr = towersGroup . style . transform ;
155+ if ( transformStr ) {
156+ const matchX = transformStr . match ( / r o t a t e X \( ( [ - 0 - 9 . ] + ) d e g \) / ) ;
157+ const matchY = transformStr . match ( / r o t a t e Y \( ( [ - 0 - 9 . ] + ) d e g \) / ) ;
158+ if ( matchX ) currentX = parseFloat ( matchX [ 1 ] ) ;
159+ if ( matchY ) currentY = parseFloat ( matchY [ 1 ] ) ;
160+ }
161+
162+ const newX = currentX - dy * 0.5 ;
163+ const newY = currentY + dx * 0.5 ;
164+
165+ towersGroup . style . transform = `translate(0px, 20px) rotateX(${ newX } deg) rotateY(${ newY } deg)` ;
166+ } ;
167+
168+ const handleReset3D = ( ) => {
169+ const towersGroup = document . getElementById ( 'cp-towers' ) ;
170+ if ( towersGroup ) {
171+ // Apply a smooth transition for the reset
172+ towersGroup . style . transition = 'transform 1.2s cubic-bezier(0.16, 1, 0.3, 1)' ;
173+ towersGroup . style . transform = '' ;
174+ }
175+ } ;
176+
143177 return (
144178 < div className = "min-h-screen overflow-x-hidden bg-transparent font-sans text-black dark:text-white selection:bg-black/20 dark:selection:bg-white/20" >
145179 < div className = "pointer-events-none fixed inset-0 overflow-hidden" >
@@ -308,7 +342,12 @@ export default function LandingPage() {
308342
309343 < div className = "group relative mt-10" >
310344 < div className = "absolute -inset-1 rounded-[2.5rem] bg-gradient-to-r from-emerald-500/20 to-cyan-500/20 opacity-50 blur-2xl transition duration-1000 group-hover:opacity-100" />
311- < div className = "relative flex min-h-[480px] md:min-h-[520px] items-center justify-center overflow-visible rounded-3xl border border-black/5 bg-white/50 p-8 backdrop-blur-xl shadow-2xl dark:border-white/10 dark:bg-[#0a0a0a]/80" >
345+ < InteractiveViewer
346+ className = "relative flex min-h-[480px] md:min-h-[520px] items-center justify-center overflow-visible rounded-3xl border border-black/5 bg-white/50 p-8 backdrop-blur-xl shadow-2xl dark:border-white/10 dark:bg-[#0a0a0a]/80"
347+ is3DMode = { true }
348+ onRotate3D = { handleRotate3D }
349+ onReset3D = { handleReset3D }
350+ >
312351 { hasUsername ? (
313352 < div className = "w-full flex items-center justify-center" >
314353 { svgState === 'loading' && (
@@ -370,7 +409,7 @@ export default function LandingPage() {
370409 </ p >
371410 </ div >
372411 ) }
373- </ div >
412+ </ InteractiveViewer >
374413 </ div >
375414 </ section >
376415
0 commit comments