Spaces:
Running
Running
File size: 7,751 Bytes
8af739b 7f20600 8af739b 16a4dbd 467789d 062c414 163eb99 8af739b bc139ec 8af739b bc139ec 8af739b bc139ec 8af739b 467789d 062c414 2a1df12 8af739b 2a1df12 8af739b 16a4dbd 467789d 163eb99 8af739b bc139ec 8af739b bc139ec 8af739b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
'use client'
import React, { useState, useRef } from 'react'
import Draggable from 'react-draggable'
import {
Folder,
Calendar,
Clock,
Globe,
Sparkle,
Flask,
DeviceMobile,
Function,
HardDrives,
Code,
Lightning,
Key,
Brain,
ChatCircleDots,
MusicNote
} from '@phosphor-icons/react'
import { DynamicClockIcon } from './DynamicClockIcon'
import { DynamicCalendarIcon } from './DynamicCalendarIcon'
interface DraggableDesktopIconProps {
id: string
label: string
iconType: string
initialPosition?: { x: number; y: number }
onClick: () => void
onDoubleClick: () => void
}
export function DraggableDesktopIcon({
id,
label,
iconType,
initialPosition = { x: 0, y: 0 },
onClick,
onDoubleClick
}: DraggableDesktopIconProps) {
const [selected, setSelected] = useState(false)
const nodeRef = useRef<HTMLDivElement>(null) as React.MutableRefObject<HTMLDivElement>
const handleClick = () => {
setSelected(true)
onClick()
// Deselect after a short time
setTimeout(() => setSelected(false), 3000)
}
const getIcon = () => {
switch (iconType) {
case 'files':
return (
<div className="bg-gradient-to-br from-blue-400 to-cyan-200 w-full h-full rounded-xl flex items-center justify-center border border-white/30">
<Folder size={32} weight="regular" className="text-blue-900" />
</div>
)
case 'calendar':
return (
<div className="w-full h-full">
<DynamicCalendarIcon />
</div>
)
case 'clock':
return (
<div className="w-full h-full">
<DynamicClockIcon />
</div>
)
case 'messages':
return (
<div className="bg-gradient-to-b from-[#4CD964] to-[#2E8B57] w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<ChatCircleDots size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
case 'flutter':
return (
<div className="bg-gradient-to-b from-[#54C5F8] to-[#29B6F6] w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<DeviceMobile size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
<div className="absolute top-1.5 right-1.5">
<Lightning size={12} weight="fill" className="text-yellow-300 drop-shadow-md" />
</div>
</div>
)
case 'latex':
return (
<div className="bg-gradient-to-b from-slate-700 to-slate-900 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/10 to-transparent opacity-30" />
<div className="relative z-10 flex flex-col items-center justify-center">
<Function size={32} weight="bold" className="text-green-400 drop-shadow-md" />
<span className="text-[8px] font-black text-gray-300 tracking-widest mt-0.5">TEX</span>
</div>
</div>
)
case 'gemini':
return (
<div className="bg-gradient-to-b from-white to-blue-50 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/50 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/40 to-transparent" />
<Sparkle size={36} weight="fill" className="text-blue-500 relative z-10 drop-shadow-sm" />
</div>
)
case 'harddrive':
return (
<div className="bg-gray-200 w-full h-full rounded-lg flex items-center justify-center border border-gray-300 relative">
<HardDrives size={32} weight="regular" className="text-gray-600" />
<div className="absolute bottom-2 right-2 w-1.5 h-1.5 bg-green-400 rounded-full animate-pulse" />
</div>
)
case 'vscode':
return (
<div className="bg-gradient-to-br from-blue-600 to-blue-800 w-full h-full rounded-xl flex items-center justify-center border border-blue-900/30 shadow-inner">
<Code size={32} weight="bold" className="text-white" />
</div>
)
case 'playground':
return (
<div className="bg-gradient-to-br from-yellow-500 to-orange-600 w-full h-full rounded-xl flex items-center justify-center border border-orange-700/30 shadow-inner">
<Lightning size={32} weight="fill" className="text-white" />
</div>
)
case 'key':
return (
<div className="bg-gradient-to-br from-purple-600 to-purple-800 w-full h-full rounded-xl flex items-center justify-center border border-purple-900/30 shadow-inner">
<Key size={32} weight="bold" className="text-white" />
</div>
)
case 'quiz':
return (
<div className="bg-gradient-to-br from-teal-400 to-emerald-500 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<Brain size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
case 'voice-app':
return (
<div className="bg-gradient-to-br from-purple-500 to-pink-500 w-full h-full rounded-[22%] flex items-center justify-center shadow-lg border-[0.5px] border-white/20 relative overflow-hidden group-hover:shadow-2xl transition-all duration-300">
<div className="absolute inset-0 bg-gradient-to-b from-white/20 to-transparent opacity-50" />
<MusicNote size={36} weight="fill" className="text-white relative z-10 drop-shadow-md" />
</div>
)
default:
return (
<div className="bg-gray-400 w-full h-full rounded-xl flex items-center justify-center">
<Folder size={32} weight="regular" className="text-white" />
</div>
)
}
}
return (
<Draggable
nodeRef={nodeRef}
defaultPosition={initialPosition}
grid={[25, 25]}
handle=".icon-handle"
>
<div
ref={nodeRef}
className="absolute flex flex-col items-center w-20 group cursor-pointer transition-all hover:bg-white/10 rounded p-1"
onClick={handleClick}
onDoubleClick={onDoubleClick}
>
<div className="icon-handle">
<div
className={`w-14 h-14 shadow-lg transition-transform hover:scale-110 ${iconType === 'clock' ? '' : 'rounded-xl'
}`}
>
{getIcon()}
</div>
</div>
<span
className={`mt-1 text-xs font-medium drop-shadow-lg text-center leading-tight px-1 py-0.5 rounded transition-colors ${selected
? 'bg-blue-600/80 text-white'
: 'text-white bg-black/20 group-hover:bg-blue-600/80'
}`}
>
{label}
</span>
</div>
</Draggable>
)
} |