basheer1414 commited on
Commit
17f6c25
·
verified ·
1 Parent(s): 7f6058c

Now I cannot increase the size from anywhere it's only dragging but that's only from the middle make sure that's working OK why are you doing like this make sure that's working I want see I'm clarifying once again if I wanna increase the size of the element only from the border OK any border so if I are placing on the right border I can extend to right if I'm keeping the upside border I can extend to upside if I am keeping bottom down side bottom right left side corner I can extend aside understood so if my mouse point inside that element we cannot extend the size of it only we can drag - Follow Up Deployment

Browse files
Files changed (1) hide show
  1. index.html +282 -86
index.html CHANGED
@@ -47,129 +47,116 @@
47
  </script>
48
  <script>
49
  $(document).ready(function() {
50
- // Make elements draggable
 
 
 
 
 
 
51
  $('.element-card').draggable({
52
  helper: 'clone',
53
  cursor: 'move',
54
  zIndex: 1000,
55
- revert: 'invalid'
 
 
 
 
56
  });
57
 
58
  // Make canvas a drop zone
59
  $('#dropZone').droppable({
60
  accept: '.element-card',
 
 
61
  drop: function(event, ui) {
62
  const elementType = ui.draggable.data('element');
63
- addElementToCanvas(elementType);
 
 
 
 
64
  }
65
  });
66
 
67
- // Function to add element to canvas
68
- function addElementToCanvas(type) {
69
  const elementId = 'element-' + Date.now();
70
  let elementHTML = '';
71
 
 
 
 
 
 
 
72
  switch(type) {
73
  case 'button':
74
  elementHTML = `
75
  <div class="canvas-element glass-panel p-2 rounded flex items-center justify-center absolute"
76
- style="width: 120px; height: 40px; top: 100px; left: 100px;"
77
  id="${elementId}">
78
  <span class="text-sm">Button</span>
79
- <div class="resizer resizer-nw"></div>
80
- <div class="resizer resizer-ne"></div>
81
- <div class="resizer resizer-sw"></div>
82
- <div class="resizer resizer-se"></div>
83
- <div class="rotator"></div>
84
  </div>
85
  `;
86
  break;
87
  case 'input':
88
  elementHTML = `
89
  <div class="canvas-element glass-panel p-2 rounded absolute"
90
- style="width: 200px; height: 40px; top: 100px; left: 100px;"
91
  id="${elementId}">
92
  <input type="text" placeholder="Input field" class="w-full h-full bg-transparent border border-gray-600 rounded px-2 text-sm">
93
- <div class="resizer resizer-nw"></div>
94
- <div class="resizer resizer-ne"></div>
95
- <div class="resizer resizer-sw"></div>
96
- <div class="resizer resizer-se"></div>
97
- <div class="rotator"></div>
98
  </div>
99
  `;
100
  break;
101
  case 'card':
102
  elementHTML = `
103
  <div class="canvas-element glass-panel p-4 rounded absolute"
104
- style="width: 250px; height: 150px; top: 100px; left: 100px;"
105
  id="${elementId}">
106
  <h3 class="font-semibold mb-2">Card Title</h3>
107
  <p class="text-xs">Card content goes here...</p>
108
- <div class="resizer resizer-nw"></div>
109
- <div class="resizer resizer-ne"></div>
110
- <div class="resizer resizer-sw"></div>
111
- <div class="resizer resizer-se"></div>
112
- <div class="rotator"></div>
113
  </div>
114
  `;
115
  break;
116
  case 'image':
117
  elementHTML = `
118
  <div class="canvas-element glass-panel rounded absolute flex items-center justify-center"
119
- style="width: 200px; height: 150px; top: 100px; left: 100px;"
120
  id="${elementId}">
121
  <i class="fas fa-image text-4xl text-gray-500"></i>
122
- <div class="resizer resizer-nw"></div>
123
- <div class="resizer resizer-ne"></div>
124
- <div class="resizer resizer-sw"></div>
125
- <div class="resizer resizer-se"></div>
126
- <div class="rotator"></div>
127
  </div>
128
  `;
129
  break;
130
  case 'container':
131
  elementHTML = `
132
  <div class="canvas-element glass-panel p-4 rounded absolute"
133
- style="width: 300px; height: 200px; top: 100px; left: 100px;"
134
  id="${elementId}">
135
  <div class="w-full h-full border-2 border-dashed border-gray-600 rounded flex items-center justify-center">
136
  <span class="text-gray-500">Container</span>
137
  </div>
138
- <div class="resizer resizer-nw"></div>
139
- <div class="resizer resizer-ne"></div>
140
- <div class="resizer resizer-sw"></div>
141
- <div class="resizer resizer-se"></div>
142
- <div class="rotator"></div>
143
  </div>
144
  `;
145
  break;
146
  case 'section':
147
  elementHTML = `
148
  <div class="canvas-element glass-panel p-4 rounded absolute"
149
- style="width: 400px; height: 300px; top: 100px; left: 100px;"
150
  id="${elementId}">
151
  <div class="w-full h-full border border-gray-600 rounded flex items-center justify-center">
152
  <span class="text-gray-500">Section</span>
153
  </div>
154
- <div class="resizer resizer-nw"></div>
155
- <div class="resizer resizer-ne"></div>
156
- <div class="resizer resizer-sw"></div>
157
- <div class="resizer resizer-se"></div>
158
- <div class="rotator"></div>
159
  </div>
160
  `;
161
  break;
162
  default:
163
  elementHTML = `
164
  <div class="canvas-element glass-panel p-2 rounded absolute"
165
- style="width: 150px; height: 50px; top: 100px; left: 100px;"
166
  id="${elementId}">
167
  <span class="text-sm">${type.charAt(0).toUpperCase() + type.slice(1)}</span>
168
- <div class="resizer resizer-nw"></div>
169
- <div class="resizer resizer-ne"></div>
170
- <div class="resizer resizer-sw"></div>
171
- <div class="resizer resizer-se"></div>
172
- <div class="rotator"></div>
173
  </div>
174
  `;
175
  }
@@ -179,8 +166,11 @@
179
  // Make the new element selectable
180
  $(`#${elementId}`).click(function(e) {
181
  e.stopPropagation();
182
- $('.canvas-element').removeClass('selected');
183
- $(this).addClass('selected');
 
 
 
184
  });
185
 
186
  // Make the new element draggable
@@ -188,17 +178,28 @@
188
 
189
  // Make the new element resizable and rotatable
190
  makeElementResizableRotatable(`#${elementId}`);
 
 
 
 
 
 
 
191
  }
192
 
193
- // Make canvas elements draggable
194
  function makeElementDraggable(selector) {
195
  $(selector).draggable({
196
- containment: '#dropZone',
197
  cursor: 'move',
198
  handle: ':not(.resizer):not(.rotator)',
199
  start: function() {
200
  $(this).addClass('dragging');
201
  },
 
 
 
 
202
  stop: function() {
203
  $(this).removeClass('dragging');
204
  }
@@ -208,12 +209,28 @@
208
  // Make elements resizable and rotatable
209
  function makeElementResizableRotatable(selector) {
210
  interact(selector)
 
 
 
 
 
 
 
 
 
 
 
 
211
  .resizable({
212
- edges: { left: true, right: true, bottom: true, top: true },
 
 
 
 
 
213
  modifiers: [
214
  interact.modifiers.restrictEdges({
215
- outer: 'parent',
216
- endOnly: true
217
  })
218
  ],
219
  inertia: true
@@ -239,20 +256,89 @@
239
  })
240
  .on('resizeend', function (event) {
241
  event.target.classList.remove('resizing');
 
 
242
  });
243
  }
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  // Select canvas elements
246
  $(document).on('click', '.canvas-element', function(e) {
247
  e.stopPropagation();
248
- $('.canvas-element').removeClass('selected');
249
- $(this).addClass('selected');
 
 
 
 
 
 
 
 
 
 
250
  });
251
 
252
  // Deselect when clicking on canvas
253
  $('#dropZone').click(function(e) {
254
- if (e.target.id === 'dropZone') {
255
  $('.canvas-element').removeClass('selected');
 
256
  }
257
  });
258
 
@@ -261,6 +347,100 @@
261
  makeElementDraggable(this);
262
  makeElementResizableRotatable(this);
263
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  });
265
  </script>
266
  <style>
@@ -335,31 +515,6 @@
335
  background-size: 20px 20px;
336
  }
337
 
338
- .resizer {
339
- position: absolute;
340
- width: 10px;
341
- height: 10px;
342
- background: rgba(0, 212, 255, 0.8);
343
- border-radius: 50%;
344
- z-index: 10;
345
- }
346
-
347
- .resizer-nw { top: -5px; left: -5px; cursor: nw-resize; }
348
- .resizer-ne { top: -5px; right: -5px; cursor: ne-resize; }
349
- .resizer-sw { bottom: -5px; left: -5px; cursor: sw-resize; }
350
- .resizer-se { bottom: -5px; right: -5px; cursor: se-resize; }
351
-
352
- .rotator {
353
- position: absolute;
354
- top: -30px;
355
- left: 50%;
356
- transform: translateX(-50%);
357
- width: 20px;
358
- height: 20px;
359
- background: rgba(0, 212, 255, 0.8);
360
- border-radius: 50%;
361
- cursor: grab;
362
- }
363
 
364
  .canvas-element {
365
  position: absolute;
@@ -371,6 +526,10 @@
371
  box-shadow: 0 0 0 2px #00D4FF, 0 0 15px rgba(0, 212, 255, 0.5);
372
  }
373
 
 
 
 
 
374
  .dragging {
375
  opacity: 0.7;
376
  z-index: 1000;
@@ -380,6 +539,7 @@
380
  position: relative;
381
  width: 100%;
382
  height: 100%;
 
383
  }
384
 
385
  .property-slider::-webkit-slider-thumb {
@@ -448,6 +608,14 @@
448
  color: #00D4FF;
449
  }
450
 
 
 
 
 
 
 
 
 
451
  .layer-item {
452
  transition: all 0.2s ease;
453
  }
@@ -611,17 +779,45 @@
611
 
612
  <!-- Canvas Area -->
613
  <div class="flex-1 overflow-auto relative canvas-grid" id="canvas">
614
- <div class="drop-zone" id="dropZone">
615
  <!-- Canvas is now clean - ready for elements to be added -->
616
  </div>
617
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
618
  </div>
619
 
620
  <!-- Right Customization Panel -->
621
  <div class="w-48 glass-panel flex flex-col border-l border-gray-800">
622
  <div class="p-2 border-b border-gray-800">
623
  <h2 class="text-xs font-semibold">Properties</h2>
624
- <p class="tiny-text text-gray-400">Primary Button selected</p>
625
  </div>
626
 
627
  <div class="flex-1 overflow-y-auto p-2">
@@ -676,12 +872,12 @@
676
  </div>
677
  </div>
678
 
679
- <div class="mb-2">
680
  <h3 class="font-medium tiny-text mb-1">Text</h3>
681
  <div class="space-y-2">
682
  <div>
683
  <label class="tiny-text text-gray-400">Content</label>
684
- <input type="text" value="Primary Button" class="w-full mt-1 tiny-input rounded-md glow-input">
685
  </div>
686
 
687
  <div>
 
47
  </script>
48
  <script>
49
  $(document).ready(function() {
50
+ // Current tool state
51
+ let currentTool = 'select'; // 'select', 'hand', 'text', 'rectangle', 'circle', 'line'
52
+ let isPanning = false;
53
+ let panStart = { x: 0, y: 0 };
54
+ let canvasStart = { x: 0, y: 0 };
55
+
56
+ // Make component cards draggable (clone mode)
57
  $('.element-card').draggable({
58
  helper: 'clone',
59
  cursor: 'move',
60
  zIndex: 1000,
61
+ revert: 'invalid',
62
+ start: function(event, ui) {
63
+ // Improve visual feedback during drag
64
+ ui.helper.addClass('opacity-75');
65
+ }
66
  });
67
 
68
  // Make canvas a drop zone
69
  $('#dropZone').droppable({
70
  accept: '.element-card',
71
+ tolerance: 'pointer',
72
+ activeClass: 'border-2 border-dashed border-accent-blue',
73
  drop: function(event, ui) {
74
  const elementType = ui.draggable.data('element');
75
+ const position = {
76
+ x: event.clientX - event.target.getBoundingClientRect().left,
77
+ y: event.clientY - event.target.getBoundingClientRect().top
78
+ };
79
+ addElementToCanvas(elementType, position);
80
  }
81
  });
82
 
83
+ // Function to add element to canvas with position
84
+ function addElementToCanvas(type, position) {
85
  const elementId = 'element-' + Date.now();
86
  let elementHTML = '';
87
 
88
+ // Position element at drop point
89
+ const adjustedPosition = {
90
+ x: position.x - 50,
91
+ y: position.y - 25
92
+ };
93
+
94
  switch(type) {
95
  case 'button':
96
  elementHTML = `
97
  <div class="canvas-element glass-panel p-2 rounded flex items-center justify-center absolute"
98
+ style="width: 120px; height: 40px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
99
  id="${elementId}">
100
  <span class="text-sm">Button</span>
 
 
 
 
 
101
  </div>
102
  `;
103
  break;
104
  case 'input':
105
  elementHTML = `
106
  <div class="canvas-element glass-panel p-2 rounded absolute"
107
+ style="width: 200px; height: 40px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
108
  id="${elementId}">
109
  <input type="text" placeholder="Input field" class="w-full h-full bg-transparent border border-gray-600 rounded px-2 text-sm">
 
 
 
 
 
110
  </div>
111
  `;
112
  break;
113
  case 'card':
114
  elementHTML = `
115
  <div class="canvas-element glass-panel p-4 rounded absolute"
116
+ style="width: 250px; height: 150px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
117
  id="${elementId}">
118
  <h3 class="font-semibold mb-2">Card Title</h3>
119
  <p class="text-xs">Card content goes here...</p>
 
 
 
 
 
120
  </div>
121
  `;
122
  break;
123
  case 'image':
124
  elementHTML = `
125
  <div class="canvas-element glass-panel rounded absolute flex items-center justify-center"
126
+ style="width: 200px; height: 150px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
127
  id="${elementId}">
128
  <i class="fas fa-image text-4xl text-gray-500"></i>
 
 
 
 
 
129
  </div>
130
  `;
131
  break;
132
  case 'container':
133
  elementHTML = `
134
  <div class="canvas-element glass-panel p-4 rounded absolute"
135
+ style="width: 300px; height: 200px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
136
  id="${elementId}">
137
  <div class="w-full h-full border-2 border-dashed border-gray-600 rounded flex items-center justify-center">
138
  <span class="text-gray-500">Container</span>
139
  </div>
 
 
 
 
 
140
  </div>
141
  `;
142
  break;
143
  case 'section':
144
  elementHTML = `
145
  <div class="canvas-element glass-panel p-4 rounded absolute"
146
+ style="width: 400px; height: 300px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
147
  id="${elementId}">
148
  <div class="w-full h-full border border-gray-600 rounded flex items-center justify-center">
149
  <span class="text-gray-500">Section</span>
150
  </div>
 
 
 
 
 
151
  </div>
152
  `;
153
  break;
154
  default:
155
  elementHTML = `
156
  <div class="canvas-element glass-panel p-2 rounded absolute"
157
+ style="width: 150px; height: 50px; top: ${adjustedPosition.y}px; left: ${adjustedPosition.x}px;"
158
  id="${elementId}">
159
  <span class="text-sm">${type.charAt(0).toUpperCase() + type.slice(1)}</span>
 
 
 
 
 
160
  </div>
161
  `;
162
  }
 
166
  // Make the new element selectable
167
  $(`#${elementId}`).click(function(e) {
168
  e.stopPropagation();
169
+ if (currentTool === 'select') {
170
+ $('.canvas-element').removeClass('selected');
171
+ $(this).addClass('selected');
172
+ updatePropertyPanel($(this));
173
+ }
174
  });
175
 
176
  // Make the new element draggable
 
178
 
179
  // Make the new element resizable and rotatable
180
  makeElementResizableRotatable(`#${elementId}`);
181
+
182
+ // Select the newly added element
183
+ if (currentTool === 'select') {
184
+ $('.canvas-element').removeClass('selected');
185
+ $(`#${elementId}`).addClass('selected');
186
+ updatePropertyPanel($(`#${elementId}`));
187
+ }
188
  }
189
 
190
+ // Make canvas elements draggable with better containment
191
  function makeElementDraggable(selector) {
192
  $(selector).draggable({
193
+ containment: 'parent',
194
  cursor: 'move',
195
  handle: ':not(.resizer):not(.rotator)',
196
  start: function() {
197
  $(this).addClass('dragging');
198
  },
199
+ drag: function(event, ui) {
200
+ // Smooth dragging without visual artifacts
201
+ ui.helper.removeClass('bg-dark-700');
202
+ },
203
  stop: function() {
204
  $(this).removeClass('dragging');
205
  }
 
209
  // Make elements resizable and rotatable
210
  function makeElementResizableRotatable(selector) {
211
  interact(selector)
212
+ .draggable({
213
+ inertia: true,
214
+ modifiers: [
215
+ interact.modifiers.restrictRect({
216
+ restriction: 'parent'
217
+ })
218
+ ],
219
+ autoScroll: true,
220
+ listeners: {
221
+ move: dragMoveListener
222
+ }
223
+ })
224
  .resizable({
225
+ edges: {
226
+ left: '.resize-left',
227
+ right: '.resize-right',
228
+ top: '.resize-top',
229
+ bottom: '.resize-bottom'
230
+ },
231
  modifiers: [
232
  interact.modifiers.restrictEdges({
233
+ outer: 'parent'
 
234
  })
235
  ],
236
  inertia: true
 
256
  })
257
  .on('resizeend', function (event) {
258
  event.target.classList.remove('resizing');
259
+ // Reset resize classes
260
+ event.target.classList.remove('resize-left', 'resize-right', 'resize-top', 'resize-bottom');
261
  });
262
  }
263
 
264
+ // Drag move listener for positioning elements
265
+ function dragMoveListener (event) {
266
+ var target = event.target;
267
+ var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
268
+ var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
269
+
270
+ target.style.transform = 'translate(' + x + 'px,' + y + 'px)';
271
+
272
+ target.setAttribute('data-x', x);
273
+ target.setAttribute('data-y', y);
274
+ }
275
+
276
+ // Update cursor and resize state based on mouse position relative to element edges
277
+ $(document).on('mousemove', '.canvas-element', function(e) {
278
+ const element = $(this);
279
+ const offset = element.offset();
280
+ const width = element.outerWidth();
281
+ const height = element.outerHeight();
282
+ const x = e.pageX - offset.left;
283
+ const y = e.pageY - offset.top;
284
+ const edgeThreshold = 8;
285
+
286
+ // Check if mouse is near any edge
287
+ const nearLeft = x < edgeThreshold;
288
+ const nearRight = x > width - edgeThreshold;
289
+ const nearTop = y < edgeThreshold;
290
+ const nearBottom = y > height - edgeThreshold;
291
+ const nearAnyEdge = nearLeft || nearRight || nearTop || nearBottom;
292
+
293
+ // Set appropriate cursor
294
+ if ((nearLeft && nearTop) || (nearRight && nearBottom)) {
295
+ element.css('cursor', 'nwse-resize');
296
+ } else if ((nearRight && nearTop) || (nearLeft && nearBottom)) {
297
+ element.css('cursor', 'nesw-resize');
298
+ } else if (nearLeft || nearRight) {
299
+ element.css('cursor', 'ew-resize');
300
+ } else if (nearTop || nearBottom) {
301
+ element.css('cursor', 'ns-resize');
302
+ } else {
303
+ element.css('cursor', 'move');
304
+ }
305
+
306
+ // Add resize classes for interact.js
307
+ element.removeClass('resize-left resize-right resize-top resize-bottom');
308
+ if (nearLeft) element.addClass('resize-left');
309
+ if (nearRight) element.addClass('resize-right');
310
+ if (nearTop) element.addClass('resize-top');
311
+ if (nearBottom) element.addClass('resize-bottom');
312
+ });
313
+
314
+ // Reset cursor and resize state when mouse leaves element
315
+ $(document).on('mouseleave', '.canvas-element', function() {
316
+ $(this).css('cursor', 'default')
317
+ .removeClass('resize-left resize-right resize-top resize-bottom');
318
+ });
319
+
320
  // Select canvas elements
321
  $(document).on('click', '.canvas-element', function(e) {
322
  e.stopPropagation();
323
+ if (currentTool === 'select') {
324
+ $('.canvas-element').removeClass('selected');
325
+ $(this).addClass('selected');
326
+ updatePropertyPanel($(this));
327
+ }
328
+ });
329
+
330
+ // Add hover effect for bounding box visualization
331
+ $(document).on('mouseenter', '.canvas-element', function() {
332
+ $(this).addClass('hovered');
333
+ }).on('mouseleave', '.canvas-element', function() {
334
+ $(this).removeClass('hovered');
335
  });
336
 
337
  // Deselect when clicking on canvas
338
  $('#dropZone').click(function(e) {
339
+ if (e.target.id === 'dropZone' && currentTool === 'select') {
340
  $('.canvas-element').removeClass('selected');
341
+ updatePropertyPanel(null);
342
  }
343
  });
344
 
 
347
  makeElementDraggable(this);
348
  makeElementResizableRotatable(this);
349
  });
350
+
351
+ // Tool selection
352
+ $('.tool-btn').click(function() {
353
+ $('.tool-btn').removeClass('bg-dark-700');
354
+ $(this).addClass('bg-dark-700');
355
+ currentTool = $(this).data('tool');
356
+
357
+ // Update cursor based on tool
358
+ updateCanvasCursor();
359
+ });
360
+
361
+ // Update cursor based on current tool
362
+ function updateCanvasCursor() {
363
+ const canvas = $('#canvas');
364
+ canvas.removeClass('cursor-move cursor-crosshair cursor-text');
365
+
366
+ switch(currentTool) {
367
+ case 'hand':
368
+ canvas.addClass('cursor-move');
369
+ break;
370
+ case 'rectangle':
371
+ case 'circle':
372
+ case 'line':
373
+ canvas.addClass('cursor-crosshair');
374
+ break;
375
+ case 'text':
376
+ canvas.addClass('cursor-text');
377
+ break;
378
+ default:
379
+ canvas.css('cursor', 'default');
380
+ }
381
+ }
382
+
383
+ // Spacebar panning functionality
384
+ $(document).keydown(function(e) {
385
+ if (e.keyCode === 32 && !isPanning) { // Spacebar
386
+ e.preventDefault();
387
+ isPanning = true;
388
+ $('#canvas').addClass('cursor-grab');
389
+ }
390
+ });
391
+
392
+ $(document).keyup(function(e) {
393
+ if (e.keyCode === 32 && isPanning) {
394
+ isPanning = false;
395
+ $('#canvas').removeClass('cursor-grab cursor-grabbing');
396
+ }
397
+ });
398
+
399
+ // Panning implementation
400
+ $('#canvas').mousedown(function(e) {
401
+ if (isPanning) {
402
+ e.preventDefault();
403
+ panStart = { x: e.clientX, y: e.clientY };
404
+ canvasStart = {
405
+ x: parseInt($('#dropZone').css('left')) || 0,
406
+ y: parseInt($('#dropZone').css('top')) || 0
407
+ };
408
+ $('#canvas').addClass('cursor-grabbing').removeClass('cursor-grab');
409
+ $(document).on('mousemove.pan', function(e) {
410
+ const dx = e.clientX - panStart.x;
411
+ const dy = e.clientY - panStart.y;
412
+ $('#dropZone').css({
413
+ left: canvasStart.x + dx,
414
+ top: canvasStart.y + dy
415
+ });
416
+ });
417
+ }
418
+ });
419
+
420
+ $(document).mouseup(function(e) {
421
+ if (isPanning) {
422
+ $('#canvas').addClass('cursor-grab').removeClass('cursor-grabbing');
423
+ $(document).off('mousemove.pan');
424
+ }
425
+ });
426
+
427
+ // Update property panel based on selected element
428
+ function updatePropertyPanel(element) {
429
+ if (element) {
430
+ const elementType = element.data('element') || 'element';
431
+ $('#selectedElementName').text(elementType.charAt(0).toUpperCase() + elementType.slice(1) + ' selected');
432
+
433
+ // Show/hide text customization based on element content
434
+ if (element.find('span, h3, p, input').length > 0) {
435
+ $('#textCustomization').show();
436
+ } else {
437
+ $('#textCustomization').hide();
438
+ }
439
+ } else {
440
+ $('#selectedElementName').text('No element selected');
441
+ $('#textCustomization').hide();
442
+ }
443
+ }
444
  });
445
  </script>
446
  <style>
 
515
  background-size: 20px 20px;
516
  }
517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
 
519
  .canvas-element {
520
  position: absolute;
 
526
  box-shadow: 0 0 0 2px #00D4FF, 0 0 15px rgba(0, 212, 255, 0.5);
527
  }
528
 
529
+ .canvas-element.hovered {
530
+ box-shadow: 0 0 0 1px #00D4FF, 0 0 10px rgba(0, 212, 255, 0.3);
531
+ }
532
+
533
  .dragging {
534
  opacity: 0.7;
535
  z-index: 1000;
 
539
  position: relative;
540
  width: 100%;
541
  height: 100%;
542
+ transition: border-color 0.2s ease;
543
  }
544
 
545
  .property-slider::-webkit-slider-thumb {
 
608
  color: #00D4FF;
609
  }
610
 
611
+ .tool-btn {
612
+ transition: all 0.2s ease;
613
+ }
614
+
615
+ .tool-btn:hover {
616
+ background: rgba(100, 100, 150, 0.1);
617
+ }
618
+
619
  .layer-item {
620
  transition: all 0.2s ease;
621
  }
 
779
 
780
  <!-- Canvas Area -->
781
  <div class="flex-1 overflow-auto relative canvas-grid" id="canvas">
782
+ <div class="drop-zone absolute" id="dropZone" style="width: 200%; height: 200%; left: -50%; top: -50%;">
783
  <!-- Canvas is now clean - ready for elements to be added -->
784
  </div>
785
  </div>
786
+
787
+ <!-- Bottom Toolbar -->
788
+ <div class="glass h-10 flex items-center justify-center border-t border-gray-800">
789
+ <div class="flex space-x-1">
790
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center bg-dark-700" data-tool="select" title="Selection Tool (V)">
791
+ <i class="fas fa-mouse-pointer text-xs"></i>
792
+ </button>
793
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="hand" title="Hand Tool (H)">
794
+ <i class="fas fa-hand-paper text-xs"></i>
795
+ </button>
796
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="rectangle" title="Rectangle Tool (R)">
797
+ <i class="fas fa-square text-xs"></i>
798
+ </button>
799
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="circle" title="Ellipse Tool (O)">
800
+ <i class="fas fa-circle text-xs"></i>
801
+ </button>
802
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="line" title="Line Tool (L)">
803
+ <i class="fas fa-minus text-xs"></i>
804
+ </button>
805
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="text" title="Text Tool (T)">
806
+ <i class="fas fa-font text-xs"></i>
807
+ </button>
808
+ <div class="w-px h-6 bg-gray-700 mx-1"></div>
809
+ <button class="tool-btn w-8 h-8 rounded flex items-center justify-center" data-tool="eyedropper" title="Eyedropper Tool (I)">
810
+ <i class="fas fa-eye-dropper text-xs"></i>
811
+ </button>
812
+ </div>
813
+ </div>
814
  </div>
815
 
816
  <!-- Right Customization Panel -->
817
  <div class="w-48 glass-panel flex flex-col border-l border-gray-800">
818
  <div class="p-2 border-b border-gray-800">
819
  <h2 class="text-xs font-semibold">Properties</h2>
820
+ <p class="tiny-text text-gray-400" id="selectedElementName">No element selected</p>
821
  </div>
822
 
823
  <div class="flex-1 overflow-y-auto p-2">
 
872
  </div>
873
  </div>
874
 
875
+ <div class="mb-2" id="textCustomization">
876
  <h3 class="font-medium tiny-text mb-1">Text</h3>
877
  <div class="space-y-2">
878
  <div>
879
  <label class="tiny-text text-gray-400">Content</label>
880
+ <input type="text" value="Primary Button" class="w-full mt-1 tiny-input rounded-md glow-input" id="textContent">
881
  </div>
882
 
883
  <div>