@amplifyup/sdk 0.1.12 → 0.1.13

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.
@@ -283,6 +283,32 @@ function resolveAmplifyUpUrls(target) {
283
283
  };
284
284
  }
285
285
 
286
+ // src/preview.ts
287
+ function isPreviewRequest(searchParams) {
288
+ if (searchParams instanceof URLSearchParams) {
289
+ return searchParams.get("preview") === "true" || searchParams.get("visualEditor") === "true";
290
+ }
291
+ const preview = searchParams.preview;
292
+ const visualEditor = searchParams.visualEditor;
293
+ return preview === "true" || visualEditor === "true";
294
+ }
295
+ function isComposerPreview() {
296
+ if (typeof window === "undefined") return false;
297
+ if (window.__AMPLIFYUP_PREVIEW_MODE__ === true) return true;
298
+ const params = new URLSearchParams(window.location.search);
299
+ if (isPreviewRequest(params)) return true;
300
+ if (window.self !== window.top && document.referrer) {
301
+ try {
302
+ const refUrl = new URL(document.referrer);
303
+ if (refUrl.hostname === "amplifyup.ai" || refUrl.hostname.endsWith(".amplifyup.ai") || refUrl.hostname === "localhost" && refUrl.port === "5001" || refUrl.pathname.includes("/dashboard/composer") || refUrl.pathname.includes("/dashboard/routes/")) {
304
+ return true;
305
+ }
306
+ } catch {
307
+ }
308
+ }
309
+ return false;
310
+ }
311
+
286
312
  // src/index.ts
287
313
  function readPreviewQueryOverrides() {
288
314
  if (typeof window === "undefined") return {};
@@ -324,6 +350,15 @@ var AmplifyUpSDK = class {
324
350
  this.messageListener = null;
325
351
  this.mutationObserver = null;
326
352
  this.composerDragHandlers = null;
353
+ /** Last slot highlighted during Composer drag — avoid clear/re-add flicker. */
354
+ this.lastComposerDragSlot = null;
355
+ /** Consecutive miss frames before clearing highlight (anti-jitter). */
356
+ this.composerDragMissFrames = 0;
357
+ /**
358
+ * Parent overlay is driving drag via postMessage. Native iframe dragleave must
359
+ * not clear highlight — overlay takeover fires a spurious document dragleave.
360
+ */
361
+ this.composerOverlayDragActive = false;
327
362
  this.isVisualEditorMode = false;
328
363
  this.eventSelectionMode = false;
329
364
  this.eventSelectionClickHandler = null;
@@ -854,6 +889,12 @@ Available Console Commands:
854
889
  }
855
890
  throw new Error(`Failed to fetch page: ${response.statusText}`);
856
891
  }
892
+ const contentType = response.headers.get("content-type") || "";
893
+ if (!contentType.includes("application/json")) {
894
+ throw new Error(
895
+ `Layout provider returned non-JSON (${contentType || "unknown"}). Check Composer preview routing.`
896
+ );
897
+ }
857
898
  const data = await response.json();
858
899
  const pageConfig = data.page;
859
900
  if (pageConfig?.eventTracking) {
@@ -1138,6 +1179,13 @@ Available Console Commands:
1138
1179
  }
1139
1180
  return;
1140
1181
  }
