basheer1414 commited on
Commit
f49c1ee
·
verified ·
1 Parent(s): b89a354

Please deduct the code again and there is some error I can see some more text it looks like a code off of the window of the preview - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1189 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Ui Customization Tool
3
- emoji: 🐨
4
- colorFrom: blue
5
- colorTo: green
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: ui-customization-tool
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: blue
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,1189 @@
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">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>UI Customization Tool</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
+ <style>
10
+ /* Custom CSS for elements that can't be done with Tailwind */
11
+ .sidebar {
12
+ transition: all 0.3s ease;
13
+ }
14
+ .sidebar.collapsed {
15
+ transform: translateX(-90%);
16
+ }
17
+ .sidebar.collapsed:hover {
18
+ transform: translateX(0);
19
+ }
20
+ .color-picker {
21
+ width: 30px;
22
+ height: 30px;
23
+ border-radius: 50%;
24
+ cursor: pointer;
25
+ transition: transform 0.2s;
26
+ }
27
+ .color-picker:hover {
28
+ transform: scale(1.2);
29
+ }
30
+ .gradient-preview {
31
+ width: 100%;
32
+ height: 60px;
33
+ border-radius: 8px;
34
+ margin-top: 10px;
35
+ }
36
+ .modal {
37
+ display: none;
38
+ position: fixed;
39
+ z-index: 100;
40
+ left: 0;
41
+ top: 0;
42
+ width: 100%;
43
+ height: 100%;
44
+ background-color: rgba(0,0,0,0.5);
45
+ }
46
+ .modal-content {
47
+ background-color: #f8fafc;
48
+ margin: 5% auto;
49
+ padding: 20px;
50
+ border-radius: 10px;
51
+ width: 80%;
52
+ max-width: 700px;
53
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
54
+ }
55
+ .code-editor {
56
+ width: 100%;
57
+ height: 300px;
58
+ font-family: 'Courier New', monospace;
59
+ padding: 10px;
60
+ border-radius: 5px;
61
+ border: 1px solid #cbd5e1;
62
+ resize: none;
63
+ }
64
+ .canvas-container {
65
+ position: relative;
66
+ border: 2px dashed #94a3b8;
67
+ background-color: #f1f5f9;
68
+ overflow: auto;
69
+ }
70
+ .resize-handle {
71
+ position: absolute;
72
+ width: 10px;
73
+ height: 10px;
74
+ background-color: #3b82f6;
75
+ border-radius: 50%;
76
+ z-index: 10;
77
+ }
78
+ .resize-handle.nw { top: -5px; left: -5px; cursor: nw-resize; }
79
+ .resize-handle.ne { top: -5px; right: -5px; cursor: ne-resize; }
80
+ .resize-handle.sw { bottom: -5px; left: -5px; cursor: sw-resize; }
81
+ .resize-handle.se { bottom: -5px; right: -5px; cursor: se-resize; }
82
+ .toolbar {
83
+ transition: all 0.3s ease;
84
+ }
85
+ .element-controls {
86
+ position: absolute;
87
+ top: -40px;
88
+ left: 0;
89
+ background-color: white;
90
+ padding: 5px;
91
+ border-radius: 5px;
92
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2);
93
+ display: none;
94
+ }
95
+ .canvas-element:hover .element-controls {
96
+ display: block;
97
+ }
98
+ .tab-button {
99
+ transition: all 0.2s ease;
100
+ }
101
+ .tab-button.active {
102
+ background-color: #3b82f6;
103
+ color: white;
104
+ }
105
+ .uiverse-modal {
106
+ max-height: 80vh;
107
+ overflow-y: auto;
108
+ }
109
+ </style>
110
+ </head>
111
+ <body class="bg-gray-100 h-screen flex flex-col">
112
+ <!-- Top Navigation -->
113
+ <header class="bg-white shadow-sm py-2 px-4 flex justify-between items-center">
114
+ <h1 class="text-xl font-bold text-gray-800">UI Customization Tool</h1>
115
+ <div class="flex space-x-2">
116
+ <button id="htmlBtn" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition">
117
+ <i class="fas fa-code mr-2"></i>HTML
118
+ </button>
119
+ <button id="cssBtn" class="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-lg transition">
120
+ <i class="fab fa-css3-alt mr-2"></i>CSS
121
+ </button>
122
+ <button id="saveBtn" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg transition">
123
+ <i class="fas fa-save mr-2"></i>Save
124
+ </button>
125
+ <button id="resetBtn" class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg transition">
126
+ <i class="fas fa-trash-alt mr-2"></i>Reset
127
+ </button>
128
+ </div>
129
+ </header>
130
+
131
+ <div class="flex flex-1 overflow-hidden">
132
+ <!-- Sidebar -->
133
+ <div id="sidebar" class="sidebar w-64 bg-gray-800 text-white h-full flex flex-col transition-all duration-300">
134
+ <div class="p-4 flex justify-between items-center bg-gray-900">
135
+ <h2 class="text-lg font-semibold">Elements</h2>
136
+ <button id="toggleSidebar" class="text-gray-400 hover:text-white">
137
+ <i class="fas fa-chevron-left"></i>
138
+ </button>
139
+ </div>
140
+ <div class="flex-1 overflow-y-auto p-4">
141
+ <div class="mb-6">
142
+ <h3 class="text-sm uppercase font-medium text-gray-400 mb-2">Basic Elements</h3>
143
+ <div class="space-y-2">
144
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="button">
145
+ <i class="fas fa-square mr-2"></i> Button
146
+ </button>
147
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="input">
148
+ <i class="fas fa-font mr-2"></i> Input
149
+ </button>
150
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="card">
151
+ <i class="fas fa-id-card mr-2"></i> Card
152
+ </button>
153
+ </div>
154
+ </div>
155
+ <div class="mb-6">
156
+ <h3 class="text-sm uppercase font-medium text-gray-400 mb-2">Containers</h3>
157
+ <div class="space-y-2">
158
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="div">
159
+ <i class="fas fa-square-full mr-2"></i> Div
160
+ </button>
161
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="section">
162
+ <i class="fas fa-border-all mr-2"></i> Section
163
+ </button>
164
+ </div>
165
+ </div>
166
+ <div class="mb-6">
167
+ <h3 class="text-sm uppercase font-medium text-gray-400 mb-2">Advanced</h3>
168
+ <div class="space-y-2">
169
+ <button id="uiverseBtn" class="w-full text-left px-3 py-2 bg-indigo-700 hover:bg-indigo-600 rounded flex items-center">
170
+ <i class="fas fa-magic mr-2"></i> Uiverse.io
171
+ </button>
172
+ <button class="element-btn w-full text-left px-3 py-2 bg-gray-700 hover:bg-gray-600 rounded flex items-center" data-type="custom">
173
+ <i class="fas fa-code mr-2"></i> Custom HTML
174
+ </button>
175
+ </div>
176
+ </div>
177
+ </div>
178
+ </div>
179
+
180
+ <!-- Main Content -->
181
+ <div class="flex-1 flex flex-col overflow-hidden">
182
+ <!-- Toolbar -->
183
+ <div class="toolbar bg-white border-b p-2 flex items-center space-x-4 overflow-x-auto">
184
+ <div class="flex items-center space-x-2">
185
+ <span class="text-sm font-medium">Position:</span>
186
+ <input type="number" id="posX" placeholder="X" class="w-12 px-2 py-1 border rounded">
187
+ <input type="number" id="posY" placeholder="Y" class="w-12 px-2 py-1 border rounded">
188
+ </div>
189
+ <div class="flex items-center space-x-2">
190
+ <span class="text-sm font-medium">Size:</span>
191
+ <input type="number" id="width" placeholder="W" class="w-12 px-2 py-1 border rounded">
192
+ <input type="number" id="height" placeholder="H" class="w-12 px-2 py-1 border rounded">
193
+ </div>
194
+ <div class="flex items-center space-x-2">
195
+ <span class="text-sm font-medium">Rotation:</span>
196
+ <input type="number" id="rotation" placeholder="deg" class="w-16 px-2 py-1 border rounded">
197
+ </div>
198
+ <div class="flex items-center space-x-2">
199
+ <span class="text-sm font-medium">Color:</span>
200
+ <input type="color" id="colorPicker" class="w-8 h-8 cursor-pointer">
201
+ </div>
202
+ <div class="flex items-center space-x-2">
203
+ <span class="text-sm font-medium">BG:</span>
204
+ <input type="color" id="bgColorPicker" class="w-8 h-8 cursor-pointer">
205
+ </div>
206
+ <div class="flex items-center space-x-2">
207
+ <button id="gradientBtn" class="px-2 py-1 bg-gray-200 rounded text-sm">Gradient</button>
208
+ </div>
209
+ <div class="flex items-center space-x-2">
210
+ <span class="text-sm font-medium">Opacity:</span>
211
+ <input type="range" id="opacity" min="0" max="100" value="100" class="w-20">
212
+ </div>
213
+ <div class="flex items-center space-x-2">
214
+ <span class="text-sm font-medium">Z-index:</span>
215
+ <input type="number" id="zIndex" value="1" class="w-12 px-2 py-1 border rounded">
216
+ </div>
217
+ <div class="flex items-center space-x-2">
218
+ <button id="deleteBtn" class="px-2 py-1 bg-red-500 text-white rounded text-sm">
219
+ <i class="fas fa-trash-alt"></i>
220
+ </button>
221
+ </div>
222
+ <div class="flex items-center space-x-2">
223
+ <button id="duplicateBtn" class="px-2 py-1 bg-blue-500 text-white rounded text-sm">
224
+ <i class="fas fa-copy"></i>
225
+ </button>
226
+ </div>
227
+ <div class="flex items-center space-x-2">
228
+ <button id="newWindowBtn" class="px-2 py-1 bg-green-500 text-white rounded text-sm">
229
+ <i class="fas fa-plus"></i> New Window
230
+ </button>
231
+ </div>
232
+ </div>
233
+
234
+ <!-- Canvas -->
235
+ <div id="canvasContainer" class="canvas-container flex-1 m-4 bg-white relative overflow-auto">
236
+ <div id="canvas" class="relative w-full h-full min-h-[500px]">
237
+ <!-- Elements will be added here -->
238
+ </div>
239
+ </div>
240
+ </div>
241
+ </div>
242
+
243
+ <!-- HTML Modal -->
244
+ <div id="htmlModal" class="modal">
245
+ <div class="modal-content">
246
+ <div class="flex justify-between items-center mb-4">
247
+ <h2 class="text-xl font-bold">HTML Editor</h2>
248
+ <button id="closeHtmlModal" class="text-gray-500 hover:text-gray-700">
249
+ <i class="fas fa-times"></i>
250
+ </button>
251
+ </div>
252
+ <textarea id="htmlEditor" class="code-editor" placeholder="Paste your HTML code here..."></textarea>
253
+ <div class="flex justify-end mt-4 space-x-2">
254
+ <button id="cancelHtmlBtn" class="px-4 py-2 bg-gray-300 hover:bg-gray-400 rounded">Cancel</button>
255
+ <button id="applyHtmlBtn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded">Apply</button>
256
+ </div>
257
+ </div>
258
+ </div>
259
+
260
+ <!-- CSS Modal -->
261
+ <div id="cssModal" class="modal">
262
+ <div class="modal-content">
263
+ <div class="flex justify-between items-center mb-4">
264
+ <h2 class="text-xl font-bold">CSS Editor</h2>
265
+ <button id="closeCssModal" class="text-gray-500 hover:text-gray-700">
266
+ <i class="fas fa-times"></i>
267
+ </button>
268
+ </div>
269
+ <textarea id="cssEditor" class="code-editor" placeholder="Paste your CSS code here..."></textarea>
270
+ <div class="flex justify-end mt-4 space-x-2">
271
+ <button id="cancelCssBtn" class="px-4 py-2 bg-gray-300 hover:bg-gray-400 rounded">Cancel</button>
272
+ <button id="applyCssBtn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded">Apply</button>
273
+ </div>
274
+ </div>
275
+ </div>
276
+
277
+ <!-- Gradient Modal -->
278
+ <div id="gradientModal" class="modal">
279
+ <div class="modal-content">
280
+ <div class="flex justify-between items-center mb-4">
281
+ <h2 class="text-xl font-bold">Gradient Editor</h2>
282
+ <button id="closeGradientModal" class="text-gray-500 hover:text-gray-700">
283
+ <i class="fas fa-times"></i>
284
+ </button>
285
+ </div>
286
+ <div class="grid grid-cols-2 gap-4">
287
+ <div>
288
+ <label class="block text-sm font-medium mb-1">Gradient Type</label>
289
+ <select id="gradientType" class="w-full p-2 border rounded">
290
+ <option value="linear">Linear</option>
291
+ <option value="radial">Radial</option>
292
+ </select>
293
+ </div>
294
+ <div id="linearOptions">
295
+ <label class="block text-sm font-medium mb-1">Direction</label>
296
+ <select id="gradientDirection" class="w-full p-2 border rounded">
297
+ <option value="to right">Left to Right</option>
298
+ <option value="to bottom">Top to Bottom</option>
299
+ <option value="to bottom right">Diagonal</option>
300
+ <option value="135deg">135°</option>
301
+ </select>
302
+ </div>
303
+ </div>
304
+ <div class="mt-4">
305
+ <label class="block text-sm font-medium mb-2">Color Stops</label>
306
+ <div id="colorStops" class="space-y-2">
307
+ <div class="flex items-center space-x-2">
308
+ <input type="color" value="#3b82f6" class="color-picker">
309
+ <input type="range" min="0" max="100" value="0" class="flex-1">
310
+ <span>0%</span>
311
+ <button class="remove-stop px-2 py-1 bg-red-500 text-white rounded text-sm">
312
+ <i class="fas fa-times"></i>
313
+ </button>
314
+ </div>
315
+ <div class="flex items-center space-x-2">
316
+ <input type="color" value="#8b5cf6" class="color-picker">
317
+ <input type="range" min="0" max="100" value="100" class="flex-1">
318
+ <span>100%</span>
319
+ <button class="remove-stop px-2 py-1 bg-red-500 text-white rounded text-sm">
320
+ <i class="fas fa-times"></i>
321
+ </button>
322
+ </div>
323
+ </div>
324
+ <button id="addStopBtn" class="mt-2 px-3 py-1 bg-gray-200 hover:bg-gray-300 rounded text-sm">
325
+ <i class="fas fa-plus mr-1"></i> Add Color Stop
326
+ </button>
327
+ </div>
328
+ <div class="mt-4">
329
+ <label class="block text-sm font-medium mb-1">Preview</label>
330
+ <div id="gradientPreview" class="gradient-preview" style="background: linear-gradient(to right, #3b82f6, #8b5cf6);"></div>
331
+ </div>
332
+ <div class="flex justify-end mt-4 space-x-2">
333
+ <button id="cancelGradientBtn" class="px-4 py-2 bg-gray-300 hover:bg-gray-400 rounded">Cancel</button>
334
+ <button id="applyGradientBtn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded">Apply</button>
335
+ </div>
336
+ </div>
337
+ </div>
338
+
339
+ <!-- Uiverse Modal -->
340
+ <div id="uiverseModal" class="modal">
341
+ <div class="modal-content uiverse-modal">
342
+ <div class="flex justify-between items-center mb-4">
343
+ <h2 class="text-xl font-bold">Uiverse Elements</h2>
344
+ <button id="closeUiverseModal" class="text-gray-500 hover:text-gray-700">
345
+ <i class="fas fa-times"></i>
346
+ </button>
347
+ </div>
348
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
349
+ <!-- Sample Uiverse elements - in a real app these would be fetched from the API -->
350
+ <div class="uiverse-element border rounded p-4">
351
+ <h3 class="font-medium mb-2">Bitter Parrot Button</h3>
352
+ <div class="mb-3">
353
+ <button class="px-4 py-2 bg-gradient-to-r from-purple-500 to-pink-500 text-white rounded-full shadow-lg hover:shadow-xl transition duration-300">
354
+ Hover me
355
+ </button>
356
+ </div>
357
+ <div class="flex justify-between">
358
+ <button class="copy-code px-2 py-1 bg-blue-500 text-white rounded text-sm">
359
+ <i class="fas fa-copy mr-1"></i> Copy
360
+ </button>
361
+ <button class="add-to-canvas px-2 py-1 bg-green-500 text-white rounded text-sm">
362
+ <i class="fas fa-plus mr-1"></i> Add
363
+ </button>
364
+ </div>
365
+ </div>
366
+ <div class="uiverse-element border rounded p-4">
367
+ <h3 class="font-medium mb-2">Cool Input</h3>
368
+ <div class="mb-3">
369
+ <div class="relative">
370
+ <input type="text" class="w-full px-4 py-2 border-b-2 border-gray-300 focus:border-blue-500 outline-none transition" placeholder="Type something...">
371
+ </div>
372
+ </div>
373
+ <div class="flex justify-between">
374
+ <button class="copy-code px-2 py-1 bg-blue-500 text-white rounded text-sm">
375
+ <i class="fas fa-copy mr-1"></i> Copy
376
+ </button>
377
+ <button class="add-to-canvas px-2 py-1 bg-green-500 text-white rounded text-sm">
378
+ <i class="fas fa-plus mr-1"></i> Add
379
+ </button>
380
+ </div>
381
+ </div>
382
+ <div class="uiverse-element border rounded p-4">
383
+ <h3 class="font-medium mb-2">Animated Card</h3>
384
+ <div class="mb-3">
385
+ <div class="w-full max-w-sm bg-white border border-gray-200 rounded-lg shadow hover:scale-105 transition duration-300 p-4">
386
+ <h4 class="text-lg font-semibold">Card Title</h4>
387
+ <p class="text-gray-600">Hover to see animation</p>
388
+ </div>
389
+ </div>
390
+ <div class="flex justify-between">
391
+ <button class="copy-code px-2 py-1 bg-blue-500 text-white rounded text-sm">
392
+ <i class="fas fa-copy mr-1"></i> Copy
393
+ </button>
394
+ <button class="add-to-canvas px-2 py-1 bg-green-500 text-white rounded text-sm">
395
+ <i class="fas fa-plus mr-1"></i> Add
396
+ </button>
397
+ </div>
398
+ </div>
399
+ </div>
400
+ <div class="flex justify-center mt-6">
401
+ <button class="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded">
402
+ Load More
403
+ </button>
404
+ </div>
405
+ </div>
406
+ </div>
407
+
408
+ <!-- Custom Element Modal -->
409
+ <div id="customElementModal" class="modal">
410
+ <div class="modal-content">
411
+ <div class="flex justify-between items-center mb-4">
412
+ <h2 class="text-xl font-bold">Custom Element</h2>
413
+ <button id="closeCustomModal" class="text-gray-500 hover:text-gray-700">
414
+ <i class="fas fa-times"></i>
415
+ </button>
416
+ </div>
417
+ <textarea id="customElementEditor" class="code-editor" placeholder="Enter your custom HTML here..."></textarea>
418
+ <div class="flex justify-end mt-4 space-x-2">
419
+ <button id="cancelCustomBtn" class="px-4 py-2 bg-gray-300 hover:bg-gray-400 rounded">Cancel</button>
420
+ <button id="applyCustomBtn" class="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded">Add to Canvas</button>
421
+ </div>
422
+ </div>
423
+ </div>
424
+
425
+ <script>
426
+ // DOM Elements
427
+ const htmlBtn = document.getElementById('htmlBtn');
428
+ const cssBtn = document.getElementById('cssBtn');
429
+ const saveBtn = document.getElementById('saveBtn');
430
+ const resetBtn = document.getElementById('resetBtn');
431
+ const htmlModal = document.getElementById('htmlModal');
432
+ const cssModal = document.getElementById('cssModal');
433
+ const gradientModal = document.getElementById('gradientModal');
434
+ const uiverseModal = document.getElementById('uiverseModal');
435
+ const customElementModal = document.getElementById('customElementModal');
436
+ const closeHtmlModal = document.getElementById('closeHtmlModal');
437
+ const closeCssModal = document.getElementById('closeCssModal');
438
+ const closeGradientModal = document.getElementById('closeGradientModal');
439
+ const closeUiverseModal = document.getElementById('closeUiverseModal');
440
+ const closeCustomModal = document.getElementById('closeCustomModal');
441
+ const cancelHtmlBtn = document.getElementById('cancelHtmlBtn');
442
+ const cancelCssBtn = document.getElementById('cancelCssBtn');
443
+ const cancelGradientBtn = document.getElementById('cancelGradientBtn');
444
+ const cancelCustomBtn = document.getElementById('cancelCustomBtn');
445
+ const applyHtmlBtn = document.getElementById('applyHtmlBtn');
446
+ const applyCssBtn = document.getElementById('applyCssBtn');
447
+ const applyGradientBtn = document.getElementById('applyGradientBtn');
448
+ const applyCustomBtn = document.getElementById('applyCustomBtn');
449
+ const htmlEditor = document.getElementById('htmlEditor');
450
+ const cssEditor = document.getElementById('cssEditor');
451
+ const customElementEditor = document.getElementById('customElementEditor');
452
+ const canvas = document.getElementById('canvas');
453
+ const gradientBtn = document.getElementById('gradientBtn');
454
+ const toggleSidebar = document.getElementById('toggleSidebar');
455
+ const sidebar = document.getElementById('sidebar');
456
+ const elementBtns = document.querySelectorAll('.element-btn');
457
+ const uiverseBtn = document.getElementById('uiverseBtn');
458
+ const deleteBtn = document.getElementById('deleteBtn');
459
+ const duplicateBtn = document.getElementById('duplicateBtn');
460
+ const newWindowBtn = document.getElementById('newWindowBtn');
461
+ const posX = document.getElementById('posX');
462
+ const posY = document.getElementById('posY');
463
+ const width = document.getElementById('width');
464
+ const height = document.getElementById('height');
465
+ const rotation = document.getElementById('rotation');
466
+ const colorPicker = document.getElementById('colorPicker');
467
+ const bgColorPicker = document.getElementById('bgColorPicker');
468
+ const opacity = document.getElementById('opacity');
469
+ const zIndex = document.getElementById('zIndex');
470
+ const gradientType = document.getElementById('gradientType');
471
+ const gradientDirection = document.getElementById('gradientDirection');
472
+ const colorStops = document.getElementById('colorStops');
473
+ const addStopBtn = document.getElementById('addStopBtn');
474
+ const gradientPreview = document.getElementById('gradientPreview');
475
+
476
+ // State
477
+ let selectedElement = null;
478
+ let isDragging = false;
479
+ let isResizing = false;
480
+ let resizeHandle = null;
481
+ let startX, startY, startWidth, startHeight, startLeft, startTop;
482
+
483
+ // Initialize
484
+ function init() {
485
+ // Set default color picker values
486
+ colorPicker.value = '#000000';
487
+ bgColorPicker.value = '#ffffff';
488
+
489
+ // Add event listeners
490
+ setupEventListeners();
491
+
492
+ // Load saved data if available
493
+ loadSavedData();
494
+ }
495
+
496
+ // Set up all event listeners
497
+ function setupEventListeners() {
498
+ // Modal buttons
499
+ htmlBtn.addEventListener('click', () => htmlModal.style.display = 'block');
500
+ cssBtn.addEventListener('click', () => cssModal.style.display = 'block');
501
+ saveBtn.addEventListener('click', saveDesign);
502
+ resetBtn.addEventListener('click', resetCanvas);
503
+
504
+ // Close modals
505
+ closeHtmlModal.addEventListener('click', () => htmlModal.style.display = 'none');
506
+ closeCssModal.addEventListener('click', () => cssModal.style.display = 'none');
507
+ closeGradientModal.addEventListener('click', () => gradientModal.style.display = 'none');
508
+ closeUiverseModal.addEventListener('click', () => uiverseModal.style.display = 'none');
509
+ closeCustomModal.addEventListener('click', () => customElementModal.style.display = 'none');
510
+
511
+ // Cancel buttons
512
+ cancelHtmlBtn.addEventListener('click', () => htmlModal.style.display = 'none');
513
+ cancelCssBtn.addEventListener('click', () => cssModal.style.display = 'none');
514
+ cancelGradientBtn.addEventListener('click', () => gradientModal.style.display = 'none');
515
+ cancelCustomBtn.addEventListener('click', () => customElementModal.style.display = 'none');
516
+
517
+ // Apply buttons
518
+ applyHtmlBtn.addEventListener('click', applyHtml);
519
+ applyCssBtn.addEventListener('click', applyCss);
520
+ applyGradientBtn.addEventListener('click', applyGradient);
521
+ applyCustomBtn.addEventListener('click', addCustomElement);
522
+
523
+ // Gradient editor
524
+ gradientBtn.addEventListener('click', () => gradientModal.style.display = 'block');
525
+ gradientType.addEventListener('change', updateGradientUI);
526
+ gradientDirection.addEventListener('change', updateGradientPreview);
527
+
528
+ // Color stops
529
+ addStopBtn.addEventListener('click', addColorStop);
530
+ colorStops.addEventListener('click', (e) => {
531
+ if (e.target.classList.contains('remove-stop')) {
532
+ if (colorStops.children.length > 2) {
533
+ e.target.parentElement.remove();
534
+ updateGradientPreview();
535
+ }
536
+ } else if (e.target.classList.contains('color-picker')) {
537
+ e.target.addEventListener('change', updateGradientPreview);
538
+ } else if (e.target.type === 'range') {
539
+ e.target.addEventListener('input', () => {
540
+ e.target.nextElementSibling.textContent = e.target.value + '%';
541
+ updateGradientPreview();
542
+ });
543
+ }
544
+ });
545
+
546
+ // Sidebar
547
+ toggleSidebar.addEventListener('click', toggleSidebarCollapse);
548
+
549
+ // Element buttons
550
+ elementBtns.forEach(btn => {
551
+ btn.addEventListener('click', () => {
552
+ const type = btn.dataset.type;
553
+ if (type === 'custom') {
554
+ customElementModal.style.display = 'block';
555
+ customElementEditor.value = '';
556
+ } else {
557
+ addElementToCanvas(type);
558
+ }
559
+ });
560
+ });
561
+
562
+ // Uiverse button
563
+ uiverseBtn.addEventListener('click', () => uiverseModal.style.display = 'block');
564
+
565
+ // Uiverse modal interactions
566
+ document.querySelectorAll('.add-to-canvas').forEach(btn => {
567
+ btn.addEventListener('click', () => {
568
+ const element = btn.closest('.uiverse-element');
569
+ const preview = element.querySelector('button, input, div');
570
+ if (preview) {
571
+ const clone = preview.cloneNode(true);
572
+ addElementToCanvas(clone);
573
+ uiverseModal.style.display = 'none';
574
+ }
575
+ });
576
+ });
577
+
578
+ // Canvas interactions
579
+ canvas.addEventListener('mousedown', startDrag);
580
+ document.addEventListener('mousemove', handleDrag);
581
+ document.addEventListener('mouseup', stopDrag);
582
+
583
+ // Toolbar controls
584
+ posX.addEventListener('change', updateElementPosition);
585
+ posY.addEventListener('change', updateElementPosition);
586
+ width.addEventListener('change', updateElementSize);
587
+ height.addEventListener('change', updateElementSize);
588
+ rotation.addEventListener('change', updateElementRotation);
589
+ colorPicker.addEventListener('change', updateElementColor);
590
+ bgColorPicker.addEventListener('change', updateElementBackground);
591
+ opacity.addEventListener('input', updateElementOpacity);
592
+ zIndex.addEventListener('change', updateElementZIndex);
593
+ deleteBtn.addEventListener('click', deleteSelectedElement);
594
+ duplicateBtn.addEventListener('click', duplicateSelectedElement);
595
+ newWindowBtn.addEventListener('click', addNewWindow);
596
+ }
597
+
598
+ // Toggle sidebar collapse
599
+ function toggleSidebarCollapse() {
600
+ sidebar.classList.toggle('collapsed');
601
+ const icon = toggleSidebar.querySelector('i');
602
+ if (sidebar.classList.contains('collapsed')) {
603
+ icon.classList.remove('fa-chevron-left');
604
+ icon.classList.add('fa-chevron-right');
605
+ } else {
606
+ icon.classList.remove('fa-chevron-right');
607
+ icon.classList.add('fa-chevron-left');
608
+ }
609
+ }
610
+
611
+ // Add element to canvas
612
+ function addElementToCanvas(type, html = null) {
613
+ let element;
614
+
615
+ if (html) {
616
+ // Create a temporary div to parse the HTML
617
+ const tempDiv = document.createElement('div');
618
+ tempDiv.innerHTML = html;
619
+ element = tempDiv.firstChild;
620
+ } else {
621
+ // Create standard elements based on type
622
+ switch (type) {
623
+ case 'button':
624
+ element = document.createElement('button');
625
+ element.textContent = 'Button';
626
+ element.className = 'px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition';
627
+ break;
628
+ case 'input':
629
+ element = document.createElement('input');
630
+ element.type = 'text';
631
+ element.placeholder = 'Type something...';
632
+ element.className = 'px-3 py-2 border rounded';
633
+ break;
634
+ case 'card':
635
+ element = document.createElement('div');
636
+ element.className = 'bg-white rounded-lg shadow-md p-4 w-64';
637
+ element.innerHTML = `
638
+ <h3 class="text-lg font-semibold mb-2">Card Title</h3>
639
+ <p class="text-gray-600">This is a sample card element.</p>
640
+ `;
641
+ break;
642
+ case 'div':
643
+ element = document.createElement('div');
644
+ element.className = 'bg-gray-200 border border-gray-300 p-4';
645
+ element.textContent = 'Div Container';
646
+ break;
647
+ case 'section':
648
+ element = document.createElement('section');
649
+ element.className = 'bg-white border border-gray-300 p-4';
650
+ element.textContent = 'Section Container';
651
+ break;
652
+ default:
653
+ element = document.createElement('div');
654
+ element.textContent = 'New Element';
655
+ }
656
+ }
657
+
658
+ // Set default styles for positioning
659
+ element.className += ' absolute cursor-move canvas-element';
660
+ element.style.left = '50px';
661
+ element.style.top = '50px';
662
+ element.style.width = 'auto';
663
+ element.style.minWidth = '100px';
664
+ element.style.minHeight = '40px';
665
+
666
+ // Add resize handles
667
+ addResizeHandles(element);
668
+
669
+ // Add element to canvas
670
+ canvas.appendChild(element);
671
+
672
+ // Select the new element
673
+ selectElement(element);
674
+ }
675
+
676
+ // Add custom element from modal
677
+ function addCustomElement() {
678
+ const html = customElementEditor.value.trim();
679
+ if (html) {
680
+ addElementToCanvas('custom', html);
681
+ customElementModal.style.display = 'none';
682
+ }
683
+ }
684
+
685
+ // Add resize handles to an element
686
+ function addResizeHandles(element) {
687
+ const positions = ['nw', 'ne', 'sw', 'se'];
688
+
689
+ positions.forEach(pos => {
690
+ const handle = document.createElement('div');
691
+ handle.className = `resize-handle ${pos}`;
692
+ handle.dataset.position = pos;
693
+ element.appendChild(handle);
694
+
695
+ // Add event listeners for resizing
696
+ handle.addEventListener('mousedown', (e) => {
697
+ e.stopPropagation();
698
+ isResizing = true;
699
+ resizeHandle = pos;
700
+ selectedElement = element;
701
+
702
+ // Store initial dimensions and position
703
+ startWidth = parseInt(getComputedStyle(element).width);
704
+ startHeight = parseInt(getComputedStyle(element).height);
705
+ startLeft = parseInt(getComputedStyle(element).left);
706
+ startTop = parseInt(getComputedStyle(element).top);
707
+
708
+ // Update toolbar inputs
709
+ updateToolbarWithElementData(element);
710
+ });
711
+ });
712
+ }
713
+
714
+ // Start dragging an element
715
+ function startDrag(e) {
716
+ if (e.target.classList.contains('resize-handle')) {
717
+ return; // Let the resize handle handle this
718
+ }
719
+
720
+ const element = e.target.closest('.canvas-element');
721
+ if (element) {
722
+ e.preventDefault();
723
+ isDragging = true;
724
+ selectedElement = element;
725
+
726
+ // Store initial position
727
+ startX = e.clientX;
728
+ startY = e.clientY;
729
+ startLeft = parseInt(getComputedStyle(element).left);
730
+ startTop = parseInt(getComputedStyle(element).top);
731
+
732
+ // Update toolbar inputs
733
+ updateToolbarWithElementData(element);
734
+ }
735
+ }
736
+
737
+ // Handle dragging
738
+ function handleDrag(e) {
739
+ if (isDragging && selectedElement) {
740
+ const dx = e.clientX - startX;
741
+ const dy = e.clientY - startY;
742
+
743
+ selectedElement.style.left = `${startLeft + dx}px`;
744
+ selectedElement.style.top = `${startTop + dy}px`;
745
+
746
+ // Update position inputs
747
+ posX.value = startLeft + dx;
748
+ posY.value = startTop + dy;
749
+ } else if (isResizing && selectedElement) {
750
+ const dx = e.clientX - startX;
751
+ const dy = e.clientY - startY;
752
+
753
+ let newWidth = startWidth;
754
+ let newHeight = startHeight;
755
+ let newLeft = startLeft;
756
+ let newTop = startTop;
757
+
758
+ switch (resizeHandle) {
759
+ case 'nw':
760
+ newWidth = startWidth - dx;
761
+ newHeight = startHeight - dy;
762
+ newLeft = startLeft + dx;
763
+ newTop = startTop + dy;
764
+ break;
765
+ case 'ne':
766
+ newWidth = startWidth + dx;
767
+ newHeight = startHeight - dy;
768
+ newTop = startTop + dy;
769
+ break;
770
+ case 'sw':
771
+ newWidth = startWidth - dx;
772
+ newHeight = startHeight + dy;
773
+ newLeft = startLeft + dx;
774
+ break;
775
+ case 'se':
776
+ newWidth = startWidth + dx;
777
+ newHeight = startHeight + dy;
778
+ break;
779
+ }
780
+
781
+ // Apply minimum dimensions
782
+ newWidth = Math.max(newWidth, 30);
783
+ newHeight = Math.max(newHeight, 30);
784
+
785
+ selectedElement.style.width = `${newWidth}px`;
786
+ selectedElement.style.height = `${newHeight}px`;
787
+ if (newLeft !== startLeft) selectedElement.style.left = `${newLeft}px`;
788
+ if (newTop !== startTop) selectedElement.style.top = `${newTop}px`;
789
+
790
+ // Update size inputs
791
+ width.value = newWidth;
792
+ height.value = newHeight;
793
+ if (newLeft !== startLeft) posX.value = newLeft;
794
+ if (newTop !== startTop) posY.value = newTop;
795
+ }
796
+ }
797
+
798
+ // Stop dragging
799
+ function stopDrag() {
800
+ isDragging = false;
801
+ isResizing = false;
802
+ resizeHandle = null;
803
+ }
804
+
805
+ // Select an element
806
+ function selectElement(element) {
807
+ // Remove selection from all elements
808
+ document.querySelectorAll('.canvas-element').forEach(el => {
809
+ el.classList.remove('ring-2', 'ring-blue-500');
810
+ });
811
+
812
+ // Select the new element
813
+ element.classList.add('ring-2', 'ring-blue-500');
814
+ selectedElement = element;
815
+
816
+ // Update toolbar with element data
817
+ updateToolbarWithElementData(element);
818
+ }
819
+
820
+ // Update toolbar inputs with element data
821
+ function updateToolbarWithElementData(element) {
822
+ const style = getComputedStyle(element);
823
+
824
+ // Position
825
+ posX.value = parseInt(style.left) || 0;
826
+ posY.value = parseInt(style.top) || 0;
827
+
828
+ // Size
829
+ width.value = parseInt(style.width) || 0;
830
+ height.value = parseInt(style.height) || 0;
831
+
832
+ // Rotation
833
+ const transform = style.transform;
834
+ if (transform && transform !== 'none') {
835
+ const values = transform.match(/matrix\((.+)\)/)[1].split(', ');
836
+ const a = parseFloat(values[0]);
837
+ const b = parseFloat(values[1]);
838
+ const angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
839
+ rotation.value = angle;
840
+ } else {
841
+ rotation.value = 0;
842
+ }
843
+
844
+ // Color
845
+ colorPicker.value = rgbToHex(style.color);
846
+
847
+ // Background color
848
+ if (style.background && style.background !== 'none' && !style.background.includes('gradient')) {
849
+ bgColorPicker.value = rgbToHex(style.backgroundColor);
850
+ }
851
+
852
+ // Opacity
853
+ opacity.value = Math.round(parseFloat(style.opacity) * 100);
854
+
855
+ // Z-index
856
+ zIndex.value = style.zIndex;
857
+ }
858
+
859
+ // Convert RGB to HEX
860
+ function rgbToHex(rgb) {
861
+ if (!rgb) return '#000000';
862
+
863
+ // Check if it's already hex
864
+ if (rgb.startsWith('#')) return rgb;
865
+
866
+ // Extract RGB values
867
+ const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
868
+ if (!match) return '#000000';
869
+
870
+ const r = parseInt(match[1]);
871
+ const g = parseInt(match[2]);
872
+ const b = parseInt(match[3]);
873
+
874
+ return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
875
+ }
876
+
877
+ // Update element position from toolbar
878
+ function updateElementPosition() {
879
+ if (selectedElement) {
880
+ selectedElement.style.left = `${posX.value}px`;
881
+ selectedElement.style.top = `${posY.value}px`;
882
+ }
883
+ }
884
+
885
+ // Update element size from toolbar
886
+ function updateElementSize() {
887
+ if (selectedElement) {
888
+ selectedElement.style.width = `${width.value}px`;
889
+ selectedElement.style.height = `${height.value}px`;
890
+ }
891
+ }
892
+
893
+ // Update element rotation from toolbar
894
+ function updateElementRotation() {
895
+ if (selectedElement) {
896
+ selectedElement.style.transform = `rotate(${rotation.value}deg)`;
897
+ }
898
+ }
899
+
900
+ // Update element color from toolbar
901
+ function updateElementColor() {
902
+ if (selectedElement) {
903
+ selectedElement.style.color = colorPicker.value;
904
+ }
905
+ }
906
+
907
+ // Update element background from toolbar
908
+ function updateElementBackground() {
909
+ if (selectedElement) {
910
+ selectedElement.style.background = bgColorPicker.value;
911
+ }
912
+ }
913
+
914
+ // Update element opacity from toolbar
915
+ function updateElementOpacity() {
916
+ if (selectedElement) {
917
+ selectedElement.style.opacity = opacity.value / 100;
918
+ }
919
+ }
920
+
921
+ // Update element z-index from toolbar
922
+ function updateElementZIndex() {
923
+ if (selectedElement) {
924
+ selectedElement.style.zIndex = zIndex.value;
925
+ }
926
+ }
927
+
928
+ // Delete selected element
929
+ function deleteSelectedElement() {
930
+ if (selectedElement) {
931
+ selectedElement.remove();
932
+ selectedElement = null;
933
+ }
934
+ }
935
+
936
+ // Duplicate selected element
937
+ function duplicateSelectedElement() {
938
+ if (selectedElement) {
939
+ const clone = selectedElement.cloneNode(true);
940
+ canvas.appendChild(clone);
941
+
942
+ // Offset the clone slightly
943
+ const left = parseInt(getComputedStyle(selectedElement).left) + 20;
944
+ const top = parseInt(getComputedStyle(selectedElement).top) + 20;
945
+ clone.style.left = `${left}px`;
946
+ clone.style.top = `${top}px`;
947
+
948
+ // Add resize handles to the clone
949
+ addResizeHandles(clone);
950
+
951
+ // Select the new clone
952
+ selectElement(clone);
953
+ }
954
+ }
955
+
956
+ // Add new window
957
+ function addNewWindow() {
958
+ const window = document.createElement('div');
959
+ window.className = 'absolute bg-white border border-gray-300 shadow-lg rounded-lg overflow-hidden canvas-element';
960
+ window.style.width = '400px';
961
+ window.style.height = '300px';
962
+ window.style.left = '100px';
963
+ window.style.top = '100px';
964
+
965
+ // Window header
966
+ const header = document.createElement('div');
967
+ header.className = 'bg-gray-800 text-white p-2 flex justify-between items-center';
968
+ header.innerHTML = `
969
+ <span>New Window</span>
970
+ <button class="close-window text-white hover:text-gray-300">
971
+ <i class="fas fa-times"></i>
972
+ </button>
973
+ `;
974
+
975
+ // Window content
976
+ const content = document.createElement('div');
977
+ content.className = 'p-4 flex-1 overflow-auto';
978
+ content.textContent = 'Window content goes here...';
979
+
980
+ // Add elements to window
981
+ window.appendChild(header);
982
+ window.appendChild(content);
983
+
984
+ // Add to canvas
985
+ canvas.appendChild(window);
986
+
987
+ // Add resize handles
988
+ addResizeHandles(window);
989
+
990
+ // Select the new window
991
+ selectElement(window);
992
+
993
+ // Add close event
994
+ header.querySelector('.close-window').addEventListener('click', () => {
995
+ window.remove();
996
+ });
997
+ }
998
+
999
+ // Apply HTML from modal
1000
+ function applyHtml() {
1001
+ const html = htmlEditor.value.trim();
1002
+ if (html) {
1003
+ // Clear canvas
1004
+ canvas.innerHTML = '';
1005
+
1006
+ // Add the HTML to canvas
1007
+ canvas.innerHTML = html;
1008
+
1009
+ // Add canvas-element class and resize handles to all top-level children
1010
+ Array.from(canvas.children).forEach(child => {
1011
+ child.classList.add('canvas-element');
1012
+ addResizeHandles(child);
1013
+ });
1014
+
1015
+ // Close modal
1016
+ htmlModal.style.display = 'none';
1017
+ }
1018
+ }
1019
+
1020
+ // Apply CSS from modal
1021
+ function applyCss() {
1022
+ const css = cssEditor.value.trim();
1023
+ if (css) {
1024
+ // Create a style element or use existing one
1025
+ let styleElement = document.getElementById('custom-css');
1026
+ if (!styleElement) {
1027
+ styleElement = document.createElement('style');
1028
+ styleElement.id = 'custom-css';
1029
+ document.head.appendChild(styleElement);
1030
+ }
1031
+
1032
+ // Set CSS
1033
+ styleElement.textContent = css;
1034
+
1035
+ // Close modal
1036
+ cssModal.style.display = 'none';
1037
+ }
1038
+ }
1039
+
1040
+ // Add color stop to gradient editor
1041
+ function addColorStop() {
1042
+ const stopDiv = document.createElement('div');
1043
+ stopDiv.className = 'flex items-center space-x-2';
1044
+
1045
+ // Random color for new stop
1046
+ const randomColor = '#' + Math.floor(Math.random()*16777215).toString(16);
1047
+ const position = Math.floor(Math.random() * 50) + 25; // Between 25-75%
1048
+
1049
+ stopDiv.innerHTML = `
1050
+ <input type="color" value="${randomColor}" class="color-picker">
1051
+ <input type="range" min="0" max="100" value="${position}" class="flex-1">
1052
+ <span>${position}%</span>
1053
+ <button class="remove-stop px-2 py-1 bg-red-500 text-white rounded text-sm">
1054
+ <i class="fas fa-times"></i>
1055
+ </button>
1056
+ `;
1057
+
1058
+ colorStops.appendChild(stopDiv);
1059
+
1060
+ // Add event listeners
1061
+ stopDiv.querySelector('.color-picker').addEventListener('change', updateGradientPreview);
1062
+ stopDiv.querySelector('input[type="range"]').addEventListener('input', function() {
1063
+ this.nextElementSibling.textContent = this.value + '%';
1064
+ updateGradientPreview();
1065
+ });
1066
+
1067
+ updateGradientPreview();
1068
+ }
1069
+
1070
+ // Update gradient UI based on type
1071
+ function updateGradientUI() {
1072
+ const type = gradientType.value;
1073
+ if (type === 'linear') {
1074
+ document.getElementById('linearOptions').style.display = 'block';
1075
+ } else {
1076
+ document.getElementById('linearOptions').style.display = 'none';
1077
+ }
1078
+ updateGradientPreview();
1079
+ }
1080
+
1081
+ // Update gradient preview
1082
+ function updateGradientPreview() {
1083
+ const type = gradientType.value;
1084
+ const stops = Array.from(colorStops.querySelectorAll('.flex.items-center')).map(div => {
1085
+ const color = div.querySelector('.color-picker').value;
1086
+ const position = div.querySelector('input[type="range"]').value;
1087
+ return `${color} ${position}%`;
1088
+ }).join(', ');
1089
+
1090
+ if (type === 'linear') {
1091
+ const direction = gradientDirection.value;
1092
+ gradientPreview.style.background = `linear-gradient(${direction}, ${stops})`;
1093
+ } else {
1094
+ gradientPreview.style.background = `radial-gradient(circle, ${stops})`;
1095
+ }
1096
+ }
1097
+
1098
+ // Apply gradient to selected element
1099
+ function applyGradient() {
1100
+ if (selectedElement) {
1101
+ const type = gradientType.value;
1102
+ const stops = Array.from(colorStops.querySelectorAll('.flex.items-center')).map(div => {
1103
+ const color = div.querySelector('.color-picker').value;
1104
+ const position = div.querySelector('input[type="range"]').value;
1105
+ return `${color} ${position}%`;
1106
+ }).join(', ');
1107
+
1108
+ if (type === 'linear') {
1109
+ const direction = gradientDirection.value;
1110
+ selectedElement.style.background = `linear-gradient(${direction}, ${stops})`;
1111
+ } else {
1112
+ selectedElement.style.background = `radial-gradient(circle, ${stops})`;
1113
+ }
1114
+
1115
+ // Close modal
1116
+ gradientModal.style.display = 'none';
1117
+ }
1118
+ }
1119
+
1120
+ // Save design to localStorage
1121
+ function saveDesign() {
1122
+ if (canvas) {
1123
+ const html = canvas.innerHTML;
1124
+ const css = document.getElementById('custom-css')?.textContent || '';
1125
+
1126
+ localStorage.setItem('uiDesigner_html', html);
1127
+ localStorage.setItem('uiDesigner_css', css);
1128
+
1129
+ alert('Design saved successfully!');
1130
+ }
1131
+ }
1132
+
1133
+ // Load saved data from localStorage
1134
+ function loadSavedData() {
1135
+ const savedHtml = localStorage.getItem('uiDesigner_html');
1136
+ const savedCss = localStorage.getItem('uiDesigner_css');
1137
+
1138
+ if (savedHtml) {
1139
+ canvas.innerHTML = savedHtml;
1140
+
1141
+ // Add canvas-element class and resize handles to all top-level children
1142
+ Array.from(canvas.children).forEach(child => {
1143
+ child.classList.add('canvas-element');
1144
+ addResizeHandles(child);
1145
+ });
1146
+ }
1147
+
1148
+ if (savedCss) {
1149
+ let styleElement = document.getElementById('custom-css');
1150
+ if (!styleElement) {
1151
+ styleElement = document.createElement('style');
1152
+ styleElement.id = 'custom-css';
1153
+ document.head.appendChild(styleElement);
1154
+ }
1155
+ styleElement.textContent = savedCss;
1156
+
1157
+ // Update editors
1158
+ cssEditor.value = savedCss;
1159
+ }
1160
+ }
1161
+
1162
+ // Reset canvas
1163
+ function resetCanvas() {
1164
+ if (confirm('Are you sure you want to reset the canvas? This cannot be undone.')) {
1165
+ canvas.innerHTML = '';
1166
+
1167
+ // Remove custom CSS
1168
+ const styleElement = document.getElementById('custom-css');
1169
+ if (styleElement) {
1170
+ styleElement.remove();
1171
+ }
1172
+
1173
+ // Clear localStorage
1174
+ localStorage.removeItem('uiDesigner_html');
1175
+ localStorage.removeItem('uiDesigner_css');
1176
+
1177
+ // Clear editors
1178
+ htmlEditor.value = '';
1179
+ cssEditor.value = '';
1180
+
1181
+ selectedElement = null;
1182
+ }
1183
+ }
1184
+
1185
+ // Initialize the app
1186
+ init();
1187
+ </script>
1188
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=basheer1414/ui-customization-tool" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1189
+ </html>