@base44-preview/vite-plugin 0.2.24-pr.29.5743fec → 0.2.24-pr.36.31362a5

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 (38) hide show
  1. package/dist/injections/layer-dropdown/consts.d.ts +19 -0
  2. package/dist/injections/layer-dropdown/consts.d.ts.map +1 -0
  3. package/dist/injections/layer-dropdown/consts.js +40 -0
  4. package/dist/injections/layer-dropdown/consts.js.map +1 -0
  5. package/dist/injections/layer-dropdown/controller.d.ts +4 -0
  6. package/dist/injections/layer-dropdown/controller.d.ts.map +1 -0
  7. package/dist/injections/layer-dropdown/controller.js +88 -0
  8. package/dist/injections/layer-dropdown/controller.js.map +1 -0
  9. package/dist/injections/layer-dropdown/dropdown-ui.d.ts +13 -0
  10. package/dist/injections/layer-dropdown/dropdown-ui.d.ts.map +1 -0
  11. package/dist/injections/layer-dropdown/dropdown-ui.js +172 -0
  12. package/dist/injections/layer-dropdown/dropdown-ui.js.map +1 -0
  13. package/dist/injections/layer-dropdown/types.d.ts +26 -0
  14. package/dist/injections/layer-dropdown/types.d.ts.map +1 -0
  15. package/dist/injections/layer-dropdown/types.js +3 -0
  16. package/dist/injections/layer-dropdown/types.js.map +1 -0
  17. package/dist/injections/layer-dropdown/utils.d.ts +25 -0
  18. package/dist/injections/layer-dropdown/utils.d.ts.map +1 -0
  19. package/dist/injections/layer-dropdown/utils.js +131 -0
  20. package/dist/injections/layer-dropdown/utils.js.map +1 -0
  21. package/dist/injections/utils.d.ts +4 -5
  22. package/dist/injections/utils.d.ts.map +1 -1
  23. package/dist/injections/utils.js +12 -21
  24. package/dist/injections/utils.js.map +1 -1
  25. package/dist/injections/visual-edit-agent.d.ts.map +1 -1
  26. package/dist/injections/visual-edit-agent.js +86 -100
  27. package/dist/injections/visual-edit-agent.js.map +1 -1
  28. package/dist/statics/index.mjs +1 -1
  29. package/dist/statics/index.mjs.map +1 -1
  30. package/package.json +1 -1
  31. package/src/injections/layer-dropdown/LAYERS.md +258 -0
  32. package/src/injections/layer-dropdown/consts.ts +49 -0
  33. package/src/injections/layer-dropdown/controller.ts +109 -0
  34. package/src/injections/layer-dropdown/dropdown-ui.ts +228 -0
  35. package/src/injections/layer-dropdown/types.ts +30 -0
  36. package/src/injections/layer-dropdown/utils.ts +162 -0
  37. package/src/injections/utils.ts +18 -25
  38. package/src/injections/visual-edit-agent.ts +97 -126
@@ -1,4 +1,6 @@
1
- import { findElementsById, updateElementClasses, updateElementAttribute, collectAllowedAttributes, ALLOWED_ATTRIBUTES } from "./utils.js";
1
+ import { findElementsById, updateElementClasses, getElementSelectorId } from "./utils.js";
2
+ import { createLayerController } from "./layer-dropdown/controller.js";
3
+ import { LAYER_DROPDOWN_ATTR } from "./layer-dropdown/consts.js";
2
4
 
3
5
  export function setupVisualEditAgent() {
4
6
  // State variables (replacing React useState/useRef)
@@ -78,6 +80,75 @@ export function setupVisualEditAgent() {
78
80
  currentHighlightedElements = [];
79
81
  };
80
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
+ isTextElement,
123
+ }, "*");
124
+ };
125
+
126
+ // Select an element: create overlays, update state, notify parent
127
+ const selectElement = (element: Element): HTMLDivElement | undefined => {
128
+ const visualSelectorId = getElementSelectorId(element);
129
+
130
+ clearSelectedOverlays();
131
+
132
+ const elements = findElementsById(visualSelectorId || null);
133
+ elements.forEach((el) => {
134
+ const overlay = createOverlay(true);
135
+ document.body.appendChild(overlay);
136
+ selectedOverlays.push(overlay);
137
+ positionOverlay(overlay, el, true);
138
+ });
139
+
140
+ selectedElementId = visualSelectorId || null;
141
+ clearHoverOverlays();
142
+ notifyElementSelected(element);
143
+
144
+ return selectedOverlays[0];
145
+ };
146
+
147
+ const notifyDeselection = (): void => {
148
+ selectedElementId = null;
149
+ window.parent.postMessage({ type: "unselect-element" }, "*");
150
+ };
151
+
81
152
  // Handle mouse over event