1182
+ if (event.data?.type === "COMPOSER_DRAG_START") {
1183
+ this.composerOverlayDragActive = true;
1184
+ if (typeof document !== "undefined") {
1185
+ document.body.classList.add("amplifyup-composer-dragging");
1186
+ }
1187
+ return;
1188
+ }
1141
1189
  if (event.data?.type === "COMPOSER_DRAG_AT_POINT") {
1142
1190
  const { x, y } = event.data;
1143
1191
  if (typeof x === "number" && typeof y === "number") {
@@ -1153,36 +1201,72 @@ Available Console Commands:
1153
1201
  return;
1154
1202
  }
1155
1203
  if (event.data?.type === "COMPOSER_DRAG_END") {
1204
+ this.composerOverlayDragActive = false;
1156
1205
  this.clearComposerDragHighlight();
1157
1206
  return;
1158
1207
  }
1159
1208
  if (event.data?.type === "GET_ELEMENT_POSITION") {
1160
- const { componentId, slotName } = event.data;
1161
- const selector = slotName ? `[data-amplifyup-slot="${slotName}"], [data-slot-id="${slotName}"]` : `[data-amplifyup-component="${componentId}"], [data-component-id="${componentId}"]`;
1162
- console.log("[AmplifyUp SDK] Finding element position:", { selector, componentId, slotName });
1163
- const element = document.querySelector(selector);
1209
+ const { componentId, slotName, nodeId, isPageSlot } = event.data;
1210
+ let element = null;
1211
+ if (isPageSlot || slotName === "main" && !nodeId && !componentId) {
1212
+ element = document.querySelector(
1213
+ '[data-slot-source="page"]'
1214
+ );
1215
+ }
1216
+ if (!element && nodeId && slotName) {
1217
+ element = document.querySelector(
1218
+ `[data-parent-node-id="${nodeId}"][data-slot-id="${slotName}"], [data-parent-node-id="${nodeId}"][data-amplifyup-slot="${slotName}"]`
1219
+ );
1220
+ }
1221
+ if (!element && nodeId && !slotName) {
1222
+ element = document.querySelector(
1223
+ `[data-node-id="${nodeId}"]`
1224
+ );
1225
+ }
1226
+ if (!element && slotName) {
1227
+ element = document.querySelector(
1228
+ `[data-amplifyup-slot="${slotName}"], [data-slot-id="${slotName}"]`
1229
+ );
1230
+ }
1231
+ if (!element && componentId) {
1232
+ element = document.querySelector(
1233
+ `[data-amplifyup-component="${componentId}"], [data-component-id="${componentId}"]`
1234
+ );
1235
+ }
1236
+ console.log("[AmplifyUp SDK] Finding element position:", {
1237
+ componentId,
1238
+ slotName,
1239
+ nodeId,
1240
+ isPageSlot,
1241
+ found: !!element
1242
+ });
1164
1243
  if (element) {
1165
1244
  const rect = element.getBoundingClientRect();
1166
1245
  const position = {
1167
1246
  x: rect.left + rect.width / 2,
1168
- // Center of element
1169
1247
  y: rect.top - 50,
1170
- // Position above element
1171
1248
  width: rect.width,
1172
1249
  height: rect.height
1173
1250
  };
1174
- console.log("[AmplifyUp SDK] Element position calculated:", { rect, position });
1251
+ const bounds = {
1252
+ top: rect.top,
1253
+ left: rect.left,
1254
+ width: rect.width,
1255
+ height: rect.height
1256
+ };
1175
1257
  if (window.parent && window.parent !== window) {
1176
1258
  window.parent.postMessage({
1177
1259
  type: "ELEMENT_POSITION",
1178
- componentId,
1179
- slotName,
1180
- position
1260
+ componentId: componentId || null,
1261
+ slotName: slotName || null,
1262
+ nodeId: nodeId || null,
1263
+ isPageSlot: !!isPageSlot,
1264
+ position,
1265
+ bounds
1181
1266
  }, "*");
1182
- console.log("[AmplifyUp SDK] Sent ELEMENT_POSITION message");
1183
1267
  }
1184
1268
  } else {
1185
- console.warn("[AmplifyUp SDK] Element not found for selector:", selector);
1269
+ console.warn("[AmplifyUp SDK] Element not found for position request");
1186
1270
  }
1187
1271
  return;
1188
1272
  }
@@ -1297,37 +1381,148 @@ Available Console Commands:
1297
1381
  el.classList.remove("amplifyup-drag-over-slot");
1298
1382
  });
