@base44-preview/vite-plugin 0.2.22-pr.37.eb62313 → 0.2.22-pr.38.2655a87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/injections/visual-edit-agent.d.ts +1 -1
  2. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  3. package/dist/injections/visual-edit-agent.js +466 -1
  4. package/dist/injections/visual-edit-agent.js.map +1 -1
  5. package/dist/statics/index.mjs +1 -5
  6. package/dist/statics/index.mjs.map +1 -1
  7. package/package.json +1 -1
  8. package/src/injections/visual-edit-agent.ts +570 -1
  9. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts +0 -25
  10. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts.map +0 -1
  11. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js +0 -95
  12. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js.map +0 -1
  13. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts +0 -4
  14. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts.map +0 -1
  15. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js +0 -4
  16. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js.map +0 -1
  17. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts +0 -9
  18. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts.map +0 -1
  19. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js +0 -26
  20. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js.map +0 -1
  21. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts +0 -10
  22. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts.map +0 -1
  23. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js +0 -60
  24. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js.map +0 -1
  25. package/dist/injections/visual-edit-agent/constants.d.ts +0 -10
  26. package/dist/injections/visual-edit-agent/constants.d.ts.map +0 -1
  27. package/dist/injections/visual-edit-agent/constants.js +0 -10
  28. package/dist/injections/visual-edit-agent/constants.js.map +0 -1
  29. package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts +0 -10
  30. package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts.map +0 -1
  31. package/dist/injections/visual-edit-agent/handlers/click-handlers.js +0 -108
  32. package/dist/injections/visual-edit-agent/handlers/click-handlers.js.map +0 -1
  33. package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts +0 -14
  34. package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts.map +0 -1
  35. package/dist/injections/visual-edit-agent/handlers/hover-handlers.js +0 -64
  36. package/dist/injections/visual-edit-agent/handlers/hover-handlers.js.map +0 -1
  37. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts +0 -14
  38. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts.map +0 -1
  39. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js +0 -109
  40. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js.map +0 -1
  41. package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts +0 -26
  42. package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts.map +0 -1
  43. package/dist/injections/visual-edit-agent/handlers/message-handlers.js +0 -145
  44. package/dist/injections/visual-edit-agent/handlers/message-handlers.js.map +0 -1
  45. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts +0 -7
  46. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts.map +0 -1
  47. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js +0 -58
  48. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js.map +0 -1
  49. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts +0 -11
  50. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts.map +0 -1
  51. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js +0 -32
  52. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js.map +0 -1
  53. package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts +0 -86
  54. package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts.map +0 -1
  55. package/dist/injections/visual-edit-agent/handlers/messages/types.js +0 -28
  56. package/dist/injections/visual-edit-agent/handlers/messages/types.js.map +0 -1
  57. package/dist/injections/visual-edit-agent/index.d.ts +0 -5
  58. package/dist/injections/visual-edit-agent/index.d.ts.map +0 -1
  59. package/dist/injections/visual-edit-agent/index.js +0 -95
  60. package/dist/injections/visual-edit-agent/index.js.map +0 -1
  61. package/dist/injections/visual-edit-agent/state/agent-state.d.ts +0 -17
  62. package/dist/injections/visual-edit-agent/state/agent-state.d.ts.map +0 -1
  63. package/dist/injections/visual-edit-agent/state/agent-state.js +0 -18
  64. package/dist/injections/visual-edit-agent/state/agent-state.js.map +0 -1
  65. package/dist/injections/visual-edit-agent/ui/overlay.d.ts +0 -26
  66. package/dist/injections/visual-edit-agent/ui/overlay.d.ts.map +0 -1
  67. package/dist/injections/visual-edit-agent/ui/overlay.js +0 -104
  68. package/dist/injections/visual-edit-agent/ui/overlay.js.map +0 -1
  69. package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts +0 -14
  70. package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts.map +0 -1
  71. package/dist/injections/visual-edit-agent/utils/dom-utils.js +0 -34
  72. package/dist/injections/visual-edit-agent/utils/dom-utils.js.map +0 -1
  73. package/src/injections/visual-edit-agent/README.md +0 -222
  74. package/src/injections/visual-edit-agent/capabilities/inline-editing/core.ts +0 -120
  75. package/src/injections/visual-edit-agent/capabilities/inline-editing/index.ts +0 -10
  76. package/src/injections/visual-edit-agent/capabilities/inline-editing/styles.ts +0 -26
  77. package/src/injections/visual-edit-agent/capabilities/inline-editing/validation.ts +0 -67
  78. package/src/injections/visual-edit-agent/constants.ts +0 -9
  79. package/src/injections/visual-edit-agent/handlers/click-handlers.ts +0 -135
  80. package/src/injections/visual-edit-agent/handlers/hover-handlers.ts +0 -78
  81. package/src/injections/visual-edit-agent/handlers/inline-edit-handlers.ts +0 -141
  82. package/src/injections/visual-edit-agent/handlers/message-handlers.ts +0 -191
  83. package/src/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.ts +0 -70
  84. package/src/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.ts +0 -40
  85. package/src/injections/visual-edit-agent/handlers/messages/types.ts +0 -112
  86. package/src/injections/visual-edit-agent/index.ts +0 -108
  87. package/src/injections/visual-edit-agent/state/agent-state.ts +0 -31
  88. package/src/injections/visual-edit-agent/ui/overlay.ts +0 -126
  89. package/src/injections/visual-edit-agent/utils/dom-utils.ts +0 -39
