@base44-preview/vite-plugin 0.2.26-pr.43.e9195be → 0.2.27-pr.41.77be9cb

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 (168) hide show
  1. package/dist/capabilities/inline-edit/controller.d.ts +3 -0
  2. package/dist/capabilities/inline-edit/controller.d.ts.map +1 -0
  3. package/dist/capabilities/inline-edit/controller.js +194 -0
  4. package/dist/capabilities/inline-edit/controller.js.map +1 -0
  5. package/dist/capabilities/inline-edit/dom-utils.d.ts +6 -0
  6. package/dist/capabilities/inline-edit/dom-utils.d.ts.map +1 -0
  7. package/dist/capabilities/inline-edit/dom-utils.js +49 -0
  8. package/dist/capabilities/inline-edit/dom-utils.js.map +1 -0
  9. package/dist/capabilities/inline-edit/index.d.ts +3 -0
  10. package/dist/capabilities/inline-edit/index.d.ts.map +1 -0
  11. package/dist/capabilities/inline-edit/index.js +2 -0
  12. package/dist/capabilities/inline-edit/index.js.map +1 -0
  13. package/dist/capabilities/inline-edit/types.d.ts +25 -0
  14. package/dist/capabilities/inline-edit/types.d.ts.map +1 -0
  15. package/dist/capabilities/inline-edit/types.js.map +1 -0
  16. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts +25 -0
  17. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.d.ts.map +1 -0
  18. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js +95 -0
  19. package/dist/injections/visual-edit-agent/capabilities/inline-editing/core.js.map +1 -0
  20. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts +4 -0
  21. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.d.ts.map +1 -0
  22. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js +4 -0
  23. package/dist/injections/visual-edit-agent/capabilities/inline-editing/index.js.map +1 -0
  24. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts +9 -0
  25. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.d.ts.map +1 -0
  26. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js +26 -0
  27. package/dist/injections/visual-edit-agent/capabilities/inline-editing/styles.js.map +1 -0
  28. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts +17 -0
  29. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.d.ts.map +1 -0
  30. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js +76 -0
  31. package/dist/injections/visual-edit-agent/capabilities/inline-editing/validation.js.map +1 -0
  32. package/dist/injections/visual-edit-agent/constants.d.ts +10 -0
  33. package/dist/injections/visual-edit-agent/constants.d.ts.map +1 -0
  34. package/dist/injections/visual-edit-agent/constants.js +10 -0
  35. package/dist/injections/visual-edit-agent/constants.js.map +1 -0
  36. package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts +10 -0
  37. package/dist/injections/visual-edit-agent/handlers/click-handlers.d.ts.map +1 -0
  38. package/dist/injections/visual-edit-agent/handlers/click-handlers.js +117 -0
  39. package/dist/injections/visual-edit-agent/handlers/click-handlers.js.map +1 -0
  40. package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts +14 -0
  41. package/dist/injections/visual-edit-agent/handlers/hover-handlers.d.ts.map +1 -0
  42. package/dist/injections/visual-edit-agent/handlers/hover-handlers.js +64 -0
  43. package/dist/injections/visual-edit-agent/handlers/hover-handlers.js.map +1 -0
  44. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts +14 -0
  45. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.d.ts.map +1 -0
  46. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js +114 -0
  47. package/dist/injections/visual-edit-agent/handlers/inline-edit-handlers.js.map +1 -0
  48. package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts +26 -0
  49. package/dist/injections/visual-edit-agent/handlers/message-handlers.d.ts.map +1 -0
  50. package/dist/injections/visual-edit-agent/handlers/message-handlers.js +148 -0
  51. package/dist/injections/visual-edit-agent/handlers/message-handlers.js.map +1 -0
  52. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts +7 -0
  53. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.d.ts.map +1 -0
  54. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js +54 -0
  55. package/dist/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.js.map +1 -0
  56. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts +11 -0
  57. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.d.ts.map +1 -0
  58. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js +32 -0
  59. package/dist/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.js.map +1 -0
  60. package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts +105 -0
  61. package/dist/injections/visual-edit-agent/handlers/messages/types.d.ts.map +1 -0
  62. package/dist/injections/visual-edit-agent/handlers/messages/types.js +28 -0
  63. package/dist/injections/visual-edit-agent/handlers/messages/types.js.map +1 -0
  64. package/dist/injections/visual-edit-agent/index.d.ts +6 -0
  65. package/dist/injections/visual-edit-agent/index.d.ts.map +1 -0
  66. package/dist/injections/visual-edit-agent/index.js +109 -0
  67. package/dist/injections/visual-edit-agent/index.js.map +1 -0
  68. package/dist/injections/visual-edit-agent/state/agent-state.d.ts +17 -0
  69. package/dist/injections/visual-edit-agent/state/agent-state.d.ts.map +1 -0
  70. package/dist/injections/visual-edit-agent/state/agent-state.js +18 -0
  71. package/dist/injections/visual-edit-agent/state/agent-state.js.map +1 -0
  72. package/dist/injections/visual-edit-agent/ui/overlay.d.ts +26 -0
  73. package/dist/injections/visual-edit-agent/ui/overlay.d.ts.map +1 -0
  74. package/dist/injections/visual-edit-agent/ui/overlay.js +104 -0
  75. package/dist/injections/visual-edit-agent/ui/overlay.js.map +1 -0
  76. package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts +14 -0
  77. package/dist/injections/visual-edit-agent/utils/dom-utils.d.ts.map +1 -0
  78. package/dist/injections/visual-edit-agent/utils/dom-utils.js +34 -0
  79. package/dist/injections/visual-edit-agent/utils/dom-utils.js.map +1 -0
  80. package/dist/injections/visual-edit-agent.d.ts +1 -1
  81. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  82. package/dist/injections/visual-edit-agent.js +1 -506
  83. package/dist/injections/visual-edit-agent.js.map +1 -1
  84. package/dist/jsx-processor.d.ts +1 -4
  85. package/dist/jsx-processor.d.ts.map +1 -1
  86. package/dist/jsx-processor.js +6 -33
  87. package/dist/jsx-processor.js.map +1 -1
  88. package/dist/jsx-utils.d.ts +0 -9
  89. package/dist/jsx-utils.d.ts.map +1 -1
  90. package/dist/jsx-utils.js +0 -86
  91. package/dist/jsx-utils.js.map +1 -1
  92. package/dist/processors/shared-utils.d.ts +0 -64
  93. package/dist/processors/shared-utils.d.ts.map +1 -1
  94. package/dist/processors/shared-utils.js +0 -468
  95. package/dist/processors/shared-utils.js.map +1 -1
  96. package/dist/processors/static-array-processor.d.ts +3 -2
  97. package/dist/processors/static-array-processor.d.ts.map +1 -1
  98. package/dist/processors/static-array-processor.js +3 -2
  99. package/dist/processors/static-array-processor.js.map +1 -1
  100. package/dist/statics/index.mjs +5 -1
  101. package/dist/statics/index.mjs.map +1 -1
  102. package/dist/visual-edit-plugin.d.ts +1 -0
  103. package/dist/visual-edit-plugin.d.ts.map +1 -1
  104. package/dist/visual-edit-plugin.js +178 -29
  105. package/dist/visual-edit-plugin.js.map +1 -1
  106. package/package.json +1 -1
  107. package/src/capabilities/inline-edit/controller.ts +245 -0
  108. package/src/capabilities/inline-edit/dom-utils.ts +48 -0
  109. package/src/capabilities/inline-edit/index.ts +2 -0
  110. package/src/capabilities/inline-edit/types.ts +30 -0
  111. package/src/injections/visual-edit-agent/README.md +222 -0
  112. package/src/injections/visual-edit-agent/capabilities/inline-editing/core.ts +120 -0
  113. package/src/injections/visual-edit-agent/capabilities/inline-editing/index.ts +10 -0
  114. package/src/injections/visual-edit-agent/capabilities/inline-editing/styles.ts +26 -0
  115. package/src/injections/visual-edit-agent/capabilities/inline-editing/validation.ts +87 -0
  116. package/src/injections/visual-edit-agent/constants.ts +9 -0
  117. package/src/injections/visual-edit-agent/handlers/click-handlers.ts +146 -0
  118. package/src/injections/visual-edit-agent/handlers/hover-handlers.ts +78 -0
  119. package/src/injections/visual-edit-agent/handlers/inline-edit-handlers.ts +146 -0
  120. package/src/injections/visual-edit-agent/handlers/message-handlers.ts +201 -0
  121. package/src/injections/visual-edit-agent/handlers/messages/toggle-inline-edit-mode.ts +65 -0
  122. package/src/injections/visual-edit-agent/handlers/messages/toggle-visual-edit-mode.ts +40 -0
  123. package/src/injections/visual-edit-agent/handlers/messages/types.ts +134 -0
  124. package/src/injections/visual-edit-agent/index.ts +121 -0
  125. package/src/injections/visual-edit-agent/state/agent-state.ts +31 -0
  126. package/src/injections/visual-edit-agent/ui/overlay.ts +126 -0
  127. package/src/injections/visual-edit-agent/utils/dom-utils.ts +39 -0
  128. package/src/injections/visual-edit-agent.ts +1 -625
  129. package/src/jsx-processor.ts +14 -41
  130. package/src/jsx-utils.ts +0 -116
  131. package/src/processors/shared-utils.ts +0 -596
  132. package/src/processors/static-array-processor.ts +3 -6
  133. package/src/visual-edit-plugin.ts +215 -34
  134. package/dist/consts.d.ts +0 -12
  135. package/dist/consts.d.ts.map +0 -1
  136. package/dist/consts.js +0 -12
  137. package/dist/consts.js.map +0 -1
  138. package/dist/processors/collection-id-processor.d.ts +0 -20
  139. package/dist/processors/collection-id-processor.d.ts.map +0 -1
  140. package/dist/processors/collection-id-processor.js +0 -182
  141. package/dist/processors/collection-id-processor.js.map +0 -1
  142. package/dist/processors/collection-item-field-processor.d.ts +0 -33
  143. package/dist/processors/collection-item-field-processor.d.ts.map +0 -1
  144. package/dist/processors/collection-item-field-processor.js +0 -275
  145. package/dist/processors/collection-item-field-processor.js.map +0 -1
  146. package/dist/processors/collection-item-id-processor.d.ts +0 -12
  147. package/dist/processors/collection-item-id-processor.d.ts.map +0 -1
  148. package/dist/processors/collection-item-id-processor.js +0 -50
  149. package/dist/processors/collection-item-id-processor.js.map +0 -1
  150. package/dist/processors/collection-reference-field-processor.d.ts +0 -31
  151. package/dist/processors/collection-reference-field-processor.d.ts.map +0 -1
  152. package/dist/processors/collection-reference-field-processor.js +0 -174
  153. package/dist/processors/collection-reference-field-processor.js.map +0 -1
  154. package/dist/processors/collection-tracing-utils.d.ts +0 -31
  155. package/dist/processors/collection-tracing-utils.d.ts.map +0 -1
  156. package/dist/processors/collection-tracing-utils.js +0 -326
  157. package/dist/processors/collection-tracing-utils.js.map +0 -1
  158. package/dist/types.d.ts +0 -5
  159. package/dist/types.d.ts.map +0 -1
  160. package/dist/types.js.map +0 -1
  161. package/src/consts.ts +0 -12
  162. package/src/processors/collection-id-processor.ts +0 -261
  163. package/src/processors/collection-item-field-processor.ts +0 -410
  164. package/src/processors/collection-item-id-processor.ts +0 -69
  165. package/src/processors/collection-reference-field-processor.ts +0 -225
  166. package/src/processors/collection-tracing-utils.ts +0 -436
  167. package/src/types.ts +0 -4
  168. /package/dist/{types.js → capabilities/inline-edit/types.js} +0 -0