1299
1383
  document.body.classList.remove("amplifyup-drag-no-drop");
1384
+ document.body.classList.remove("amplifyup-composer-dragging");
1385
+ this.lastComposerDragSlot = null;
1386
+ this.composerDragMissFrames = 0;
1387
+ }
1388
+ /** Re-apply drag-over class only if missing (avoids classList churn / flicker). */
1389
+ ensureDragOverClass(slot) {
1390
+ if (!slot.classList.contains("amplifyup-drag-over-slot")) {
1391
+ slot.classList.add("amplifyup-drag-over-slot");
1392
+ }
1393
+ if (document.body.classList.contains("amplifyup-drag-no-drop")) {
1394
+ document.body.classList.remove("amplifyup-drag-no-drop");
1395
+ }
1300
1396
  }
1301
1397
  /**
1302
- * Hit-test a slot at iframe-local coordinates (Composer overlay drag path).
1303
- * Required for cross-origin drags: the browser blocks native drop inside the iframe.
1398
+ * Composer drag targets the innermost (most specific) slot under the cursor.
1399
+ * e.g. FullWidthGrid's main wins over a page-level main that wraps it.
1304
1400
  */
1305
- handleComposerDragAtPoint(x, y) {
1306
- if (typeof document === "undefined") return;
1401
+ resolveSlotAtPoint(x, y) {
1402
+ if (typeof document === "undefined") return null;
1307
1403
  const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
1308
- this.clearComposerDragHighlight();
1309
- const el = document.elementFromPoint(x, y)?.closest?.(slotSelector);
1310
- if (el) {
1311
- el.classList.add("amplifyup-drag-over-slot");
1312
- } else {
1404
+ const containing = [];
1405
+ document.querySelectorAll(slotSelector).forEach((node) => {
1406
+ const el = node;
1407
+ const r = el.getBoundingClientRect();
1408
+ if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) {
1409
+ containing.push(el);
1410
+ }
1411
+ });
1412
+ if (containing.length === 0) return null;
1413
+ const innermost = containing.filter(
1414
+ (el) => !containing.some((other) => other !== el && el.contains(other))
1415
+ );
1416
+ if (innermost.length === 1) return innermost[0];
1417
+ let best = innermost[0];
1418
+ let bestArea = Infinity;
1419
+ for (const el of innermost) {
1420
+ const r = el.getBoundingClientRect();
1421
+ const area = Math.max(1, r.width) * Math.max(1, r.height);
1422
+ if (area < bestArea) {
1423
+ bestArea = area;
1424
+ best = el;
1425
+ }
1426
+ }
1427
+ return best;
1428
+ }
1429
+ /** Parent layout node that owns this slot (null for page-level code main). */
1430
+ parentComponentForSlot(slotEl) {
1431
+ let componentId = slotEl.getAttribute("data-parent-component-id");
1432
+ let nodeId = slotEl.getAttribute("data-parent-node-id");
1433
+ let el = slotEl.parentElement;
1434
+ while (el && (!nodeId || !componentId)) {
1435
+ if (!nodeId && el.hasAttribute("data-node-id")) {
1436
+ nodeId = el.getAttribute("data-node-id");
1437
+ }
1438
+ if (!componentId) {
1439
+ componentId = el.getAttribute("data-amplifyup-component") || el.getAttribute("data-component-id");
1440
+ }
1441
+ if (nodeId) break;
1442
+ el = el.parentElement;
1443
+ }
1444
+ return { componentId, nodeId };
1445
+ }
1446
+ pointInRect(x, y, el, pad = 8) {
1447
+ const r = el.getBoundingClientRect();
1448
+ return x >= r.left - pad && x <= r.right + pad && y >= r.top - pad && y <= r.bottom + pad;
1449
+ }
1450
+ setComposerDragHighlight(slot, x, y) {
1451
+ if (slot && slot === this.lastComposerDragSlot) {
1452
+ this.composerDragMissFrames = 0;
1453
+ this.ensureDragOverClass(slot);
1454
+ return;
1455
+ }
1456
+ if (slot && this.lastComposerDragSlot && this.lastComposerDragSlot.contains(slot) && slot !== this.lastComposerDragSlot) {
1457
+ this.composerDragMissFrames = 0;
1458
+ this.lastComposerDragSlot.classList.remove("amplifyup-drag-over-slot");
1459
+ this.lastComposerDragSlot = slot;
1460
+ this.ensureDragOverClass(slot);
1461
+ return;
1462
+ }
1463
+ if (this.lastComposerDragSlot && typeof x === "number" && typeof y === "number" && this.pointInRect(x, y, this.lastComposerDragSlot)) {
1464
+ if (!slot || slot.contains(this.lastComposerDragSlot) || slot === this.lastComposerDragSlot) {
1465
+ this.composerDragMissFrames = 0;
1466
+ this.ensureDragOverClass(this.lastComposerDragSlot);
1467
+ return;
1468
+ }
1469
+ }
1470
+ if (slot) {
1471
+ this.composerDragMissFrames = 0;
1472
+ if (this.lastComposerDragSlot && this.lastComposerDragSlot !== slot) {
1473
+ this.lastComposerDragSlot.classList.remove("amplifyup-drag-over-slot");
1474
+ }
1475
+ this.lastComposerDragSlot = slot;
1476
+ this.ensureDragOverClass(slot);
1477
+ return;
1478
+ }
1479
+ this.composerDragMissFrames += 1;
1480
+ if (this.lastComposerDragSlot && this.composerDragMissFrames < 8) {
1481
+ this.ensureDragOverClass(this.lastComposerDragSlot);
1482
+ return;
1483
+ }
1484
+ if (this.lastComposerDragSlot) {
1485
+ this.lastComposerDragSlot.classList.remove("amplifyup-drag-over-slot");
1486
+ this.lastComposerDragSlot = null;
1487
+ }
1488
+ if (!document.body.classList.contains("amplifyup-drag-no-drop")) {
1313
1489
  document.body.classList.add("amplifyup-drag-no-drop");
1314
1490
  }
1315
1491
  }
1492
+ handleComposerDragAtPoint(x, y) {
1493
+ this.composerOverlayDragActive = true;
1494
+ if (!document.body.classList.contains("amplifyup-composer-dragging")) {
1495
+ document.body.classList.add("amplifyup-composer-dragging");
1496
+ }
1497
+ this.setComposerDragHighlight(this.resolveSlotAtPoint(x, y), x, y);
1498
+ }
1499
+ postDropOnSlot(slotEl) {
1500
+ const win = window;
1501
+ if (!win.parent || win.parent === win) return;
1502
+ const slotName = slotEl.getAttribute("data-amplifyup-slot") || slotEl.getAttribute("data-slot-id");
1503
+ if (!slotName) return;
1504
+ const { componentId, nodeId } = this.parentComponentForSlot(slotEl);
1505
+ const isEmpty = slotEl.getAttribute("data-slot-empty") === "true";
1506
+ win.parent.postMessage(
1507
+ {
1508
+ type: "DROP_ON_SLOT",
1509
+ slotName,
1510
+ slotElement: {
1511
+ path: slotEl.getAttribute("data-slot-path"),
1512
+ isEmpty,
1513
+ parentComponentId: componentId,
1514
+ parentNodeId: nodeId
1515
+ }
1516
+ },
1517
+ "*"
1518
+ );
1519
+ }
1316
1520
  handleComposerDropAtPoint(x, y) {
1317
1521
  if (typeof document === "undefined") return;
1318
- const win = window;
1319
- const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
1522
+ const htmlEl = this.resolveSlotAtPoint(x, y);
1320
1523
  this.clearComposerDragHighlight();
1321
- const htmlEl = document.elementFromPoint(x, y)?.closest?.(slotSelector);
1322
- if (!htmlEl || !win.parent || win.parent === win) return;
1323
- const slotName = htmlEl.getAttribute("data-amplifyup-slot") || htmlEl.getAttribute("data-slot-id");
1324
- if (!slotName) return;
1325
- const isEmpty = htmlEl.getAttribute("data-slot-empty") === "true";
1326
- win.parent.postMessage({
1327
- type: "DROP_ON_SLOT",
1328
- slotName,
1329
- slotElement: { path: htmlEl.getAttribute("data-slot-path"), isEmpty }
1330
- }, "*");
1524
+ if (!htmlEl) return;
1525
+ this.postDropOnSlot(htmlEl);
1331
1526
  }
1332
1527
  /**
1333
1528
  * Enable component highlighting
@@ -1355,35 +1550,25 @@ Available Console Commands:
1355
1550
  this.teardownComposerDragDrop();
1356
1551
  const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
1357
1552
  const clearDragOverState = () => {
1358
- document.querySelectorAll(`${slotSelector}.amplifyup-drag-over-slot`).forEach((el) => {
1359
- el.classList.remove("amplifyup-drag-over-slot");
1360
- });
1361
- document.body.classList.remove("amplifyup-drag-no-drop");
1553
+ this.clearComposerDragHighlight();
1362
1554
  };
1363
1555
  const dragenter = (e) => {
1364
1556
  e.preventDefault();
1365
- if (e.dataTransfer?.types?.length) {
1366
- document.body.classList.add("amplifyup-drag-no-drop");
1367
- }
1368
1557
  };
1369
1558
  const dragover = (e) => {
1370
1559
  e.preventDefault();
1371
- const target = e.target;
1372
- const slot = target?.closest?.(slotSelector);
1560
+ if (this.composerOverlayDragActive) {
1561
+ if (e.dataTransfer) e.dataTransfer.dropEffect = "copy";
1562
+ return;
1563
+ }
1564
+ const slot = this.resolveSlotAtPoint(e.clientX, e.clientY);
1373
1565
  if (e.dataTransfer) {
1374
1566
  e.dataTransfer.dropEffect = slot ? "copy" : "none";
1375
1567
  }
1376
- document.querySelectorAll(`${slotSelector}.amplifyup-drag-over-slot`).forEach((el) => {
1377
- el.classList.remove("amplifyup-drag-over-slot");
1378
- });
1379
- if (slot) {
1380
- slot.classList.add("amplifyup-drag-over-slot");
1381
- document.body.classList.remove("amplifyup-drag-no-drop");
1382
- } else {
1383
- document.body.classList.add("amplifyup-drag-no-drop");
1384
- }
1568
+ this.setComposerDragHighlight(slot, e.clientX, e.clientY);
1385
1569
  };
1386
1570
  const dragleave = (e) => {
1571
+ if (this.composerOverlayDragActive) return;
1387
1572
  const related = e.relatedTarget;
1388
1573
  if (!related || !document.body.contains(related)) {
1389
1574
  clearDragOverState();
@@ -1391,20 +1576,10 @@ Available Console Commands:
1391
1576
  };
1392
1577
  const drop = (e) => {
1393
1578
  e.preventDefault();
1394
- const target = e.target;
1395
- const slot = target?.closest?.(slotSelector);
1579
+ const slot = this.resolveSlotAtPoint(e.clientX, e.clientY);
1396
1580
  clearDragOverState();
1397
1581
  if (!slot || !this.isVisualEditorMode) return;
1398
- const slotName = slot.getAttribute("data-amplifyup-slot") || slot.getAttribute("data-slot-id");
1399
- const isEmpty = slot.getAttribute("data-slot-empty") === "true";
1400
- const win = window;
1401
- if (slotName && win.parent && win.parent !== win) {
1402
- win.parent.postMessage({
1403
- type: "DROP_ON_SLOT",
1404
- slotName,
1405
- slotElement: { path: slot.getAttribute("data-slot-path"), isEmpty }
1406
- }, "*");
1407
- }
1582
+ this.postDropOnSlot(slot);
1408
1583
  };
1409
1584
  const mouseover = (e) => {
1410
1585
  if (!this.showZonesEnabled) return;
@@ -1443,7 +1618,11 @@ Available Console Commands:
1443
1618
  document.removeEventListener("mouseover", h.mouseover, true);
1444
1619
  document.removeEventListener("mouseout", h.mouseout, true);
1445
1620
  this.composerDragHandlers = null;
1621
+ this.composerOverlayDragActive = false;
1622
+ this.lastComposerDragSlot = null;
1623
+ this.composerDragMissFrames = 0;
1446
1624
  document.body.classList.remove("amplifyup-drag-no-drop");
1625
+ document.body.classList.remove("amplifyup-composer-dragging");
1447
1626
  document.querySelectorAll("[data-slot-id].amplifyup-drag-over-slot, [data-amplifyup-slot].amplifyup-drag-over-slot").forEach((el) => {
1448
1627
  el.classList.remove("amplifyup-drag-over-slot");
1449
1628
  });
@@ -1484,21 +1663,32 @@ Available Console Commands:
1484
1663
  '[data-slot-id="main"], [data-amplifyup-slot="main"] {',
1485
1664
  " min-height: 50vh !important;",
1486
1665
  "}",
1487
- '[data-slot-id="main"][data-slot-empty="true"]::before,',
1488
- '[data-amplifyup-slot="main"][data-slot-empty="true"]::before {',
1489
- ' content: "Drop components here" !important;',
1490
- " position: absolute !important;",
1491
- " top: 50% !important; left: 50% !important;",
1492
- " transform: translate(-50%, -50%) !important;",
1493
- " font-size: 14px !important; font-weight: 500 !important;",
1494
- " color: rgba(34, 197, 94, 0.65) !important;",
1666
+ /* Single empty-state hint — Slot React label uses .amplifyup-slot-placeholder */
1667
+ ".amplifyup-slot-placeholder {",
1668
+ " display: flex !important;",
1669
+ " align-items: center !important;",
1670
+ " justify-content: center !important;",
1671
+ " min-height: inherit !important;",
1672
+ " color: rgba(34, 197, 94, 0.75) !important;",
1673
+ " font-size: 14px !important;",
1674
+ " font-weight: 500 !important;",
1495
1675
  " pointer-events: none !important;",
1496
- " white-space: nowrap !important;",
1676
+ " text-align: center !important;",
1497
1677
  "}",
1498
1678
  "[data-slot-id].amplifyup-slot-hover, [data-amplifyup-slot].amplifyup-slot-hover {",
1499
1679
  " outline-color: rgba(34, 197, 94, 1) !important;",
1500
1680
  " background: rgba(34, 197, 94, 0.06) !important;",
1501
1681
  "}",
1682
+ /* During any Composer drag, hide idle slot labels so they don't flash
1683
+ when the active drag-over class briefly changes */
1684
+ "body.amplifyup-composer-dragging .amplifyup-slot-placeholder {",
1685
+ " visibility: hidden !important;",
1686
+ " opacity: 0 !important;",
1687
+ "}",
1688
+ "body.amplifyup-composer-dragging [data-slot-id]::before,",
1689
+ "body.amplifyup-composer-dragging [data-amplifyup-slot]::before {",
1690
+ " content: none !important;",
1691
+ "}",
1502
1692
  "[data-slot-id].amplifyup-drag-over-slot, [data-amplifyup-slot].amplifyup-drag-over-slot {",
1503
1693
  " outline: 2px solid rgba(34, 197, 94, 1) !important;",
1504
1694
  " background: rgba(34, 197, 94, 0.18) !important;",
@@ -1514,7 +1704,7 @@ Available Console Commands:
1514
1704
  " color: rgb(22, 163, 74) !important;",
1515
1705
  " pointer-events: none !important;",
1516
1706
  " white-space: nowrap !important;",
1517
- " z-index: 1 !important;",
1707
+ " z-index: 2 !important;",
1518
1708
  "}",
1519
1709
  "body.amplifyup-drag-no-drop { cursor: no-drop !important; }",
1520
1710
  "body.amplifyup-drag-no-drop::before {",
@@ -1641,18 +1831,23 @@ Available Console Commands:
1641
1831
  sendSelectionMessage(element, hierarchy, isEmpty) {
1642
1832
  if (!this.isVisualEditorMode) return;
1643
1833
  const componentId = element.getAttribute("data-amplifyup-component") || element.getAttribute("data-component-id");
1644
- const slotName = element.getAttribute("data-amplifyup-slot") || element.getAttribute("data-slot-id");
1834
+ const slotName = componentId ? null : element.getAttribute("data-amplifyup-slot") || element.getAttribute("data-slot-id");
1645
1835
  const componentName = element.getAttribute("data-component-name");
1646
1836
  const hierarchyInfo = hierarchy.map((el, index) => {
1647
1837
  const elComponentId = el.getAttribute("data-amplifyup-component") || el.getAttribute("data-component-id");
1648
1838
  const elSlotName = el.getAttribute("data-amplifyup-slot") || el.getAttribute("data-slot-id");
1649
1839
  const elComponentName = el.getAttribute("data-component-name");
1840
+ const isSlot = !elComponentId && !!elSlotName;
1841
+ const isPageSlot = isSlot && el.getAttribute("data-slot-source") === "page";
1842
+ const nodeId = el.getAttribute("data-node-id") || (isSlot ? el.getAttribute("data-parent-node-id") : null);
1650
1843
  return {
1651
1844
  index,
1652
1845
  componentId: elComponentId,
1653
- componentName: elComponentName,
1654
- slotName: elSlotName,
1655
- isSlot: !!elSlotName
1846
+ componentName: isPageSlot ? "Page" : elComponentName,
1847
+ slotName: isSlot ? elSlotName : null,
1848
+ isSlot,
1849
+ isPageSlot,
1850
+ nodeId
1656
1851
  };
1657
1852
  });
1658
1853
  const rect = element.getBoundingClientRect ? element.getBoundingClientRect() : null;
@@ -1689,7 +1884,6 @@ Available Console Commands:
1689
1884
  return;
1690
1885
  }
1691
1886
  const doc = document;
1692
- const win = window;
1693
1887
  if (highlightComponents) {
1694
1888
  const componentElements = doc.querySelectorAll("[data-amplifyup-component], [data-component-id]");
1695
1889
  console.log("[AmplifyUp SDK] Found", componentElements.length, "components to highlight");
@@ -1750,52 +1944,8 @@ Available Console Commands:
1750
1944
  e.stopPropagation();
1751
1945
  this.sendSelectionMessage(htmlEl, hierarchy, isEmpty);
1752
1946
  };
1753
- const handleDrop = (e) => {
1754
- e.preventDefault();
1755
- e.stopPropagation();
1756
- htmlEl.classList.remove("amplifyup-drag-over-slot");
1757
- if (!win.parent || win.parent === win) return;
1758
- win.parent.postMessage({
1759
- type: "DROP_ON_SLOT",
1760
- slotName,
1761
- slotElement: { path: htmlEl.getAttribute("data-slot-path"), isEmpty }
1762
- }, "*");
1763
- try {
1764
- const data = JSON.parse(e.dataTransfer.getData("application/json"));
1765
- if (data.type === "component") {
1766
- win.parent.postMessage({
1767
- type: "COMPONENT_DROPPED",
1768
- componentId: data.componentId,
1769
- componentName: data.componentName,
1770
- slotName,
1771
- slotElement: { path: htmlEl.getAttribute("data-slot-path"), isEmpty }
1772
- }, "*");
1773
- }
1774
- } catch (_err) {
1775
- }
1776
- };
1777
- const handleDragOver = (e) => {
1778
- e.preventDefault();
1779
- e.stopPropagation();
1780
- e.dataTransfer.dropEffect = "copy";
1781
- htmlEl.classList.add("amplifyup-drag-over-slot");
1782
- };
1783
- const handleDragLeave = (e) => {
1784
- const related = e.relatedTarget;
1785
- if (!related || !htmlEl.contains(related)) {
1786
- htmlEl.classList.remove("amplifyup-drag-over-slot");
1787
- }
1788
- };
1789
1947
  htmlEl.addEventListener("click", handleClick);
1790
- htmlEl.addEventListener("dragover", handleDragOver);
1791
- htmlEl.addEventListener("dragleave", handleDragLeave);
1792
- htmlEl.addEventListener("drop", handleDrop);
1793
- htmlEl._amplifyupSlotHandlers = {
1794
- handleClick,
1795
- handleDragOver,
1796
- handleDragLeave,
1797
- handleDrop
1798
- };
1948
+ htmlEl._amplifyupSlotHandlers = { handleClick };
1799
1949
  });