82
153
  const handleMouseOver = (e: MouseEvent) => {
83
154
  if (!isVisualEditMode || isPopoverDragging) return;
@@ -146,6 +217,9 @@ export function setupVisualEditAgent() {
146
217
 
147
218
  const target = e.target as Element;
148
219
 
220
+ // Let layer dropdown clicks pass through without interference
221
+ if (target.closest(`[${LAYER_DROPDOWN_ATTR}]`)) return;
222
+
149
223
  // Close dropdowns when clicking anywhere in iframe if a dropdown is open
150
224
  if (isDropdownOpen) {
151
225
  e.preventDefault();
@@ -174,82 +248,13 @@ export function setupVisualEditAgent() {
174
248
  return;
175
249
  }
176
250
 
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
- // Collect allowed element attributes
220
- const attributes = collectAllowedAttributes(element, ALLOWED_ATTRIBUTES);
221
- const isTextElement = ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'a', 'label'].includes(element.tagName?.toLowerCase());
222
-
223
- // Send message to parent window with element info including position
224
- const svgElement = element as SVGElement;
225
- const elementData = {
226
- type: "element-selected",
227
- tagName: element.tagName,
228
- classes:
229
- (svgElement.className as unknown as SVGAnimatedString)?.baseVal ||
230
- element.className ||
231
- "",
232
- visualSelectorId: visualSelectorId,
233
- content: isTextElement ? (element as HTMLElement).innerText : undefined,
234
- dataSourceLocation: htmlElement.dataset.sourceLocation,
235
- isDynamicContent: htmlElement.dataset.dynamicContent === "true",
236
- linenumber: htmlElement.dataset.linenumber,
237
- filename: htmlElement.dataset.filename,
238
- position: elementPosition,
239
- attributes,
240
- isTextElement: isTextElement,
241
- };
242
- window.parent.postMessage(elementData, "*");
251
+ const selectedOverlay = selectElement(element);
252
+ layerController.attachToOverlay(selectedOverlay, element);
243
253
  };
244
254
 
245
- // Unselect the current element
246
- const unselectElement = () => {
247
- selectedOverlays.forEach((overlay) => {
248
- if (overlay && overlay.parentNode) {
249
- overlay.remove();
250
- }
251
- });
252
- selectedOverlays = [];
255
+ // Clear the current selection
256
+ const clearSelection = () => {
257
+ clearSelectedOverlays();
253
258
  selectedElementId = null;
254
259
  };
255
260
 
@@ -285,29 +290,6 @@ export function setupVisualEditAgent() {
285
290
  }, 50);
286
291
  };
287
292
 
288
- // Update element attribute by visual selector ID
289
- const updateElementAttributeAndReposition = (
290
- visualSelectorId: string,
291
- attribute: string,
292
- value: string
293
- ) => {
294
- const elements = findElementsById(visualSelectorId);
295
- if (elements.length === 0) return;
296
-
297
- updateElementAttribute(elements, attribute, value);
298
-
299
- // Reposition overlays after attribute change (e.g. image src swap can affect layout)
300
- setTimeout(() => {
301
- if (selectedElementId === visualSelectorId) {
302
- selectedOverlays.forEach((overlay, index) => {
303
- if (index < elements.length) {
304
- positionOverlay(overlay, elements[index]!);
305
- }
306
- });
307
- }
308
- }, 50);
309
- };
310
-
311
293
  // Update element content by visual selector ID
312
294
  const updateElementContent = (visualSelectorId: string, content: string) => {
313
295
  const elements = findElementsById(visualSelectorId);
@@ -331,19 +313,28 @@ export function setupVisualEditAgent() {
331
313
  }, 50);
332
314
  };
333
315
 
316
+ // --- Layer dropdown controller ---
317
+ const layerController = createLayerController({
318
+ createPreviewOverlay: (element: Element) => {
319
+ const overlay = createOverlay(false);
320
+ overlay.style.zIndex = "9998";
321
+ document.body.appendChild(overlay);
322
+ positionOverlay(overlay, element);
323
+ return overlay;
324
+ },
325
+ getSelectedElementId: () => selectedElementId,
326
+ selectElement,
327
+ onDeselect: notifyDeselection,
328
+ });
329
+
334
330
  // Toggle visual edit mode
335
331
  const toggleVisualEditMode = (isEnabled: boolean) => {
336
332
  isVisualEditMode = isEnabled;
337
333
 
338
334
  if (!isEnabled) {
335
+ layerController.cleanup();
339
336
  clearHoverOverlays();
340
-
341
- selectedOverlays.forEach((overlay) => {
342
- if (overlay && overlay.parentNode) {
343
- overlay.remove();
344
- }
345
- });
346
- selectedOverlays = [];
337
+ clearSelectedOverlays();
347
338
 
348
339
  currentHighlightedElements = [];
349
340
  selectedElementId = null;
@@ -423,28 +414,8 @@ export function setupVisualEditAgent() {
423
414
  }
424
415
  break;
425
416
 
426
- case "update-attribute":
427
- if (
428
- message.data &&
429
- message.data.visualSelectorId &&
430
- message.data.attribute !== undefined &&
431
- message.data.value !== undefined
432
- ) {
433
- updateElementAttributeAndReposition(
434
- message.data.visualSelectorId,
435
- message.data.attribute,
436
- message.data.value
437
- );
438
- } else {
439
- console.warn(
440
- "[VisualEditAgent] Invalid update-attribute message:",
441
- message
442
- );
443
- }
444
- break;
445
-
446
417
  case "unselect-element":
447
- unselectElement();
418
+ clearSelection();
448
419
  break;
449
420
 
450
421
  case "refresh-page":