vikashpatel commited on
Commit
dae3dc9
·
verified ·
1 Parent(s): a53f193

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1203 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Newbeam
3
- emoji: 👁
4
- colorFrom: red
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: newbeam
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1203 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>BeamGen - Animated Beam Generator</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script>
10
+ tailwind.config = {
11
+ darkMode: 'class',
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ primary: {
16
+ 50: '#f0f9ff',
17
+ 100: '#e0f2fe',
18
+ 200: '#bae6fd',
19
+ 300: '#7dd3fc',
20
+ 400: '#38bdf8',
21
+ 500: '#0ea5e9',
22
+ 600: '#0284c7',
23
+ 700: '#0369a1',
24
+ 800: '#075985',
25
+ 900: '#0c4a6e',
26
+ },
27
+ dark: {
28
+ 800: '#1e293b',
29
+ 900: '#0f172a',
30
+ }
31
+ },
32
+ animation: {
33
+ 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
34
+ 'float': 'float 6s ease-in-out infinite',
35
+ 'spin-slow': 'spin 3s linear infinite',
36
+ },
37
+ keyframes: {
38
+ float: {
39
+ '0%, 100%': { transform: 'translateY(0)' },
40
+ '50%': { transform: 'translateY(-10px)' },
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ </script>
47
+ <style>
48
+ .gradient-beam {
49
+ position: relative;
50
+ height: 2px;
51
+ overflow: hidden;
52
+ }
53
+
54
+ .gradient-beam::after {
55
+ content: '';
56
+ position: absolute;
57
+ top: 0;
58
+ left: 0;
59
+ right: 0;
60
+ bottom: 0;
61
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 0) 100%);
62
+ animation: beam-animation 2s ease-in-out infinite;
63
+ }
64
+
65
+ @keyframes beam-animation {
66
+ 0% { transform: translateX(-100%); }
67
+ 100% { transform: translateX(100%); }
68
+ }
69
+
70
+ .canvas-container {
71
+ background-image:
72
+ linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
73
+ linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
74
+ background-size: 20px 20px;
75
+ }
76
+
77
+ .custom-scrollbar::-webkit-scrollbar {
78
+ width: 6px;
79
+ height: 6px;
80
+ }
81
+
82
+ .custom-scrollbar::-webkit-scrollbar-track {
83
+ background: rgba(255, 255, 255, 0.05);
84
+ }
85
+
86
+ .custom-scrollbar::-webkit-scrollbar-thumb {
87
+ background: rgba(255, 255, 255, 0.2);
88
+ border-radius: 3px;
89
+ }
90
+
91
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
92
+ background: rgba(255, 255, 255, 0.3);
93
+ }
94
+
95
+ .tab-active {
96
+ position: relative;
97
+ }
98
+
99
+ .tab-active::after {
100
+ content: '';
101
+ position: absolute;
102
+ bottom: -1px;
103
+ left: 0;
104
+ right: 0;
105
+ height: 2px;
106
+ background-color: #0ea5e9;
107
+ }
108
+
109
+ .dot-grid {
110
+ background-image: radial-gradient(rgba(255, 255, 255, 0.1) 1px, transparent 1px);
111
+ background-size: 10px 10px;
112
+ }
113
+
114
+ .draggable {
115
+ cursor: move;
116
+ touch-action: none;
117
+ user-select: none;
118
+ }
119
+
120
+ #beamPath {
121
+ stroke-linecap: round;
122
+ }
123
+
124
+ .color-preview {
125
+ transition: all 0.2s ease;
126
+ }
127
+
128
+ .color-preview:hover {
129
+ transform: scale(1.1);
130
+ }
131
+ </style>
132
+ </head>
133
+ <body class="bg-gray-50 dark:bg-dark-900 text-gray-800 dark:text-gray-200 transition-colors duration-200">
134
+ <!-- Navigation -->
135
+ <nav class="fixed top-0 left-0 right-0 z-50 bg-white/80 dark:bg-dark-800/80 backdrop-blur-md border-b border-gray-200 dark:border-gray-700">
136
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
137
+ <div class="flex items-center justify-between h-16">
138
+ <div class="flex items-center">
139
+ <div class="flex-shrink-0 flex items-center">
140
+ <div class="w-8 h-8 rounded-full bg-gradient-to-br from-primary-400 to-primary-600 flex items-center justify-center">
141
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-5 h-5 text-white">
142
+ <path d="M5 12h14"></path>
143
+ <path d="M12 5l7 7-7 7"></path>
144
+ </svg>
145
+ </div>
146
+ <span class="ml-2 text-xl font-bold dark:text-white">BeamGen</span>
147
+ </div>
148
+ <div class="hidden md:block">
149
+ <div class="ml-10 flex items-baseline space-x-4">
150
+ <a href="#" class="px-3 py-2 rounded-md text-sm font-medium bg-primary-500 text-white">Editor</a>
151
+ <a href="#" class="px-3 py-2 rounded-md text-sm font-medium hover:bg-gray-100 dark:hover:bg-gray-700">Gallery</a>
152
+ <a href="#" class="px-3 py-2 rounded-md text-sm font-medium hover:bg-gray-100 dark:hover:bg-gray-700">Docs</a>
153
+ <a href="#" class="px-3 py-2 rounded-md text-sm font-medium hover:bg-gray-100 dark:hover:bg-gray-700">Pricing</a>
154
+ </div>
155
+ </div>
156
+ </div>
157
+ <div class="hidden md:block">
158
+ <div class="ml-4 flex items-center md:ml-6">
159
+ <button type="button" class="p-1 rounded-full text-gray-400 hover:text-gray-500 dark:hover:text-gray-300 focus:outline-none">
160
+ <span class="sr-only">Dark mode</span>
161
+ <i class="fas fa-moon" id="dark-mode-toggle"></i>
162
+ </button>
163
+ <button class="ml-4 px-4 py-2 rounded-md text-sm font-medium border border-primary-500 text-primary-500 hover:bg-primary-500 hover:text-white transition-colors">
164
+ Sign in
165
+ </button>
166
+ <button class="ml-2 px-4 py-2 rounded-md text-sm font-medium bg-primary-500 text-white hover:bg-primary-600 transition-colors">
167
+ Sign up
168
+ </button>
169
+ </div>
170
+ </div>
171
+ <div class="-mr-2 flex md:hidden">
172
+ <button type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 dark:hover:text-gray-300 focus:outline-none">
173
+ <span class="sr-only">Open main menu</span>
174
+ <svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
175
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
176
+ </svg>
177
+ </button>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </nav>
182
+
183
+ <!-- Main Content -->
184
+ <div class="pt-16 pb-12 flex flex-col h-screen">
185
+ <div class="flex flex-1 overflow-hidden">
186
+ <!-- Sidebar -->
187
+ <div class="w-64 flex-shrink-0 border-r border-gray-200 dark:border-gray-700 bg-white dark:bg-dark-800 overflow-y-auto custom-scrollbar">
188
+ <div class="p-4">
189
+ <div class="flex items-center justify-between mb-4">
190
+ <h2 class="text-lg font-semibold">Beam Properties</h2>
191
+ <button class="text-xs text-primary-500 hover:text-primary-600" id="reset-btn">Reset</button>
192
+ </div>
193
+
194
+ <div class="space-y-6">
195
+ <!-- Path Type -->
196
+ <div>
197
+ <h3 class="text-sm font-medium mb-2">Path Type</h3>
198
+ <div class="grid grid-cols-3 gap-2" id="path-type-buttons">
199
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="straight">
200
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
201
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16" />
202
+ </svg>
203
+ <span class="text-xs mt-1">Straight</span>
204
+ </button>
205
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="curved">
206
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
207
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14" />
208
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5l7 7-7 7" />
209
+ </svg>
210
+ <span class="text-xs mt-1">Curved</span>
211
+ </button>
212
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="zigzag">
213
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
214
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v14m7-7H5" />
215
+ </svg>
216
+ <span class="text-xs mt-1">Zigzag</span>
217
+ </button>
218
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="circular">
219
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
220
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
221
+ </svg>
222
+ <span class="text-xs mt-1">Circular</span>
223
+ </button>
224
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="spline">
225
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
226
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4" />
227
+ </svg>
228
+ <span class="text-xs mt-1">Spline</span>
229
+ </button>
230
+ <button class="p-2 border rounded-md hover:border-primary-500 flex flex-col items-center path-type-btn" data-type="3d">
231
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
232
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 10l-2 1m0 0l-2-1m2 1v2.5M20 7l-2 1m2-1l-2-1m2 1v2.5M14 4l-2-1-2 1M4 7l2-1M4 7l2 1M4 7v2.5M12 21l-2-1m2 1l2-1m-2 1v-2.5M6 18l-2-1v-2.5M18 18l2-1v-2.5" />
233
+ </svg>
234
+ <span class="text-xs mt-1">3D</span>
235
+ </button>
236
+ </div>
237
+ </div>
238
+
239
+ <!-- Color Settings -->
240
+ <div>
241
+ <h3 class="text-sm font-medium mb-2">Color</h3>
242
+ <div class="flex space-x-2 mb-2" id="color-type-buttons">
243
+ <button class="px-3 py-1 text-xs rounded-md bg-gray-100 dark:bg-gray-700 color-type-btn" data-type="solid">Solid</button>
244
+ <button class="px-3 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 color-type-btn" data-type="gradient">Gradient</button>
245
+ <button class="px-3 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 color-type-btn" data-type="animated">Animated</button>
246
+ </div>
247
+ <div class="flex items-center space-x-2">
248
+ <div class="w-8 h-8 rounded-md bg-gradient-to-r from-purple-500 to-pink-500 cursor-pointer color-preview" id="color-picker-btn"></div>
249
+ <input type="text" value="#0ea5e9" class="flex-1 text-xs px-2 py-1 border rounded-md dark:bg-gray-700" id="color-input">
250
+ </div>
251
+ <div class="mt-2 hidden" id="gradient-controls">
252
+ <div class="flex items-center space-x-2">
253
+ <div class="w-8 h-8 rounded-md bg-gradient-to-r from-purple-500 to-pink-500 cursor-pointer color-preview" id="gradient-color-picker-btn"></div>
254
+ <input type="text" value="#ec4899" class="flex-1 text-xs px-2 py-1 border rounded-md dark:bg-gray-700" id="gradient-color-input">
255
+ </div>
256
+ <div class="mt-2">
257
+ <div class="flex justify-between items-center mb-1">
258
+ <span class="text-xs">Direction</span>
259
+ <span class="text-xs" id="gradient-direction-value">90°</span>
260
+ </div>
261
+ <input type="range" min="0" max="360" value="90" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" id="gradient-direction">
262
+ </div>
263
+ </div>
264
+ </div>
265
+
266
+ <!-- Width Slider -->
267
+ <div>
268
+ <div class="flex justify-between items-center mb-1">
269
+ <h3 class="text-sm font-medium">Width</h3>
270
+ <span class="text-xs" id="width-value">4px</span>
271
+ </div>
272
+ <input type="range" min="1" max="20" value="4" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" id="width-slider">
273
+ </div>
274
+
275
+ <!-- Opacity Slider -->
276
+ <div>
277
+ <div class="flex justify-between items-center mb-1">
278
+ <h3 class="text-sm font-medium">Opacity</h3>
279
+ <span class="text-xs" id="opacity-value">80%</span>
280
+ </div>
281
+ <input type="range" min="0" max="100" value="80" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" id="opacity-slider">
282
+ </div>
283
+
284
+ <!-- Animation Settings -->
285
+ <div>
286
+ <h3 class="text-sm font-medium mb-2">Animation</h3>
287
+ <div class="grid grid-cols-2 gap-2 mb-2" id="animation-trigger-buttons">
288
+ <button class="px-2 py-1 text-xs rounded-md bg-gray-100 dark:bg-gray-700 animation-trigger-btn" data-trigger="load">On Load</button>
289
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 animation-trigger-btn" data-trigger="hover">On Hover</button>
290
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 animation-trigger-btn" data-trigger="click">On Click</button>
291
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 animation-trigger-btn" data-trigger="scroll">On Scroll</button>
292
+ </div>
293
+ <div class="flex justify-between items-center mb-1">
294
+ <span class="text-xs">Speed</span>
295
+ <span class="text-xs" id="speed-value">Medium</span>
296
+ </div>
297
+ <input type="range" min="0" max="100" value="50" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" id="speed-slider">
298
+ </div>
299
+
300
+ <!-- Effects -->
301
+ <div>
302
+ <h3 class="text-sm font-medium mb-2">Effects</h3>
303
+ <div class="space-y-2">
304
+ <label class="flex items-center space-x-2">
305
+ <input type="checkbox" class="rounded text-primary-500 effect-checkbox" data-effect="pulsing">
306
+ <span class="text-sm">Pulsing</span>
307
+ </label>
308
+ <label class="flex items-center space-x-2">
309
+ <input type="checkbox" class="rounded text-primary-500 effect-checkbox" data-effect="sparkling">
310
+ <span class="text-sm">Sparkling</span>
311
+ </label>
312
+ <label class="flex items-center space-x-2">
313
+ <input type="checkbox" class="rounded text-primary-500 effect-checkbox" data-effect="glow" checked>
314
+ <span class="text-sm">Glow</span>
315
+ </label>
316
+ <label class="flex items-center space-x-2">
317
+ <input type="checkbox" class="rounded text-primary-500 effect-checkbox" data-effect="particles">
318
+ <span class="text-sm">Particles</span>
319
+ </label>
320
+ </div>
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+
326
+ <!-- Main Canvas -->
327
+ <div class="flex-1 flex flex-col overflow-hidden">
328
+ <!-- Toolbar -->
329
+ <div class="border-b border-gray-200 dark:border-gray-700 bg-white dark:bg-dark-800 p-2 flex items-center justify-between">
330
+ <div class="flex space-x-2">
331
+ <button class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">
332
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
333
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
334
+ </svg>
335
+ </button>
336
+ <button class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">
337
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
338
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
339
+ </svg>
340
+ </button>
341
+ <button class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">
342
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
343
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
344
+ </svg>
345
+ </button>
346
+ <div class="border-l border-gray-200 dark:border-gray-700 mx-2"></div>
347
+ <button class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">
348
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
349
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
350
+ </svg>
351
+ </button>
352
+ <button class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700">
353
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
354
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
355
+ </svg>
356
+ </button>
357
+ </div>
358
+ <div class="flex space-x-2">
359
+ <button class="px-3 py-1 text-sm rounded-md border border-gray-200 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700" id="export-btn">
360
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 inline mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
361
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
362
+ </svg>
363
+ Export
364
+ </button>
365
+ <button class="px-3 py-1 text-sm rounded-md bg-primary-500 text-white hover:bg-primary-600" id="save-btn">
366
+ Save
367
+ </button>
368
+ </div>
369
+ </div>
370
+
371
+ <!-- Canvas Area -->
372
+ <div class="flex-1 overflow-auto canvas-container dot-grid relative" id="canvas">
373
+ <svg width="100%" height="100%" class="absolute inset-0">
374
+ <path id="beamPath" stroke="url(#beamGradient)" fill="none" stroke-width="4" stroke-opacity="0.8" filter="url(#glowFilter)"></path>
375
+ <defs>
376
+ <linearGradient id="beamGradient" x1="0%" y1="0%" x2="100%" y2="0%">
377
+ <stop offset="0%" stop-color="#0ea5e9" />
378
+ <stop offset="100%" stop-color="#0ea5e9" />
379
+ </linearGradient>
380
+ <filter id="glowFilter" x="-30%" y="-30%" width="160%" height="160%">
381
+ <feGaussianBlur stdDeviation="4" result="blur" />
382
+ <feComposite in="SourceGraphic" in2="blur" operator="over" />
383
+ </filter>
384
+ </defs>
385
+ </svg>
386
+
387
+ <!-- Draggable Points -->
388
+ <div class="absolute w-8 h-8 rounded-full bg-primary-500 flex items-center justify-center cursor-move shadow-lg draggable" id="startPoint" style="left: 25%; top: 40%;">
389
+ <div class="w-3 h-3 bg-white rounded-full"></div>
390
+ </div>
391
+ <div class="absolute w-8 h-8 rounded-full bg-primary-500 flex items-center justify-center cursor-move shadow-lg draggable" id="endPoint" style="left: 75%; top: 60%;">
392
+ <div class="w-3 h-3 bg-white rounded-full"></div>
393
+ </div>
394
+ <div class="absolute w-6 h-6 rounded-full bg-pink-500 flex items-center justify-center cursor-move shadow-lg draggable control-point" id="controlPoint1" style="left: 40%; top: 30%;">
395
+ <div class="w-2 h-2 bg-white rounded-full"></div>
396
+ </div>
397
+ <div class="absolute w-6 h-6 rounded-full bg-pink-500 flex items-center justify-center cursor-move shadow-lg draggable control-point" id="controlPoint2" style="left: 60%; top: 70%;">
398
+ <div class="w-2 h-2 bg-white rounded-full"></div>
399
+ </div>
400
+ </div>
401
+
402
+ <!-- Properties Panel -->
403
+ <div class="border-t border-gray-200 dark:border-gray-700 bg-white dark:bg-dark-800 p-4">
404
+ <div class="flex border-b border-gray-200 dark:border-gray-700">
405
+ <button class="px-4 py-2 text-sm font-medium tab-active" data-tab="beam">Beam</button>
406
+ <button class="px-4 py-2 text-sm font-medium" data-tab="path">Path</button>
407
+ <button class="px-4 py-2 text-sm font-medium" data-tab="effects">Effects</button>
408
+ <button class="px-4 py-2 text-sm font-medium" data-tab="export">Export</button>
409
+ </div>
410
+ <div class="mt-4 grid grid-cols-2 gap-4" id="beam-tab">
411
+ <div>
412
+ <label class="block text-sm font-medium mb-1">Direction</label>
413
+ <select class="w-full text-sm border rounded-md px-3 py-2 dark:bg-gray-700" id="direction-select">
414
+ <option value="forward">Forward</option>
415
+ <option value="reverse">Reverse</option>
416
+ <option value="bidirectional">Bidirectional</option>
417
+ <option value="pingpong">Ping Pong</option>
418
+ </select>
419
+ </div>
420
+ <div>
421
+ <label class="block text-sm font-medium mb-1">Easing</label>
422
+ <select class="w-full text-sm border rounded-md px-3 py-2 dark:bg-gray-700" id="easing-select">
423
+ <option value="linear">Linear</option>
424
+ <option value="ease-in">Ease In</option>
425
+ <option value="ease-out">Ease Out</option>
426
+ <option value="ease-in-out">Ease In Out</option>
427
+ </select>
428
+ </div>
429
+ <div>
430
+ <label class="block text-sm font-medium mb-1">Duration (ms)</label>
431
+ <input type="number" value="2000" class="w-full text-sm border rounded-md px-3 py-2 dark:bg-gray-700" id="duration-input">
432
+ </div>
433
+ <div>
434
+ <label class="block text-sm font-medium mb-1">Delay (ms)</label>
435
+ <input type="number" value="0" class="w-full text-sm border rounded-md px-3 py-2 dark:bg-gray-700" id="delay-input">
436
+ </div>
437
+ </div>
438
+ </div>
439
+ </div>
440
+
441
+ <!-- Export Panel -->
442
+ <div class="w-80 flex-shrink-0 border-l border-gray-200 dark:border-gray-700 bg-white dark:bg-dark-800 overflow-y-auto custom-scrollbar" id="export-panel">
443
+ <div class="p-4">
444
+ <h2 class="text-lg font-semibold mb-4">Export Settings</h2>
445
+
446
+ <div class="space-y-6">
447
+ <!-- Framework Selection -->
448
+ <div>
449
+ <h3 class="text-sm font-medium mb-2">Framework</h3>
450
+ <div class="grid grid-cols-2 gap-2" id="framework-buttons">
451
+ <button class="px-2 py-2 text-xs rounded-md bg-gray-100 dark:bg-gray-700 flex flex-col items-center framework-btn" data-framework="react">
452
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
453
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
454
+ </svg>
455
+ <span class="mt-1">React</span>
456
+ </button>
457
+ <button class="px-2 py-2 text-xs rounded-md border border-gray-200 dark:border-gray-600 flex flex-col items-center framework-btn" data-framework="vue">
458
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
459
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
460
+ </svg>
461
+ <span class="mt-1">Vue</span>
462
+ </button>
463
+ <button class="px-2 py-2 text-xs rounded-md border border-gray-200 dark:border-gray-600 flex flex-col items-center framework-btn" data-framework="svelte">
464
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
465
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
466
+ </svg>
467
+ <span class="mt-1">Svelte</span>
468
+ </button>
469
+ <button class="px-2 py-2 text-xs rounded-md border border-gray-200 dark:border-gray-600 flex flex-col items-center framework-btn" data-framework="js">
470
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
471
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" />
472
+ </svg>
473
+ <span class="mt-1">JS</span>
474
+ </button>
475
+ </div>
476
+ </div>
477
+
478
+ <!-- Export Format -->
479
+ <div>
480
+ <h3 class="text-sm font-medium mb-2">Format</h3>
481
+ <div class="grid grid-cols-3 gap-2" id="format-buttons">
482
+ <button class="px-2 py-1 text-xs rounded-md bg-gray-100 dark:bg-gray-700 format-btn" data-format="code">Code</button>
483
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 format-btn" data-format="svg">SVG</button>
484
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 format-btn" data-format="css">CSS</button>
485
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 format-btn" data-format="gif">GIF</button>
486
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 format-btn" data-format="mp4">MP4</button>
487
+ <button class="px-2 py-1 text-xs rounded-md border border-gray-200 dark:border-gray-600 format-btn" data-format="webm">WebM</button>
488
+ </div>
489
+ </div>
490
+
491
+ <!-- Code Preview -->
492
+ <div>
493
+ <h3 class="text-sm font-medium mb-2">Code Preview</h3>
494
+ <div class="bg-gray-800 text-gray-200 p-3 rounded-md text-xs font-mono overflow-x-auto" id="code-preview">
495
+ <pre><code id="code-content">import React from 'react';
496
+ import './Beam.css';
497
+
498
+ const AnimatedBeam = () => {
499
+ return (
500
+ &lt;div className="beam-container"&gt;
501
+ &lt;div className="gradient-beam" /&gt;
502
+ &lt;/div&gt;
503
+ );
504
+ };
505
+
506
+ export default AnimatedBeam;</code></pre>
507
+ </div>
508
+ <button class="mt-2 w-full py-2 bg-primary-500 text-white rounded-md hover:bg-primary-600 flex items-center justify-center" id="copy-code-btn">
509
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
510
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
511
+ </svg>
512
+ Copy Code
513
+ </button>
514
+ </div>
515
+
516
+ <!-- Download Options -->
517
+ <div>
518
+ <h3 class="text-sm font-medium mb-2">Download</h3>
519
+ <div class="space-y-2">
520
+ <button class="w-full py-2 border border-gray-200 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center justify-center" id="download-svg-btn">
521
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
522
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
523
+ </svg>
524
+ Download SVG
525
+ </button>
526
+ <button class="w-full py-2 border border-gray-200 dark:border-gray-600 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center justify-center" id="download-gif-btn">
527
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
528
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
529
+ </svg>
530
+ Download GIF
531
+ </button>
532
+ </div>
533
+ </div>
534
+ </div>
535
+ </div>
536
+ </div>
537
+ </div>
538
+ </div>
539
+
540
+ <script>
541
+ // State management
542
+ const state = {
543
+ pathType: 'curved',
544
+ colorType: 'solid',
545
+ color: '#0ea5e9',
546
+ gradientColor: '#ec4899',
547
+ gradientDirection: 90,
548
+ width: 4,
549
+ opacity: 80,
550
+ animationTrigger: 'load',
551
+ animationSpeed: 50,
552
+ effects: {
553
+ pulsing: false,
554
+ sparkling: false,
555
+ glow: true,
556
+ particles: false
557
+ },
558
+ direction: 'forward',
559
+ easing: 'linear',
560
+ duration: 2000,
561
+ delay: 0,
562
+ framework: 'react',
563
+ exportFormat: 'code',
564
+ points: {
565
+ start: { x: 25, y: 40 },
566
+ end: { x: 75, y: 60 },
567
+ control1: { x: 40, y: 30 },
568
+ control2: { x: 60, y: 70 }
569
+ }
570
+ };
571
+
572
+ // DOM elements
573
+ const elements = {
574
+ beamPath: document.getElementById('beamPath'),
575
+ beamGradient: document.querySelector('#beamGradient'),
576
+ glowFilter: document.querySelector('#glowFilter'),
577
+ startPoint: document.getElementById('startPoint'),
578
+ endPoint: document.getElementById('endPoint'),
579
+ controlPoint1: document.getElementById('controlPoint1'),
580
+ controlPoint2: document.getElementById('controlPoint2'),
581
+ canvas: document.getElementById('canvas'),
582
+ exportPanel: document.getElementById('export-panel'),
583
+ codePreview: document.getElementById('code-preview'),
584
+ codeContent: document.getElementById('code-content'),
585
+ gradientControls: document.getElementById('gradient-controls'),
586
+ colorInput: document.getElementById('color-input'),
587
+ gradientColorInput: document.getElementById('gradient-color-input'),
588
+ gradientDirection: document.getElementById('gradient-direction'),
589
+ gradientDirectionValue: document.getElementById('gradient-direction-value'),
590
+ widthSlider: document.getElementById('width-slider'),
591
+ widthValue: document.getElementById('width-value'),
592
+ opacitySlider: document.getElementById('opacity-slider'),
593
+ opacityValue: document.getElementById('opacity-value'),
594
+ speedSlider: document.getElementById('speed-slider'),
595
+ speedValue: document.getElementById('speed-value'),
596
+ directionSelect: document.getElementById('direction-select'),
597
+ easingSelect: document.getElementById('easing-select'),
598
+ durationInput: document.getElementById('duration-input'),
599
+ delayInput: document.getElementById('delay-input'),
600
+ colorPickerBtn: document.getElementById('color-picker-btn'),
601
+ gradientColorPickerBtn: document.getElementById('gradient-color-picker-btn'),
602
+ colorPreview: document.getElementById('color-picker-btn'),
603
+ gradientColorPreview: document.getElementById('gradient-color-picker-btn')
604
+ };
605
+
606
+ // Initialize the app
607
+ function init() {
608
+ setupEventListeners();
609
+ updateBeam();
610
+ updateUI();
611
+ updateCodePreview();
612
+ }
613
+
614
+ // Set up event listeners
615
+ function setupEventListeners() {
616
+ // Path type buttons
617
+ document.querySelectorAll('.path-type-btn').forEach(btn => {
618
+ btn.addEventListener('click', () => {
619
+ state.pathType = btn.dataset.type;
620
+ updateBeam();
621
+ updateUI();
622
+ });
623
+ });
624
+
625
+ // Color type buttons
626
+ document.querySelectorAll('.color-type-btn').forEach(btn => {
627
+ btn.addEventListener('click', () => {
628
+ state.colorType = btn.dataset.type;
629
+ updateBeam();
630
+ updateUI();
631
+ });
632
+ });
633
+
634
+ // Animation trigger buttons
635
+ document.querySelectorAll('.animation-trigger-btn').forEach(btn => {
636
+ btn.addEventListener('click', () => {
637
+ state.animationTrigger = btn.dataset.trigger;
638
+ updateBeam();
639
+ updateUI();
640
+ });
641
+ });
642
+
643
+ // Effect checkboxes
644
+ document.querySelectorAll('.effect-checkbox').forEach(checkbox => {
645
+ checkbox.addEventListener('change', () => {
646
+ state.effects[checkbox.dataset.effect] = checkbox.checked;
647
+ updateBeam();
648
+ updateUI();
649
+ });
650
+ });
651
+
652
+ // Framework buttons
653
+ document.querySelectorAll('.framework-btn').forEach(btn => {
654
+ btn.addEventListener('click', () => {
655
+ state.framework = btn.dataset.framework;
656
+ updateUI();
657
+ updateCodePreview();
658
+ });
659
+ });
660
+
661
+ // Format buttons
662
+ document.querySelectorAll('.format-btn').forEach(btn => {
663
+ btn.addEventListener('click', () => {
664
+ state.exportFormat = btn.dataset.format;
665
+ updateUI();
666
+ updateCodePreview();
667
+ });
668
+ });
669
+
670
+ // Input fields
671
+ elements.colorInput.addEventListener('input', () => {
672
+ state.color = elements.colorInput.value;
673
+ updateBeam();
674
+ updateUI();
675
+ });
676
+
677
+ elements.gradientColorInput.addEventListener('input', () => {
678
+ state.gradientColor = elements.gradientColorInput.value;
679
+ updateBeam();
680
+ updateUI();
681
+ });
682
+
683
+ elements.gradientDirection.addEventListener('input', () => {
684
+ state.gradientDirection = elements.gradientDirection.value;
685
+ updateBeam();
686
+ updateUI();
687
+ });
688
+
689
+ elements.widthSlider.addEventListener('input', () => {
690
+ state.width = elements.widthSlider.value;
691
+ updateBeam();
692
+ updateUI();
693
+ });
694
+
695
+ elements.opacitySlider.addEventListener('input', () => {
696
+ state.opacity = elements.opacitySlider.value;
697
+ updateBeam();
698
+ updateUI();
699
+ });
700
+
701
+ elements.speedSlider.addEventListener('input', () => {
702
+ state.animationSpeed = elements.speedSlider.value;
703
+ updateBeam();
704
+ updateUI();
705
+ });
706
+
707
+ elements.directionSelect.addEventListener('change', () => {
708
+ state.direction = elements.directionSelect.value;
709
+ updateBeam();
710
+ updateUI();
711
+ });
712
+
713
+ elements.easingSelect.addEventListener('change', () => {
714
+ state.easing = elements.easingSelect.value;
715
+ updateBeam();
716
+ updateUI();
717
+ });
718
+
719
+ elements.durationInput.addEventListener('input', () => {
720
+ state.duration = elements.durationInput.value;
721
+ updateBeam();
722
+ updateUI();
723
+ });
724
+
725
+ elements.delayInput.addEventListener('input', () => {
726
+ state.delay = elements.delayInput.value;
727
+ updateBeam();
728
+ updateUI();
729
+ });
730
+
731
+ // Color picker buttons
732
+ elements.colorPickerBtn.addEventListener('click', () => {
733
+ elements.colorInput.value = '#38bdf8';
734
+ state.color = '#38bdf8';
735
+ updateBeam();
736
+ updateUI();
737
+ });
738
+
739
+ elements.gradientColorPickerBtn.addEventListener('click', () => {
740
+ elements.gradientColorInput.value = '#ec4899';
741
+ state.gradientColor = '#ec4899';
742
+ updateBeam();
743
+ updateUI();
744
+ });
745
+
746
+ // Copy code button
747
+ document.getElementById('copy-code-btn').addEventListener('click', () => {
748
+ navigator.clipboard.writeText(elements.codeContent.textContent);
749
+ alert('Code copied to clipboard!');
750
+ });
751
+
752
+ // Export buttons
753
+ document.getElementById('export-btn').addEventListener('click', () => {
754
+ elements.exportPanel.classList.toggle('hidden');
755
+ });
756
+
757
+ // Download buttons
758
+ document.getElementById('download-svg-btn').addEventListener('click', () => {
759
+ alert('SVG download would start here in a real implementation');
760
+ });
761
+
762
+ document.getElementById('download-gif-btn').addEventListener('click', () => {
763
+ alert('GIF download would start here in a real implementation');
764
+ });
765
+
766
+ // Reset button
767
+ document.getElementById('reset-btn').addEventListener('click', () => {
768
+ resetToDefaults();
769
+ updateBeam();
770
+ updateUI();
771
+ });
772
+
773
+ // Tab buttons
774
+ document.querySelectorAll('[data-tab]').forEach(tab => {
775
+ tab.addEventListener('click', () => {
776
+ document.querySelectorAll('[data-tab]').forEach(t => t.classList.remove('tab-active'));
777
+ tab.classList.add('tab-active');
778
+ });
779
+ });
780
+
781
+ // Dark mode toggle
782
+ document.getElementById('dark-mode-toggle').addEventListener('click', toggleDarkMode);
783
+
784
+ // Draggable points
785
+ setupDraggablePoints();
786
+ }
787
+
788
+ // Set up draggable points
789
+ function setupDraggablePoints() {
790
+ const draggables = document.querySelectorAll('.draggable');
791
+
792
+ draggables.forEach(draggable => {
793
+ let isDragging = false;
794
+ let offsetX, offsetY;
795
+
796
+ draggable.addEventListener('mousedown', (e) => {
797
+ isDragging = true;
798
+ const rect = draggable.getBoundingClientRect();
799
+ offsetX = e.clientX - rect.left;
800
+ offsetY = e.clientY - rect.top;
801
+ draggable.style.zIndex = '100';
802
+ e.preventDefault();
803
+ });
804
+
805
+ document.addEventListener('mousemove', (e) => {
806
+ if (!isDragging) return;
807
+
808
+ const canvasRect = elements.canvas.getBoundingClientRect();
809
+ const maxX = canvasRect.width - draggable.offsetWidth;
810
+ const maxY = canvasRect.height - draggable.offsetHeight;
811
+
812
+ let x = e.clientX - canvasRect.left - offsetX;
813
+ let y = e.clientY - canvasRect.top - offsetY;
814
+
815
+ // Constrain to canvas
816
+ x = Math.max(0, Math.min(x, maxX));
817
+ y = Math.max(0, Math.min(y, maxY));
818
+
819
+ // Update position
820
+ draggable.style.left = `${(x / canvasRect.width) * 100}%`;
821
+ draggable.style.top = `${(y / canvasRect.height) * 100}%`;
822
+
823
+ // Update state
824
+ const pointId = draggable.id.replace('Point', '').toLowerCase();
825
+ if (pointId === 'start') {
826
+ state.points.start.x = (x / canvasRect.width) * 100;
827
+ state.points.start.y = (y / canvasRect.height) * 100;
828
+ } else if (pointId === 'end') {
829
+ state.points.end.x = (x / canvasRect.width) * 100;
830
+ state.points.end.y = (y / canvasRect.height) * 100;
831
+ } else if (pointId === 'control1') {
832
+ state.points.control1.x = (x / canvasRect.width) * 100;
833
+ state.points.control1.y = (y / canvasRect.height) * 100;
834
+ } else if (pointId === 'control2') {
835
+ state.points.control2.x = (x / canvasRect.width) * 100;
836
+ state.points.control2.y = (y / canvasRect.height) * 100;
837
+ }
838
+
839
+ updateBeam();
840
+ });
841
+
842
+ document.addEventListener('mouseup', () => {
843
+ if (isDragging) {
844
+ isDragging = false;
845
+ draggable.style.zIndex = '';
846
+ }
847
+ });
848
+ });
849
+ }
850
+
851
+ // Update the beam based on current state
852
+ function updateBeam() {
853
+ // Update path
854
+ let pathData;
855
+ const canvasRect = elements.canvas.getBoundingClientRect();
856
+
857
+ const startX = (state.points.start.x / 100) * canvasRect.width;
858
+ const startY = (state.points.start.y / 100) * canvasRect.height;
859
+ const endX = (state.points.end.x / 100) * canvasRect.width;
860
+ const endY = (state.points.end.y / 100) * canvasRect.height;
861
+ const control1X = (state.points.control1.x / 100) * canvasRect.width;
862
+ const control1Y = (state.points.control1.y / 100) * canvasRect.height;
863
+ const control2X = (state.points.control2.x / 100) * canvasRect.width;
864
+ const control2Y = (state.points.control2.y / 100) * canvasRect.height;
865
+
866
+ switch (state.pathType) {
867
+ case 'straight':
868
+ pathData = `M${startX},${startY} L${endX},${endY}`;
869
+ break;
870
+ case 'curved':
871
+ pathData = `M${startX},${startY} C${control1X},${control1Y} ${control2X},${control2Y} ${endX},${endY}`;
872
+ break;
873
+ case 'zigzag':
874
+ const midX1 = startX + (endX - startX) * 0.3;
875
+ const midY1 = startY + (endY - startY) * 0.7;
876
+ const midX2 = startX + (endX - startX) * 0.7;
877
+ const midY2 = startY + (endY - startY) * 0.3;
878
+ pathData = `M${startX},${startY} L${midX1},${midY1} L${midX2},${midY2} L${endX},${endY}`;
879
+ break;
880
+ case 'circular':
881
+ const radius = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2)) / 2;
882
+ const centerX = (startX + endX) / 2;
883
+ const centerY = (startY + endY) / 2;
884
+ pathData = `M${startX},${startY} A${radius},${radius} 0 0,1 ${endX},${endY}`;
885
+ break;
886
+ case 'spline':
887
+ pathData = `M${startX},${startY} Q${control1X},${control1Y} ${endX},${endY}`;
888
+ break;
889
+ case '3d':
890
+ // Simplified 3D effect with two curves
891
+ const depth = 50;
892
+ const midX = (startX + endX) / 2;
893
+ const midY = (startY + endY) / 2;
894
+ pathData = `M${startX},${startY} C${midX},${midY - depth} ${midX},${midY - depth} ${endX},${endY}`;
895
+ break;
896
+ default:
897
+ pathData = `M${startX},${startY} L${endX},${endY}`;
898
+ }
899
+
900
+ elements.beamPath.setAttribute('d', pathData);
901
+
902
+ // Update color
903
+ if (state.colorType === 'solid') {
904
+ elements.beamGradient.innerHTML = `
905
+ <stop offset="0%" stop-color="${state.color}" />
906
+ <stop offset="100%" stop-color="${state.color}" />
907
+ `;
908
+ } else if (state.colorType === 'gradient') {
909
+ elements.beamGradient.innerHTML = `
910
+ <stop offset="0%" stop-color="${state.color}" />
911
+ <stop offset="100%" stop-color="${state.gradientColor}" />
912
+ `;
913
+ elements.beamGradient.setAttribute('x1', '0%');
914
+ elements.beamGradient.setAttribute('y1', '0%');
915
+ elements.beamGradient.setAttribute('x2', `${Math.cos((state.gradientDirection - 90) * Math.PI / 180) * 100}%`);
916
+ elements.beamGradient.setAttribute('y2', `${Math.sin((state.gradientDirection - 90) * Math.PI / 180) * 100}%`);
917
+ } else { // animated
918
+ elements.beamGradient.innerHTML = `
919
+ <stop offset="0%" stop-color="${state.color}" />
920
+ <stop offset="50%" stop-color="${state.gradientColor}" />
921
+ <stop offset="100%" stop-color="${state.color}" />
922
+ `;
923
+ }
924
+
925
+ // Update width and opacity
926
+ elements.beamPath.setAttribute('stroke-width', state.width);
927
+ elements.beamPath.setAttribute('stroke-opacity', state.opacity / 100);
928
+
929
+ // Update effects
930
+ if (state.effects.glow) {
931
+ elements.beamPath.setAttribute('filter', 'url(#glowFilter)');
932
+ elements.glowFilter.innerHTML = `
933
+ <feGaussianBlur stdDeviation="${state.width / 2}" result="blur" />
934
+ <feComposite in="SourceGraphic" in2="blur" operator="over" />
935
+ `;
936
+ } else {
937
+ elements.beamPath.removeAttribute('filter');
938
+ }
939
+
940
+ // Update animation
941
+ const animationDuration = (2 - (state.animationSpeed / 100) * 1.8).toFixed(2); // 0.2s to 2s
942
+
943
+ // Remove existing style element if it exists
944
+ const existingStyle = document.getElementById('beamAnimationStyle');
945
+ if (existingStyle) {
946
+ existingStyle.remove();
947
+ }
948
+
949
+ // Add new animation style
950
+ const style = document.createElement('style');
951
+ style.id = 'beamAnimationStyle';
952
+ style.textContent = `
953
+ @keyframes beam-animation {
954
+ 0% { transform: translateX(-100%); }
955
+ 100% { transform: translateX(100%); }
956
+ }
957
+
958
+ #beamPath::after {
959
+ animation: beam-animation ${animationDuration}s ease-in-out infinite;
960
+ }
961
+ `;
962
+ document.head.appendChild(style);
963
+
964
+ // Show/hide control points based on path type
965
+ document.querySelectorAll('.control-point').forEach(point => {
966
+ point.style.display = state.pathType === 'curved' || state.pathType === 'spline' ? 'flex' : 'none';
967
+ });
968
+ }
969
+
970
+ // Update UI based on current state
971
+ function updateUI() {
972
+ // Update active buttons
973
+ document.querySelectorAll('.path-type-btn').forEach(btn => {
974
+ btn.classList.toggle('border-primary-500', btn.dataset.type === state.pathType);
975
+ btn.classList.toggle('bg-primary-50', btn.dataset.type === state.pathType);
976
+ btn.classList.toggle('dark:bg-primary-900/30', btn.dataset.type === state.pathType);
977
+ });
978
+
979
+ document.querySelectorAll('.color-type-btn').forEach(btn => {
980
+ btn.classList.toggle('bg-gray-100', btn.dataset.type === state.colorType);
981
+ btn.classList.toggle('dark:bg-gray-700', btn.dataset.type === state.colorType);
982
+ btn.classList.toggle('border-primary-500', btn.dataset.type === state.colorType);
983
+ });
984
+
985
+ document.querySelectorAll('.animation-trigger-btn').forEach(btn => {
986
+ btn.classList.toggle('bg-gray-100', btn.dataset.trigger === state.animationTrigger);
987
+ btn.classList.toggle('dark:bg-gray-700', btn.dataset.trigger === state.animationTrigger);
988
+ btn.classList.toggle('border-primary-500', btn.dataset.trigger === state.animationTrigger);
989
+ });
990
+
991
+ document.querySelectorAll('.framework-btn').forEach(btn => {
992
+ btn.classList.toggle('bg-gray-100', btn.dataset.framework === state.framework);
993
+ btn.classList.toggle('dark:bg-gray-700', btn.dataset.framework === state.framework);
994
+ });
995
+
996
+ document.querySelectorAll('.format-btn').forEach(btn => {
997
+ btn.classList.toggle('bg-gray-100', btn.dataset.format === state.exportFormat);
998
+ btn.classList.toggle('dark:bg-gray-700', btn.dataset.format === state.exportFormat);
999
+ });
1000
+
1001
+ // Update effect checkboxes
1002
+ document.querySelectorAll('.effect-checkbox').forEach(checkbox => {
1003
+ checkbox.checked = state.effects[checkbox.dataset.effect];
1004
+ });
1005
+
1006
+ // Update input values
1007
+ elements.colorInput.value = state.color;
1008
+ elements.gradientColorInput.value = state.gradientColor;
1009
+ elements.gradientDirection.value = state.gradientDirection;
1010
+ elements.gradientDirectionValue.textContent = `${state.gradientDirection}°`;
1011
+ elements.widthSlider.value = state.width;
1012
+ elements.widthValue.textContent = `${state.width}px`;
1013
+ elements.opacitySlider.value = state.opacity;
1014
+ elements.opacityValue.textContent = `${state.opacity}%`;
1015
+ elements.speedSlider.value = state.animationSpeed;
1016
+ elements.speedValue.textContent = getSpeedLabel(state.animationSpeed);
1017
+ elements.directionSelect.value = state.direction;
1018
+ elements.easingSelect.value = state.easing;
1019
+ elements.durationInput.value = state.duration;
1020
+ elements.delayInput.value = state.delay;
1021
+
1022
+ // Update color preview
1023
+ elements.colorPreview.style.background = state.color;
1024
+ elements.gradientColorPreview.style.background = state.gradientColor;
1025
+
1026
+ // Show/hide gradient controls
1027
+ elements.gradientControls.style.display = state.colorType === 'gradient' || state.colorType === 'animated' ? 'block' : 'none';
1028
+ }
1029
+
1030
+ // Update code preview
1031
+ function updateCodePreview() {
1032
+ let code = '';
1033
+
1034
+ if (state.exportFormat === 'code') {
1035
+ if (state.framework === 'react') {
1036
+ code = `import React from 'react';\n\n`;
1037
+ code += `const AnimatedBeam = () => {\n`;
1038
+ code += ` return (\n`;
1039
+ code += ` <div className="beam-container">\n`;
1040
+ code += ` <svg width="100%" height="100%">\n`;
1041
+ code += ` <path d="${elements.beamPath.getAttribute('d')}" stroke="url(#beamGradient)" fill="none" stroke-width="${state.width}" stroke-opacity="${state.opacity / 100}" />\n`;
1042
+ code += ` <defs>\n`;
1043
+ code += ` <linearGradient id="beamGradient" x1="0%" y1="0%" x2="100%" y2="0%">\n`;
1044
+ code += ` <stop offset="0%" stop-color="${state.color}" />\n`;
1045
+ code += ` <stop offset="100%" stop-color="${state.gradientColor}" />\n`;
1046
+ code += ` </linearGradient>\n`;
1047
+ code += ` </defs>\n`;
1048
+ code += ` </svg>\n`;
1049
+ code += ` </div>\n`;
1050
+ code += ` );\n`;
1051
+ code += `};\n\n`;
1052
+ code += `export default AnimatedBeam;`;
1053
+ } else if (state.framework === 'vue') {
1054
+ code = `<template>\n`;
1055
+ code += ` <div class="beam-container">\n`;
1056
+ code += ` <svg width="100%" height="100%">\n`;
1057
+ code += ` <path d="${elements.beamPath.getAttribute('d')}" stroke="url(#beamGradient)" fill="none" stroke-width="${state.width}" stroke-opacity="${state.opacity / 100}" />\n`;
1058
+ code += ` <defs>\n`;
1059
+ code += ` <linearGradient id="beamGradient" x1="0%" y1="0%" x2="100%" y2="0%">\n`;
1060
+ code += ` <stop offset="0%" stop-color="${state.color}" />\n`;
1061
+ code += ` <stop offset="100%" stop-color="${state.gradientColor}" />\n`;
1062
+ code += ` </linearGradient>\n`;
1063
+ code += ` </defs>\n`;
1064
+ code += ` </svg>\n`;
1065
+ code += ` </div>\n`;
1066
+ code += `</template>\n\n`;
1067
+ code += `<script>\n`;
1068
+ code += `export default {\n`;
1069
+ code += ` name: 'AnimatedBeam'\n`;
1070
+ code += `};\n`;
1071
+ code += `<\/script>`;
1072
+ } else if (state.framework === 'svelte') {
1073
+ code = `<script>\n`;
1074
+ code += ` // Svelte component logic here\n`;
1075
+ code += `<\/script>\n\n`;
1076
+ code += `<div class="beam-container">\n`;
1077
+ code += ` <svg width="100%" height="100%">\n`;
1078
+ code += ` <path d="${elements.beamPath.getAttribute('d')}" stroke="url(#beamGradient)" fill="none" stroke-width="${state.width}" stroke-opacity="${state.opacity / 100}" />\n`;
1079
+ code += ` <defs>\n`;
1080
+ code += ` <linearGradient id="beamGradient" x1="0%" y1="0%" x2="100%" y2="0%">\n`;
1081
+ code += ` <stop offset="0%" stop-color="${state.color}" />\n`;
1082
+ code += ` <stop offset="100%" stop-color="${state.gradientColor}" />\n`;
1083
+ code += ` </linearGradient>\n`;
1084
+ code += ` </defs>\n`;
1085
+ code += ` </svg>\n`;
1086
+ code += `</div>`;
1087
+ } else { // plain JS
1088
+ code = `const beam = document.createElement('div');\n`;
1089
+ code += `beam.className = 'beam-container';\n\n`;
1090
+ code += `const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n`;
1091
+ code += `svg.setAttribute('width', '100%');\n`;
1092
+ code += `svg.setAttribute('height', '100%');\n\n`;
1093
+ code += `const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n`;
1094
+ code += `path.setAttribute('d', '${elements.beamPath.getAttribute('d')}');\n`;
1095
+ code += `path.setAttribute('stroke', 'url(#beamGradient)');\n`;
1096
+ code += `path.setAttribute('fill', 'none');\n`;
1097
+ code += `path.setAttribute('stroke-width', '${state.width}');\n`;
1098
+ code += `path.setAttribute('stroke-opacity', '${state.opacity / 100}');\n\n`;
1099
+ code += `const defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n`;
1100
+ code += `const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');\n`;
1101
+ code += `gradient.setAttribute('id', 'beamGradient');\n`;
1102
+ code += `gradient.setAttribute('x1', '0%');\n`;
1103
+ code += `gradient.setAttribute('y1', '0%');\n`;
1104
+ code += `gradient.setAttribute('x2', '100%');\n`;
1105
+ code += `gradient.setAttribute('y2', '0%');\n\n`;
1106
+ code += `const stop1 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n`;
1107
+ code += `stop1.setAttribute('offset', '0%');\n`;
1108
+ code += `stop1.setAttribute('stop-color', '${state.color}');\n\n`;
1109
+ code += `const stop2 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n`;
1110
+ code += `stop2.setAttribute('offset', '100%');\n`;
1111
+ code += `stop2.setAttribute('stop-color', '${state.gradientColor}');\n\n`;
1112
+ code += `gradient.appendChild(stop1);\n`;
1113
+ code += `gradient.appendChild(stop2);\n`;
1114
+ code += `defs.appendChild(gradient);\n`;
1115
+ code += `svg.appendChild(path);\n`;
1116
+ code += `svg.appendChild(defs);\n`;
1117
+ code += `beam.appendChild(svg);\n\n`;
1118
+ code += `// Add to your document\n`;
1119
+ code += `document.body.appendChild(beam);`;
1120
+ }
1121
+ } else if (state.exportFormat === 'svg') {
1122
+ code = `<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">\n`;
1123
+ code += ` <path d="${elements.beamPath.getAttribute('d')}" stroke="url(#beamGradient)" fill="none" stroke-width="${state.width}" stroke-opacity="${state.opacity / 100}" />\n`;
1124
+ code += ` <defs>\n`;
1125
+ code += ` <linearGradient id="beamGradient" x1="0%" y1="0%" x2="100%" y2="0%">\n`;
1126
+ code += ` <stop offset="0%" stop-color="${state.color}" />\n`;
1127
+ code += ` <stop offset="100%" stop-color="${state.gradientColor}" />\n`;
1128
+ code += ` </linearGradient>\n`;
1129
+ code += ` </defs>\n`;
1130
+ code += `</svg>`;
1131
+ } else if (state.exportFormat === 'css') {
1132
+ code = `.gradient-beam {\n`;
1133
+ code += ` position: relative;\n`;
1134
+ code += ` height: ${state.width}px;\n`;
1135
+ code += ` background: linear-gradient(90deg, ${state.color} 0%, ${state.gradientColor} 100%);\n`;
1136
+ code += ` opacity: ${state.opacity / 100};\n`;
1137
+ code += ` overflow: hidden;\n`;
1138
+ code += `}\n\n`;
1139
+ code += `.gradient-beam::after {\n`;
1140
+ code += ` content: '';\n`;
1141
+ code += ` position: absolute;\n`;
1142
+ code += ` top: 0;\n`;
1143
+ code += ` left: 0;\n`;
1144
+ code += ` right: 0;\n`;
1145
+ code += ` bottom: 0;\n`;
1146
+ code += ` background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 0) 100%);\n`;
1147
+ code += ` animation: beam-animation ${(2 - (state.animationSpeed / 100) * 1.8).toFixed(2)}s ease-in-out infinite;\n`;
1148
+ code += `}\n\n`;
1149
+ code += `@keyframes beam-animation {\n`;
1150
+ code += ` 0% { transform: translateX(-100%); }\n`;
1151
+ code += ` 100% { transform: translateX(100%); }\n`;
1152
+ code += `}`;
1153
+ }
1154
+
1155
+ elements.codeContent.textContent = code;
1156
+ }
1157
+
1158
+ // Get speed label
1159
+ function getSpeedLabel(speed) {
1160
+ if (speed < 20) return 'Very Slow';
1161
+ if (speed < 40) return 'Slow';
1162
+ if (speed < 60) return 'Medium';
1163
+ if (speed < 80) return 'Fast';
1164
+ return 'Very Fast';
1165
+ }
1166
+
1167
+ // Reset to defaults
1168
+ function resetToDefaults() {
1169
+ state.pathType = 'curved';
1170
+ state.colorType = 'solid';
1171
+ state.color = '#0ea5e9';
1172
+ state.gradientColor = '#ec4899';
1173
+ state.gradientDirection = 90;
1174
+ state.width = 4;
1175
+ state.opacity = 80;
1176
+ state.animationTrigger = 'load';
1177
+ state.animationSpeed = 50;
1178
+ state.effects = {
1179
+ pulsing: false,
1180
+ sparkling: false,
1181
+ glow: true,
1182
+ particles: false
1183
+ };
1184
+ state.direction = 'forward';
1185
+ state.easing = 'linear';
1186
+ state.duration = 2000;
1187
+ state.delay = 0;
1188
+ state.framework = 'react';
1189
+ state.exportFormat = 'code';
1190
+ state.points = {
1191
+ start: { x: 25, y: 40 },
1192
+ end: { x: 75, y: 60 },
1193
+ control1: { x: 40, y: 30 },
1194
+ control2: { x: 60, y: 70 }
1195
+ };
1196
+
1197
+ // Update positions of draggable points
1198
+ elements.startPoint.style.left = `${state.points.start.x}%`;
1199
+ elements.startPoint.style.top = `${state.points.start.y}%`;
1200
+ elements.endPoint.style.left = `${state.points.end.x}%`;
1201
+ elements.endPoint.style.top = `${state.points.end.y}%`;
1202
+ elements.controlPoint1.style.left = `${
1203
+ </html>
prompts.txt ADDED
File without changes