1800
1950
  }
1801
1951
  }
@@ -2125,6 +2275,8 @@ function AmplifyRenderer({
2125
2275
  "data-slot-id": slot.slotId,
2126
2276
  "data-amplifyup-slot": slot.slotId,
2127
2277
  "data-zone-id": slot.zoneId || void 0,
2278
+ "data-parent-node-id": node.id,
2279
+ "data-parent-component-id": node.componentId,
2128
2280
  children: childrenToRender.map((child) => renderNode(child))
2129
2281
  },
2130
2282
  slot.slotId
@@ -2140,17 +2292,25 @@ function AmplifyRenderer({
2140
2292
  hasSlots: !!slotsToPass,
2141
2293
  slotKeys: slotsToPass ? Object.keys(slotsToPass) : []
2142
2294
  });
2143
- return renderComponent(
2144
- node.componentId,
2145
- node.props || {},
2146
- slotsToPass
2147
- );
2295
+ return /* @__PURE__ */ jsx("div", { "data-node-id": node.id, "data-amplifyup-node": "", children: renderComponent(node.componentId, node.props || {}, slotsToPass, {
2296
+ layoutNodeId: node.id
2297
+ }) });
2148
2298
  };
2149
- const layoutTree = pageConfig.layoutTree;
2150
- if (!layoutTree || layoutTree.length === 0) {
2299
+ const rawTree = pageConfig.layoutTree;
2300
+ const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
2301
+ if (layoutTree.length === 0) {
2151
2302
  return /* @__PURE__ */ jsx("main", { children: emptyComponent || /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "No content configured for this page." }) }) });
2152
2303
  }
2153
- return /* @__PURE__ */ jsx("main", { children: layoutTree.map((node) => /* @__PURE__ */ jsx("div", { children: renderNode(node) }, node.id)) });
2304
+ return /* @__PURE__ */ jsx("main", { children: isComposerPreview() ? /* @__PURE__ */ jsx(
2305
+ "div",
2306
+ {
2307
+ "data-slot-id": "main",
2308
+ "data-amplifyup-slot": "main",
2309
+ "data-slot-source": "page",
2310
+ "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
2311
+ children: layoutTree.map((node) => /* @__PURE__ */ jsx("div", { children: renderNode(node) }, node.id))
2312
+ }
2313
+ ) : layoutTree.map((node) => /* @__PURE__ */ jsx("div", { children: renderNode(node) }, node.id)) });
2154
2314
  }
2155
2315
 
2156
2316
  export { AmplifyRenderer };