@@ -1 +1,570 @@
1
- export { setupVisualEditAgent } from "./visual-edit-agent/index.js";
1
+ import { findElementsById, updateElementClasses } from "./utils.js";
2
+
3
+ export function setupVisualEditAgent() {
4
+ // State variables (replacing React useState/useRef)
5
+ let isVisualEditMode = false;
6
+ let isPopoverDragging = false;
7
+ let isDropdownOpen = false;
8
+ let hoverOverlays: HTMLDivElement[] = [];
9
+ let selectedOverlays: HTMLDivElement[] = [];
10
+ let currentHighlightedElements: Element[] = [];
11
+ let selectedElementId: string | null = null;
12
+
13
+ // Create overlay element
14
+ const createOverlay = (isSelected = false): HTMLDivElement => {
15
+ const overlay = document.createElement("div");
16
+ overlay.style.position = "absolute";
17
+ overlay.style.pointerEvents = "none";
18
+ overlay.style.transition = "all 0.1s ease-in-out";
19
+ overlay.style.zIndex = "9999";
20
+
21
+ if (isSelected) {
22
+ overlay.style.border = "2px solid #2563EB";
23
+ } else {
24
+ overlay.style.border = "2px solid #95a5fc";
25
+ overlay.style.backgroundColor = "rgba(99, 102, 241, 0.05)";
26
+ }
27
+
28
+ return overlay;
29
+ };
30
+
31
+ // Position overlay relative to element
32
+ const positionOverlay = (
33
+ overlay: HTMLDivElement,
34
+ element: Element,
35
+ isSelected = false
36
+ ) => {
37
+ if (!element || !isVisualEditMode) return;
38
+
39
+ const htmlElement = element as HTMLElement;
40
+ // Force layout recalculation
41
+ void htmlElement.offsetWidth;
42
+
43
+ const rect = element.getBoundingClientRect();
44
+ overlay.style.top = `${rect.top + window.scrollY}px`;
45
+ overlay.style.left = `${rect.left + window.scrollX}px`;
46
+ overlay.style.width = `${rect.width}px`;
47
+ overlay.style.height = `${rect.height}px`;
48
+
49
+ // Check if label already exists in overlay
50
+ let label = overlay.querySelector("div") as HTMLDivElement | null;
51
+
52
+ if (!label) {
53
+ label = document.createElement("div");
54
+ label.textContent = element.tagName.toLowerCase();
55
+ label.style.position = "absolute";
56
+ label.style.top = "-27px";
57
+ label.style.left = "-2px";
58
+ label.style.padding = "2px 8px";
59
+ label.style.fontSize = "11px";
60
+ label.style.fontWeight = isSelected ? "500" : "400";
61
+ label.style.color = isSelected ? "#ffffff" : "#526cff";
62
+ label.style.backgroundColor = isSelected ? "#526cff" : "#DBEAFE";
63
+ label.style.borderRadius = "3px";
64
+ label.style.minWidth = "24px";
65
+ label.style.textAlign = "center";
66
+ overlay.appendChild(label);
67
+ }
68
+ };
69
+
70
+ // Clear hover overlays
71
+ const clearHoverOverlays = () => {
72
+ hoverOverlays.forEach((overlay) => {
73
+ if (overlay && overlay.parentNode) {
74
+ overlay.remove();
75
+ }
76
+ });
77
+ hoverOverlays = [];
78
+ currentHighlightedElements = [];
79
+ };
80
+
81
+ // Handle mouse over event
82
+ const handleMouseOver = (e: MouseEvent) => {
83
+ if (!isVisualEditMode || isPopoverDragging) return;
84
+
85
+ const target = e.target as Element;
86
+
87
+ // Prevent hover effects when a dropdown is open
88
+ if (isDropdownOpen) {
89
+ clearHoverOverlays();
90
+ return;
91
+ }
92
+
93
+ // Prevent hover effects on SVG path elements
94
+ if (target.tagName.toLowerCase() === "path") {
95
+ clearHoverOverlays();
96
+ return;
97
+ }
98
+
99
+ // Support both data-source-location and data-visual-selector-id
100
+ const element = target.closest(
101
+ "[data-source-location], [data-visual-selector-id]"
102
+ );
103
+ if (!element) {
104
+ clearHoverOverlays();
105
+ return;
106
+ }
107
+
108
+ // Prefer data-source-location, fallback to data-visual-selector-id
109
+ const htmlElement = element as HTMLElement;
110
+ const selectorId =
111
+ htmlElement.dataset.sourceLocation ||
112
+ htmlElement.dataset.visualSelectorId;
113
+
114
+ // Skip if this element is already selected
115
+ if (selectedElementId === selectorId) {
116
+ clearHoverOverlays();
117
+ return;
118
+ }
119
+
120
+ // Find all elements with the same ID
121
+ const elements = findElementsById(selectorId || null);
122
+
123
+ // Clear previous hover overlays
124
+ clearHoverOverlays();
125
+
126
+ // Create overlays for all matching elements
127
+ elements.forEach((el) => {
128
+ const overlay = createOverlay(false);
129
+ document.body.appendChild(overlay);
130
+ hoverOverlays.push(overlay);
131
+ positionOverlay(overlay, el);
132
+ });
133
+
134
+ currentHighlightedElements = elements;
135
+ };
136
+
137
+ // Handle mouse out event
138
+ const handleMouseOut = () => {
139
+ if (isPopoverDragging) return;
140
+ clearHoverOverlays();
141
+ };
142
+
143
+ // Handle element click
144
+ const handleElementClick = (e: MouseEvent) => {
145
+ if (!isVisualEditMode) return;
146
+
147
+ const target = e.target as Element;
148
+
149
+ // Close dropdowns when clicking anywhere in iframe if a dropdown is open
150
+ if (isDropdownOpen) {
151
+ e.preventDefault();
152
+ e.stopPropagation();
153
+ e.stopImmediatePropagation();
154
+
155
+ window.parent.postMessage({ type: "close-dropdowns" }, "*");
156
+ return;
157
+ }
158
+
159
+ // Prevent clicking on SVG path elements
160
+ if (target.tagName.toLowerCase() === "path") {
161
+ return;
162
+ }
163
+
164
+ // Prevent default behavior immediately when in visual edit mode
165
+ e.preventDefault();
166
+ e.stopPropagation();
167
+ e.stopImmediatePropagation();
168
+
169
+ // Support both data-source-location and data-visual-selector-id
170
+ const element = target.closest(
171
+ "[data-source-location], [data-visual-selector-id]"
172
+ );
173
+ if (!element) {
174
+ return;
175
+ }
176
+
177
+ const htmlElement = element as HTMLElement;
178
+ const visualSelectorId =
179
+ htmlElement.dataset.sourceLocation ||
180
+ htmlElement.dataset.visualSelectorId;
181
+
182
+ // Clear any existing selected overlays
183
+ selectedOverlays.forEach((overlay) => {
184
+ if (overlay && overlay.parentNode) {
185
+ overlay.remove();
186
+ }
187
+ });
188
+ selectedOverlays = [];
189
+
190
+ // Find all elements with the same ID
191
+ const elements = findElementsById(visualSelectorId || null);
192
+
193
+ // Create selected overlays for all matching elements
194
+ elements.forEach((el) => {
195
+ const overlay = createOverlay(true);
196
+ document.body.appendChild(overlay);
197
+ selectedOverlays.push(overlay);
198
+ positionOverlay(overlay, el, true);
199
+ });
200
+
201
+ selectedElementId = visualSelectorId || null;
202
+
203
+ // Clear hover overlays
204
+ clearHoverOverlays();
205
+
206
+ // Calculate element position for popover positioning
207
+ const rect = element.getBoundingClientRect();
208
+ const elementPosition = {
209
+ top: rect.top,
210
+ left: rect.left,
211
+ right: rect.right,
212
+ bottom: rect.bottom,
213
+ width: rect.width,
214
+ height: rect.height,
215
+ centerX: rect.left + rect.width / 2,
216
+ centerY: rect.top + rect.height / 2,
217
+ };
218
+
219
+ // Send message to parent window with element info including position
220
+ const svgElement = element as SVGElement;
221
+ const elementData = {
222
+ type: "element-selected",
223
+ tagName: element.tagName,
224
+ classes:
225
+ (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||
226
+ element.className ||
227
+ "",
228
+ visualSelectorId: visualSelectorId,
229
+ content: (element as HTMLElement).innerText,
230
+ dataSourceLocation: htmlElement.dataset.sourceLocation,
231
+ isDynamicContent: htmlElement.dataset.dynamicContent === "true",
232
+ linenumber: htmlElement.dataset.linenumber,
233
+ filename: htmlElement.dataset.filename,
234
+ position: elementPosition,
235
+ };
236
+ window.parent.postMessage(elementData, "*");
237
+ };
238
+
239
+ // Unselect the current element
240
+ const unselectElement = () => {
241
+ selectedOverlays.forEach((overlay) => {
242
+ if (overlay && overlay.parentNode) {
243
+ overlay.remove();
244
+ }
245
+ });
246
+ selectedOverlays = [];
247
+ selectedElementId = null;
248
+ };
249
+
250
+ const updateElementClassesAndReposition = (visualSelectorId: string, classes: string) => {
251
+ const elements = findElementsById(visualSelectorId);
252
+ if (elements.length === 0) return;
253
+
254
+ updateElementClasses(elements, classes);
255
+
256
+ // Use a small delay to allow the browser to recalculate layout before repositioning
257
+ setTimeout(() => {
258
+ // Reposition selected overlays
259
+ if (selectedElementId === visualSelectorId) {
260
+ selectedOverlays.forEach((overlay, index) => {
261
+ if (index < elements.length) {
262
+ positionOverlay(overlay, elements[index]!);
263
+ }
264
+ });
265
+ }
266
+
267
+ // Reposition hover overlays if needed
268
+ if (currentHighlightedElements.length > 0) {
269
+ const hoveredElement = currentHighlightedElements[0] as HTMLElement;
270
+ const hoveredId = hoveredElement?.dataset?.visualSelectorId;
271
+ if (hoveredId === visualSelectorId) {
272
+ hoverOverlays.forEach((overlay, index) => {
273
+ if (index < currentHighlightedElements.length) {
274
+ positionOverlay(overlay, currentHighlightedElements[index]!);
275
+ }
276
+ });
277
+ }
278
+ }
279
+ }, 50);
280
+ };
281
+
282
+ // Update element content by visual selector ID
283
+ const updateElementContent = (visualSelectorId: string, content: string) => {
284
+ const elements = findElementsById(visualSelectorId);
285
+
286
+ if (elements.length === 0) {
287
+ return;
288
+ }
289
+
290
+ elements.forEach((element) => {
291
+ (element as HTMLElement).innerText = content;
292
+ });
293
+
294
+ setTimeout(() => {
295
+ if (selectedElementId === visualSelectorId) {
296
+ selectedOverlays.forEach((overlay, index) => {
297
+ if (index < elements.length) {
298
+ positionOverlay(overlay, elements[index]!);
299
+ }
300
+ });
301
+ }
302
+ }, 50);
303
+ };
304
+
305
+ // Toggle visual edit mode
306
+ const toggleVisualEditMode = (isEnabled: boolean) => {
307
+ isVisualEditMode = isEnabled;
308
+
309
+ if (!isEnabled) {
310
+ clearHoverOverlays();
311
+
312
+ selectedOverlays.forEach((overlay) => {
313
+ if (overlay && overlay.parentNode) {
314
+ overlay.remove();
315
+ }
316
+ });
317
+ selectedOverlays = [];
318
+
319
+ currentHighlightedElements = [];
320
+ selectedElementId = null;
321
+ document.body.style.cursor = "default";
322
+
323
+ document.removeEventListener("mouseover", handleMouseOver);
324
+ document.removeEventListener("mouseout", handleMouseOut);
325
+ document.removeEventListener("click", handleElementClick, true);
326
+ } else {
327
+ document.body.style.cursor = "crosshair";
328
+ document.addEventListener("mouseover", handleMouseOver);
329
+ document.addEventListener("mouseout", handleMouseOut);
330
+ document.addEventListener("click", handleElementClick, true);
331
+ }
332
+ };
333
+
334
+ // Handle scroll events to update popover position
335
+ const handleScroll = () => {
336
+ if (selectedElementId) {
337
+ const elements = findElementsById(selectedElementId);
338
+ if (elements.length > 0) {
339
+ const element = elements[0];
340
+ const rect = element!.getBoundingClientRect();
341
+
342
+ const viewportHeight = window.innerHeight;
343
+ const viewportWidth = window.innerWidth;
344
+ const isInViewport =
345
+ rect.top < viewportHeight &&
346
+ rect.bottom > 0 &&
347
+ rect.left < viewportWidth &&
348
+ rect.right > 0;
349
+
350
+ const elementPosition = {
351
+ top: rect.top,
352
+ left: rect.left,
353
+ right: rect.right,
354
+ bottom: rect.bottom,
355
+ width: rect.width,
356
+ height: rect.height,
357
+ centerX: rect.left + rect.width / 2,
358
+ centerY: rect.top + rect.height / 2,
359
+ };
360
+
361
+ window.parent.postMessage(
362
+ {
363
+ type: "element-position-update",
364
+ position: elementPosition,
365
+ isInViewport: isInViewport,
366
+ visualSelectorId: selectedElementId,
367
+ },
368
+ "*"
369
+ );
370
+ }
371
+ }
372
+ };
373
+
374
+ // Handle messages from parent window
375
+ const handleMessage = (event: MessageEvent) => {
376
+ const message = event.data;
377
+
378
+ switch (message.type) {
379
+ case "toggle-visual-edit-mode":
380
+ toggleVisualEditMode(message.data.enabled);
381
+ break;
382
+
383
+ case "update-classes":
384
+ if (message.data && message.data.classes !== undefined) {
385
+ updateElementClassesAndReposition(
386
+ message.data.visualSelectorId,
387
+ message.data.classes
388
+ );
389
+ } else {
390
+ console.warn(
391
+ "[VisualEditAgent] Invalid update-classes message:",
392
+ message
393
+ );
394
+ }
395
+ break;
396
+
397
+ case "unselect-element":
398
+ unselectElement();
399
+ break;
400
+
401
+ case "refresh-page":
402
+ window.location.reload();
403
+ break;
404
+
405
+ case "update-content":
406
+ if (message.data && message.data.content !== undefined) {
407
+ updateElementContent(
408
+ message.data.visualSelectorId,
409
+ message.data.content
410
+ );
411
+ } else {
412
+ console.warn(
413
+ "[VisualEditAgent] Invalid update-content message:",
414
+ message
415
+ );
416
+ }
417
+ break;
418
+
419
+ case "request-element-position":
420
+ if (selectedElementId) {
421
+ const elements = findElementsById(selectedElementId);
422
+ if (elements.length > 0) {
423
+ const element = elements[0];
424
+ const rect = element!.getBoundingClientRect();
425
+
426
+ const viewportHeight = window.innerHeight;
427
+ const viewportWidth = window.innerWidth;
428
+ const isInViewport =
429
+ rect.top < viewportHeight &&
430
+ rect.bottom > 0 &&
431
+ rect.left < viewportWidth &&
432
+ rect.right > 0;
433
+
434
+ const elementPosition = {
435
+ top: rect.top,
436
+ left: rect.left,
437
+ right: rect.right,
438
+ bottom: rect.bottom,
439
+ width: rect.width,
440
+ height: rect.height,
441
+ centerX: rect.left + rect.width / 2,
442
+ centerY: rect.top + rect.height / 2,
443
+ };
444
+
445
+ window.parent.postMessage(
446
+ {
447
+ type: "element-position-update",
448
+ position: elementPosition,
449
+ isInViewport: isInViewport,
450
+ visualSelectorId: selectedElementId,
451
+ },
452
+ "*"
453
+ );
454
+ }
455
+ }
456
+ break;
457
+
458
+ case "popover-drag-state":
459
+ if (message.data && message.data.isDragging !== undefined) {
460
+ isPopoverDragging = message.data.isDragging;
461
+ if (message.data.isDragging) {
462
+ clearHoverOverlays();
463
+ }
464
+ }
465
+ break;
466
+
467
+ case "dropdown-state":
468
+ if (message.data && message.data.isOpen !== undefined) {
469
+ isDropdownOpen = message.data.isOpen;
470
+ if (message.data.isOpen) {
471
+ clearHoverOverlays();
472
+ }
473
+ }
474
+ break;
475
+
476
+ case "update-theme-variables":
477
+ if (message.data?.variables) {
478
+ const style = document.documentElement.style;
479
+ for (const [name, value] of Object.entries(message.data.variables)) {
480
+ style.setProperty(name, value as string);
481
+ }
482
+ }
483
+ break;
484
+
485
+ default:
486
+ break;
487
+ }
488
+ };
489
+
490
+ // Handle window resize to reposition overlays
491
+ const handleResize = () => {
492
+ if (selectedElementId) {
493
+ const elements = findElementsById(selectedElementId);
494
+ selectedOverlays.forEach((overlay, index) => {
495
+ if (index < elements.length) {
496
+ positionOverlay(overlay, elements[index]!);
497
+ }
498
+ });
499
+ }
500
+
501
+ if (currentHighlightedElements.length > 0) {
502
+ hoverOverlays.forEach((overlay, index) => {
503
+ if (index < currentHighlightedElements.length) {
504
+ positionOverlay(overlay, currentHighlightedElements[index]!);
505
+ }
506
+ });
507
+ }
508
+ };
509
+
510
+ // Initialize: Add IDs to elements that don't have them but have linenumbers
511
+ const elementsWithLineNumber = document.querySelectorAll(
512
+ "[data-linenumber]:not([data-visual-selector-id])"
513
+ );
514
+ elementsWithLineNumber.forEach((el, index) => {
515
+ const htmlEl = el as HTMLElement;
516
+ const id = `visual-id-${htmlEl.dataset.filename}-${htmlEl.dataset.linenumber}-${index}`;
517
+ htmlEl.dataset.visualSelectorId = id;
518
+ });
519
+
520
+ // Create mutation observer to detect layout changes
521
+ const mutationObserver = new MutationObserver((mutations) => {
522
+ const needsUpdate = mutations.some((mutation) => {
523
+ const hasVisualId = (node: Node): boolean => {
524
+ if (node.nodeType === Node.ELEMENT_NODE) {
525
+ const el = node as HTMLElement;
526
+ if (el.dataset && el.dataset.visualSelectorId) {
527
+ return true;
528
+ }
529
+ for (let i = 0; i < el.children.length; i++) {
530
+ if (hasVisualId(el.children[i]!)) {
531
+ return true;
532
+ }
533
+ }
534
+ }
535
+ return false;
536
+ };
537
+
538
+ const isLayoutChange =
539
+ mutation.type === "attributes" &&
540
+ (mutation.attributeName === "style" ||
541
+ mutation.attributeName === "class" ||
542
+ mutation.attributeName === "width" ||
543
+ mutation.attributeName === "height");
544
+
545
+ return isLayoutChange && hasVisualId(mutation.target);
546
+ });
547
+
548
+ if (needsUpdate) {
549
+ setTimeout(handleResize, 50);
550
+ }
551
+ });
552
+
553
+ // Set up event listeners
554
+ window.addEventListener("message", handleMessage);
555
+ window.addEventListener("scroll", handleScroll, true);
556
+ document.addEventListener("scroll", handleScroll, true);
557
+ window.addEventListener("resize", handleResize);
558
+ window.addEventListener("scroll", handleResize);
559
+
560
+ // Start observing DOM mutations
561
+ mutationObserver.observe(document.body, {
562
+ attributes: true,
563
+ childList: true,
564
+ subtree: true,
565
+ attributeFilter: ["style", "class", "width", "height"],
566
+ });
567
+
568
+ // Send ready message to parent
569
+ window.parent.postMessage({ type: "visual-edit-agent-ready" }, "*");
570
+ }
@@ -1,25 +0,0 @@
1
- /**
2
- * Callback function type for handling text input changes
3
- */
4
- type OnTextInputChange = (element: HTMLElement) => void;
5
- /**
6
- * Set the callback function that will be called on text input changes
7
- */
8
- export declare function setInlineEditCallback(callback: OnTextInputChange | null): void;
9
- /**
10
- * Check if an element should enter inline editing mode
11
- * Called when user clicks on an already-selected element
12
- */
13
- export declare function shouldEnterInlineEditingMode(element: Element): boolean;
14
- /**
15
- * Enable contentEditable mode on an element
16
- * Follows the exact flow from inlineEdit.md
17
- */
18
- export declare function enterInlineEditingMode(element: HTMLElement): void;
19
- /**
20
- * Disable contentEditable mode on an element
21
- * Reverses everything done by enterInlineEditingMode
22
- */
23
- export declare function clearInlineEditingMode(element: HTMLElement): void;
24
- export {};
25
- //# sourceMappingURL=core.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../../src/injections/visual-edit-agent/capabilities/inline-editing/core.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;AAQxD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAE9E;AAkBD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAYtE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CA4BjE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CA0BjE"}
@@ -1,95 +0,0 @@
1
- import { injectFocusOutlineCSS, removeFocusOutlineCSS } from "./styles.js";
2
- import { selectText, isEditableTextElement } from "./validation.js";
3
- /**
4
- * Global callback that gets triggered on every input event
5
- * This is set by the visual-edit-agent and includes both updatePosition and reportInlineEdit
6
- */
7
- let onTextInputChangeCallback = null;
8
- /**
9
- * Set the callback function that will be called on text input changes
10
- */
11
- export function setInlineEditCallback(callback) {
12
- onTextInputChangeCallback = callback;
13
- }
14
- /**
15
- * WeakMap to track AbortControllers for each element's input listener.
16
- * Using WeakMap ensures no memory leaks — when an element is garbage collected,
17
- * its entry is automatically removed.
18
- */
19
- const listenerAbortControllers = new WeakMap();
20
- /**
21
- * Internal handler for the native input event
22
- */
23
- function handleInputEvent(e) {
24
- if (onTextInputChangeCallback) {
25
- onTextInputChangeCallback(this);
26
- }
27
- }
28
- /**
29
- * Check if an element should enter inline editing mode
30
- * Called when user clicks on an already-selected element
31
- */
32
- export function shouldEnterInlineEditingMode(element) {
33
- // Must have data-selected="true"
34
- if (!(element instanceof HTMLElement) || element.dataset.selected !== "true") {
35
- return false;
36
- }
37
- // Must pass all editability checks
38
- if (!isEditableTextElement(element)) {
39
- return false;
40
- }
41
- return true;
42
- }
43
- /**
44
- * Enable contentEditable mode on an element
45
- * Follows the exact flow from inlineEdit.md
46
- */
47
- export function enterInlineEditingMode(element) {
48
- // Inject CSS to suppress focus outline
49
- injectFocusOutlineCSS();
50
- // Store original state
51
- element.dataset.originalTextContent = element.textContent || "";
52
- element.dataset.originalCursor = element.style.cursor;
53
- // Enable contentEditable
54
- element.contentEditable = "true";
55
- // Create an AbortController to manage the input listener lifecycle
56
- const abortController = new AbortController();
57
- listenerAbortControllers.set(element, abortController);
58
- // Add input event listener with AbortSignal for automatic cleanup
59
- element.addEventListener("input", handleInputEvent, { signal: abortController.signal });
60
- // Set cursor to text
61
- element.style.cursor = "text";
62
- // Select all text
63
- selectText(element);
64
- // Focus after render
65
- setTimeout(() => {
66
- element.focus();
67
- }, 0);
68
- }
69
- /**
70
- * Disable contentEditable mode on an element
71
- * Reverses everything done by enterInlineEditingMode
72
- */
73
- export function clearInlineEditingMode(element) {
74
- // Abort the input event listener using the stored AbortController
75
- const abortController = listenerAbortControllers.get(element);
76
- if (abortController) {
77
- abortController.abort();
78
- listenerAbortControllers.delete(element);
79
- }
80
- // If element was removed from DOM before cleanup, skip DOM operations
81
- if (!element.isConnected) {
82
- return;
83
- }
84
- removeFocusOutlineCSS();
85
- // Disable contentEditable
86
- element.contentEditable = "false";
87
- // Remove stored original text content
88
- delete element.dataset.originalTextContent;
89
- // Restore original cursor
90
- if (element.dataset.originalCursor !== undefined) {
91
- element.style.cursor = element.dataset.originalCursor;
92
- delete element.dataset.originalCursor;
93
- }
94
- }
95
- //# sourceMappingURL=core.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../../../src/injections/visual-edit-agent/capabilities/inline-editing/core.ts"],"names":[],"mappings":"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"}