@@ -1,625 +1 @@
1
- import { findElementsById, updateElementClasses, updateElementAttribute, collectAllowedAttributes, ALLOWED_ATTRIBUTES, getElementSelectorId } from "./utils.js";
2
- import { createLayerController } from "./layer-dropdown/controller.js";
3
- import { LAYER_DROPDOWN_ATTR } from "./layer-dropdown/consts.js";
4
-
5
- export function setupVisualEditAgent() {
6
- // State variables (replacing React useState/useRef)
7
- let isVisualEditMode = false;
8
- let isPopoverDragging = false;
9
- let isDropdownOpen = false;
10
- let hoverOverlays: HTMLDivElement[] = [];
11
- let selectedOverlays: HTMLDivElement[] = [];
12
- let currentHighlightedElements: Element[] = [];
13
- let selectedElementId: string | null = null;
14
-
15
- // Create overlay element
16
- const createOverlay = (isSelected = false): HTMLDivElement => {
17
- const overlay = document.createElement("div");
18
- overlay.style.position = "absolute";
19
- overlay.style.pointerEvents = "none";
20
- overlay.style.transition = "all 0.1s ease-in-out";
21
- overlay.style.zIndex = "9999";
22
-
23
- if (isSelected) {
24
- overlay.style.border = "2px solid #2563EB";
25
- } else {
26
- overlay.style.border = "2px solid #95a5fc";
27
- overlay.style.backgroundColor = "rgba(99, 102, 241, 0.05)";
28
- }
29
-
30
- return overlay;
31
- };
32
-
33
- // Position overlay relative to element
34
- const positionOverlay = (
35
- overlay: HTMLDivElement,
36
- element: Element,
37
- isSelected = false
38
- ) => {
39
- if (!element || !isVisualEditMode) return;
40
-
41
- const htmlElement = element as HTMLElement;
42
- // Force layout recalculation
43
- void htmlElement.offsetWidth;
44
-
45
- const rect = element.getBoundingClientRect();
46
- overlay.style.top = `${rect.top + window.scrollY}px`;
47
- overlay.style.left = `${rect.left + window.scrollX}px`;
48
- overlay.style.width = `${rect.width}px`;
49
- overlay.style.height = `${rect.height}px`;
50
-
51
- // Check if label already exists in overlay
52
- let label = overlay.querySelector("div") as HTMLDivElement | null;
53
-
54
- if (!label) {
55
- label = document.createElement("div");
56
- label.textContent = element.tagName.toLowerCase();
57
- label.style.position = "absolute";
58
- label.style.top = "-27px";
59
- label.style.left = "-2px";
60
- label.style.padding = "2px 8px";
61
- label.style.fontSize = "11px";
62
- label.style.fontWeight = isSelected ? "500" : "400";
63
- label.style.color = isSelected ? "#ffffff" : "#526cff";
64
- label.style.backgroundColor = isSelected ? "#526cff" : "#DBEAFE";
65
- label.style.borderRadius = "3px";
66
- label.style.minWidth = "24px";
67
- label.style.textAlign = "center";
68
- overlay.appendChild(label);
69
- }
70
- };
71
-
72
- // Clear hover overlays
73
- const clearHoverOverlays = () => {
74
- hoverOverlays.forEach((overlay) => {
75
- if (overlay && overlay.parentNode) {
76
- overlay.remove();
77
- }
78
- });
79
- hoverOverlays = [];
80
- currentHighlightedElements = [];
81
- };
82
-
83
- const clearSelectedOverlays = () => {
84
- selectedOverlays.forEach((overlay) => {
85
- if (overlay && overlay.parentNode) {
86
- overlay.remove();
87
- }
88
- });
89
- selectedOverlays = [];
90
- };
91
-
92
- const TEXT_TAGS = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'a', 'label'];
93
-
94
- const notifyElementSelected = (element: Element) => {
95
- const htmlElement = element as HTMLElement;
96
- const rect = element.getBoundingClientRect();
97
- const svgElement = element as SVGElement;
98
- const isTextElement = TEXT_TAGS.includes(element.tagName?.toLowerCase());
99
- window.parent.postMessage({
100
- type: "element-selected",
101
- tagName: element.tagName,
102
- classes:
103
- (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||
104
- element.className ||
105
- "",
106
- visualSelectorId: getElementSelectorId(element),
107
- content: isTextElement ? htmlElement.innerText : undefined,
108
- dataSourceLocation: htmlElement.dataset.sourceLocation,
109
- isDynamicContent: htmlElement.dataset.dynamicContent === "true",
110
- linenumber: htmlElement.dataset.linenumber,
111
- filename: htmlElement.dataset.filename,
112
- position: {
113
- top: rect.top,
114
- left: rect.left,
115
- right: rect.right,
116
- bottom: rect.bottom,
117
- width: rect.width,
118
- height: rect.height,
119
- centerX: rect.left + rect.width / 2,
120
- centerY: rect.top + rect.height / 2,
121
- },
122
- attributes: collectAllowedAttributes(element, ALLOWED_ATTRIBUTES),
123
- isTextElement,
124
- }, "*");
125
- };
126
-
127
- // Select an element: create overlays, update state, notify parent
128
- const selectElement = (element: Element): HTMLDivElement | undefined => {
129
- const visualSelectorId = getElementSelectorId(element);
130
-
131
- clearSelectedOverlays();
132
-
133
- const elements = findElementsById(visualSelectorId || null);
134
- elements.forEach((el) => {
135
- const overlay = createOverlay(true);
136
- document.body.appendChild(overlay);
137
- selectedOverlays.push(overlay);
138
- positionOverlay(overlay, el, true);
139
- });
140
-
141
- selectedElementId = visualSelectorId || null;
142
- clearHoverOverlays();
143
- notifyElementSelected(element);
144
-
145
- return selectedOverlays[0];
146
- };
147
-
148
- const notifyDeselection = (): void => {
149
- selectedElementId = null;
150
- window.parent.postMessage({ type: "unselect-element" }, "*");
151
- };
152
-
153
- // Handle mouse over event
154
- const handleMouseOver = (e: MouseEvent) => {
155
- if (!isVisualEditMode || isPopoverDragging) return;
156
-
157
- const target = e.target as Element;
158
-
159
- // Prevent hover effects when a dropdown is open
160
- if (isDropdownOpen) {
161
- clearHoverOverlays();
162
- return;
163
- }
164
-
165
- // Prevent hover effects on SVG path elements
166
- if (target.tagName.toLowerCase() === "path") {
167
- clearHoverOverlays();
168
- return;
169
- }
170
-
171
- // Support both data-source-location and data-visual-selector-id
172
- const element = target.closest(
173
- "[data-source-location], [data-visual-selector-id]"
174
- );
175
- if (!element) {
176
- clearHoverOverlays();
177
- return;
178
- }
179
-
180
- // Prefer data-source-location, fallback to data-visual-selector-id
181
- const htmlElement = element as HTMLElement;
182
- const selectorId =
183
- htmlElement.dataset.sourceLocation ||
184
- htmlElement.dataset.visualSelectorId;
185
-
186
- // Skip if this element is already selected
187
- if (selectedElementId === selectorId) {
188
- clearHoverOverlays();
189
- return;
190
- }
191
-
192
- // Find all elements with the same ID
193
- const elements = findElementsById(selectorId || null);
194
-
195
- // Clear previous hover overlays
196
- clearHoverOverlays();
197
-
198
- // Create overlays for all matching elements
199
- elements.forEach((el) => {
200
- const overlay = createOverlay(false);
201
- document.body.appendChild(overlay);
202
- hoverOverlays.push(overlay);
203
- positionOverlay(overlay, el);
204
- });
205
-
206
- currentHighlightedElements = elements;
207
- };
208
-
209
- // Handle mouse out event
210
- const handleMouseOut = () => {
211
- if (isPopoverDragging) return;
212
- clearHoverOverlays();
213
- };
214
-
215
- // Handle element click
216
- const handleElementClick = (e: MouseEvent) => {
217
- if (!isVisualEditMode) return;
218
-
219
- const target = e.target as Element;
220
-
221
- // Let layer dropdown clicks pass through without interference
222
- if (target.closest(`[${LAYER_DROPDOWN_ATTR}]`)) return;
223
-
224
- // Close dropdowns when clicking anywhere in iframe if a dropdown is open
225
- if (isDropdownOpen) {
226
- e.preventDefault();
227
- e.stopPropagation();
228
- e.stopImmediatePropagation();
229
-
230
- window.parent.postMessage({ type: "close-dropdowns" }, "*");
231
- return;
232
- }
233
-
234
- // Prevent clicking on SVG path elements
235
- if (target.tagName.toLowerCase() === "path") {
236
- return;
237
- }
238
-
239
- // Prevent default behavior immediately when in visual edit mode
240
- e.preventDefault();
241
- e.stopPropagation();
242
- e.stopImmediatePropagation();
243
-
244
- // Support both data-source-location and data-visual-selector-id
245
- const element = target.closest(
246
- "[data-source-location], [data-visual-selector-id]"
247
- );
248
- if (!element) {
249
- return;
250
- }
251
-
252
- const selectedOverlay = selectElement(element);
253
- layerController.attachToOverlay(selectedOverlay, element);
254
- };
255
-
256
- // Clear the current selection
257
- const clearSelection = () => {
258
- clearSelectedOverlays();
259
- selectedElementId = null;
260
- };
261
-
262
- const updateElementClassesAndReposition = (visualSelectorId: string, classes: string) => {
263
- const elements = findElementsById(visualSelectorId);
264
- if (elements.length === 0) return;
265
-
266
- updateElementClasses(elements, classes);
267
-
268
- // Use a small delay to allow the browser to recalculate layout before repositioning
269
- setTimeout(() => {
270
- // Reposition selected overlays
271
- if (selectedElementId === visualSelectorId) {
272
- selectedOverlays.forEach((overlay, index) => {
273
- if (index < elements.length) {
274
- positionOverlay(overlay, elements[index]!);
275
- }
276
- });
277
- }
278
-
279
- // Reposition hover overlays if needed
280
- if (currentHighlightedElements.length > 0) {
281
- const hoveredElement = currentHighlightedElements[0] as HTMLElement;
282
- const hoveredId = hoveredElement?.dataset?.visualSelectorId;
283
- if (hoveredId === visualSelectorId) {
284
- hoverOverlays.forEach((overlay, index) => {
285
- if (index < currentHighlightedElements.length) {
286
- positionOverlay(overlay, currentHighlightedElements[index]!);
287
- }
288
- });
289
- }
290
- }
291
- }, 50);
292
- };
293
-
294
- // Update element attribute by visual selector ID
295
- const updateElementAttributeAndReposition = (
296
- visualSelectorId: string,
297
- attribute: string,
298
- value: string
299
- ) => {
300
- const elements = findElementsById(visualSelectorId);
301
- if (elements.length === 0) return;
302
-
303
- updateElementAttribute(elements, attribute, value);
304
-
305
- // Reposition overlays after attribute change (e.g. image src swap can affect layout)
306
- setTimeout(() => {
307
- if (selectedElementId === visualSelectorId) {
308
- selectedOverlays.forEach((overlay, index) => {
309
- if (index < elements.length) {
310
- positionOverlay(overlay, elements[index]!);
311
- }
312
- });
313
- }
314
- }, 50);
315
- };
316
-
317
- // Update element content by visual selector ID
318
- const updateElementContent = (visualSelectorId: string, content: string) => {
319
- const elements = findElementsById(visualSelectorId);
320
-
321
- if (elements.length === 0) {
322
- return;
323
- }
324
-
325
- elements.forEach((element) => {
326
- (element as HTMLElement).innerText = content;
327
- });
328
-
329
- setTimeout(() => {
330
- if (selectedElementId === visualSelectorId) {
331
- selectedOverlays.forEach((overlay, index) => {
332
- if (index < elements.length) {
333
- positionOverlay(overlay, elements[index]!);
334
- }
335
- });
336
- }
337
- }, 50);
338
- };
339
-
340
- // --- Layer dropdown controller ---
341
- const layerController = createLayerController({
342
- createPreviewOverlay: (element: Element) => {
343
- const overlay = createOverlay(false);
344
- overlay.style.zIndex = "9998";
345
- document.body.appendChild(overlay);
346
- positionOverlay(overlay, element);
347
- return overlay;
348
- },
349
- getSelectedElementId: () => selectedElementId,
350
- selectElement,
351
- onDeselect: notifyDeselection,
352
- });
353
-
354
- // Toggle visual edit mode
355
- const toggleVisualEditMode = (isEnabled: boolean) => {
356
- isVisualEditMode = isEnabled;
357
-
358
- if (!isEnabled) {
359
- layerController.cleanup();
360
- clearHoverOverlays();
361
- clearSelectedOverlays();
362
-
363
- currentHighlightedElements = [];
364
- selectedElementId = null;
365
- document.body.style.cursor = "default";
366
-
367
- document.removeEventListener("mouseover", handleMouseOver);
368
- document.removeEventListener("mouseout", handleMouseOut);
369
- document.removeEventListener("click", handleElementClick, true);
370
- } else {
371
- document.body.style.cursor = "crosshair";
372
- document.addEventListener("mouseover", handleMouseOver);
373
- document.addEventListener("mouseout", handleMouseOut);
374
- document.addEventListener("click", handleElementClick, true);
375
- }
376
- };
377
-
378
- // Handle scroll events to update popover position
379
- const handleScroll = () => {
380
- if (selectedElementId) {
381
- const elements = findElementsById(selectedElementId);
382
- if (elements.length > 0) {
383
- const element = elements[0];
384
- const rect = element!.getBoundingClientRect();
385
-
386
- const viewportHeight = window.innerHeight;
387
- const viewportWidth = window.innerWidth;
388
- const isInViewport =
389
- rect.top < viewportHeight &&
390
- rect.bottom > 0 &&
391
- rect.left < viewportWidth &&
392
- rect.right > 0;
393
-
394
- const elementPosition = {
395
- top: rect.top,
396
- left: rect.left,
397
- right: rect.right,
398
- bottom: rect.bottom,
399
- width: rect.width,
400
- height: rect.height,
401
- centerX: rect.left + rect.width / 2,
402
- centerY: rect.top + rect.height / 2,
403
- };
404
-
405
- window.parent.postMessage(
406
- {
407
- type: "element-position-update",
408
- position: elementPosition,
409
- isInViewport: isInViewport,
410
- visualSelectorId: selectedElementId,
411
- },
412
- "*"
413
- );
414
- }
415
- }
416
- };
417
-
418
- // Handle messages from parent window
419
- const handleMessage = (event: MessageEvent) => {
420
- const message = event.data;
421
-
422
- switch (message.type) {
423
- case "toggle-visual-edit-mode":
424
- toggleVisualEditMode(message.data.enabled);
425
- break;
426
-
427
- case "update-classes":
428
- if (message.data && message.data.classes !== undefined) {
429
- updateElementClassesAndReposition(
430
- message.data.visualSelectorId,
431
- message.data.classes
432
- );
433
- } else {
434
- console.warn(
435
- "[VisualEditAgent] Invalid update-classes message:",
436
- message
437
- );
438
- }
439
- break;
440
-
441
- case "update-attribute":
442
- if (
443
- message.data &&
444
- message.data.visualSelectorId &&
445
- message.data.attribute !== undefined &&
446
- message.data.value !== undefined
447
- ) {
448
- updateElementAttributeAndReposition(
449
- message.data.visualSelectorId,
450
- message.data.attribute,
451
- message.data.value
452
- );
453
- } else {
454
- console.warn(
455
- "[VisualEditAgent] Invalid update-attribute message:",
456
- message
457
- );
458
- }
459
- break;
460
-
461
- case "unselect-element":
462
- clearSelection();
463
- break;
464
-
465
- case "refresh-page":
466
- window.location.reload();
467
- break;
468
-
469
- case "update-content":
470
- if (message.data && message.data.content !== undefined) {
471
- updateElementContent(
472
- message.data.visualSelectorId,
473
- message.data.content
474
- );
475
- } else {
476
- console.warn(
477
- "[VisualEditAgent] Invalid update-content message:",
478
- message
479
- );
480
- }
481
- break;
482
-
483
- case "request-element-position":
484
- if (selectedElementId) {
485
- const elements = findElementsById(selectedElementId);
486
- if (elements.length > 0) {
487
- const element = elements[0];
488
- const rect = element!.getBoundingClientRect();
489
-
490
- const viewportHeight = window.innerHeight;
491
- const viewportWidth = window.innerWidth;
492
- const isInViewport =
493
- rect.top < viewportHeight &&
494
- rect.bottom > 0 &&
495
- rect.left < viewportWidth &&
496
- rect.right > 0;
497
-
498
- const elementPosition = {
499
- top: rect.top,
500
- left: rect.left,
501
- right: rect.right,
502
- bottom: rect.bottom,
503
- width: rect.width,
504
- height: rect.height,
505
- centerX: rect.left + rect.width / 2,
506
- centerY: rect.top + rect.height / 2,
507
- };
508
-
509
- window.parent.postMessage(
510
- {
511
- type: "element-position-update",
512
- position: elementPosition,
513
- isInViewport: isInViewport,
514
- visualSelectorId: selectedElementId,
515
- },
516
- "*"
517
- );
518
- }
519
- }
520
- break;
521
-
522
- case "popover-drag-state":
523
- if (message.data && message.data.isDragging !== undefined) {
524
- isPopoverDragging = message.data.isDragging;
525
- if (message.data.isDragging) {
526
- clearHoverOverlays();
527
- }
528
- }
529
- break;
530
-
531
- case "dropdown-state":
532
- if (message.data && message.data.isOpen !== undefined) {
533
- isDropdownOpen = message.data.isOpen;
534
- if (message.data.isOpen) {
535
- clearHoverOverlays();
536
- }
537
- }
538
- break;
539
-
540
- default:
541
- break;
542
- }
543
- };
544
-
545
- // Handle window resize to reposition overlays
546
- const handleResize = () => {
547
- if (selectedElementId) {
548
- const elements = findElementsById(selectedElementId);
549
- selectedOverlays.forEach((overlay, index) => {
550
- if (index < elements.length) {
551
- positionOverlay(overlay, elements[index]!);
552
- }
553
- });
554
- }
555
-
556
- if (currentHighlightedElements.length > 0) {
557
- hoverOverlays.forEach((overlay, index) => {
558
- if (index < currentHighlightedElements.length) {
559
- positionOverlay(overlay, currentHighlightedElements[index]!);
560
- }
561
- });
562
- }
563
- };
564
-
565
- // Initialize: Add IDs to elements that don't have them but have linenumbers
566
- const elementsWithLineNumber = document.querySelectorAll(
567
- "[data-linenumber]:not([data-visual-selector-id])"
568
- );
569
- elementsWithLineNumber.forEach((el, index) => {
570
- const htmlEl = el as HTMLElement;
571
- const id = `visual-id-${htmlEl.dataset.filename}-${htmlEl.dataset.linenumber}-${index}`;
572
- htmlEl.dataset.visualSelectorId = id;
573
- });
574
-
575
- // Create mutation observer to detect layout changes
576
- const mutationObserver = new MutationObserver((mutations) => {
577
- const needsUpdate = mutations.some((mutation) => {
578
- const hasVisualId = (node: Node): boolean => {
579
- if (node.nodeType === Node.ELEMENT_NODE) {
580
- const el = node as HTMLElement;
581
- if (el.dataset && el.dataset.visualSelectorId) {
582
- return true;
583
- }
584
- for (let i = 0; i < el.children.length; i++) {
585
- if (hasVisualId(el.children[i]!)) {
586
- return true;
587
- }
588
- }
589
- }
590
- return false;
591
- };
592
-
593
- const isLayoutChange =
594
- mutation.type === "attributes" &&
595
- (mutation.attributeName === "style" ||
596
- mutation.attributeName === "class" ||
597
- mutation.attributeName === "width" ||
598
- mutation.attributeName === "height");
599
-
600
- return isLayoutChange && hasVisualId(mutation.target);
601
- });
602
-
603
- if (needsUpdate) {
604
- setTimeout(handleResize, 50);
605
- }
606
- });
607
-
608
- // Set up event listeners
609
- window.addEventListener("message", handleMessage);
610
- window.addEventListener("scroll", handleScroll, true);
611
- document.addEventListener("scroll", handleScroll, true);
612
- window.addEventListener("resize", handleResize);
613
- window.addEventListener("scroll", handleResize);
614
-
615
- // Start observing DOM mutations
616
- mutationObserver.observe(document.body, {
617
- attributes: true,
618
- childList: true,
619
- subtree: true,
620
- attributeFilter: ["style", "class", "width", "height"],
621
- });
622
-
623
- // Send ready message to parent
624
- window.parent.postMessage({ type: "visual-edit-agent-ready" }, "*");
625
- }
1
+ export { setupVisualEditAgent } from "./visual-edit-agent/index.js";