@amplifyup/sdk 0.1.16 → 0.1.18

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.
package/dist/react.mjs CHANGED
@@ -366,6 +366,9 @@ var AmplifyUpSDK = class {
366
366
  this.attachedEventListeners = [];
367
367
  this.trackingIntervals = [];
368
368
  this.trackingCleanup = null;
369
+ this.componentViewObservers = [];
370
+ this.componentViewSeen = /* @__PURE__ */ new Set();
371
+ this.pageEngagementActive = false;
369
372
  this.adapter = adapter || new AWSAdapter();
370
373
  if (typeof window !== "undefined") {
371
374
  this.isVisualEditorMode = this.detectVisualEditorMode();
@@ -538,6 +541,7 @@ var AmplifyUpSDK = class {
538
541
  this.initialPageSent = true;
539
542
  const url = window.location.pathname;
540
543
  this.page(url);
544
+ this.setupPageEngagement();
541
545
  }
542
546
  }
543
547
  if (this.config?.debug && this.initialized) {
@@ -570,6 +574,168 @@ var AmplifyUpSDK = class {
570
574
  }
571
575
  this.trackingIntervals.forEach((id) => clearInterval(id));
572
576
  this.trackingIntervals = [];
577
+ this.cleanupComponentViewTracking();
578
+ this.pageEngagementActive = false;
579
+ }
580
+ /** Current page path for engagement attribution. */
581
+ currentPath() {
582
+ if (typeof window === "undefined") return "/";
583
+ return window.location.pathname || "/";
584
+ }
585
+ /**
586
+ * Automatic page-level Scroll Depth + Time on Page (dwell heartbeat).
587
+ */
588
+ setupPageEngagement() {
589
+ if (typeof window === "undefined" || typeof document === "undefined") return;
590
+ if (this.isPreviewMode() || this.pageEngagementActive) return;
591
+ this.pageEngagementActive = true;
592
+ const milestones = [25, 50, 75, 100];
593
+ const reached = /* @__PURE__ */ new Set();
594
+ let visibleMs = 0;
595
+ let visibleSince = document.visibilityState === "visible" ? Date.now() : null;
596
+ let lastDwellSecondsSent = 0;
597
+ let scrollRaf = null;
598
+ const path = () => this.currentPath();
599
+ const measureScrollPercent = () => {
600
+ const doc = document.documentElement;
601
+ const body = document.body;
602
+ const scrollTop = window.scrollY || doc.scrollTop || body?.scrollTop || 0;
603
+ const scrollHeight = Math.max(
604
+ doc.scrollHeight,
605
+ body?.scrollHeight || 0,
606
+ doc.offsetHeight,
607
+ body?.offsetHeight || 0
608
+ );
609
+ const clientHeight = window.innerHeight || doc.clientHeight || 0;
610
+ const traversable = Math.max(scrollHeight - clientHeight, 0);
611
+ if (traversable <= 0) return 100;
612
+ return Math.min(100, Math.round(scrollTop / traversable * 100));
613
+ };
614
+ const checkScroll = () => {
615
+ if (this.isPreviewMode()) return;
616
+ const pct = measureScrollPercent();
617
+ for (const milestone of milestones) {
618
+ if (pct >= milestone && !reached.has(milestone)) {
619
+ reached.add(milestone);
620
+ this.track("Scroll Depth", {
621
+ percentage: milestone,
622
+ path: path()
623
+ });
624
+ }
625
+ }
626
+ };
627
+ const onScroll = () => {
628
+ if (scrollRaf != null) return;
629
+ scrollRaf = window.requestAnimationFrame(() => {
630
+ scrollRaf = null;
631
+ checkScroll();
632
+ });
633
+ };
634
+ const accumulateVisible = () => {
635
+ if (visibleSince == null) return;
636
+ visibleMs += Date.now() - visibleSince;
637
+ visibleSince = Date.now();
638
+ };
639
+ const emitDwell = (force = false) => {
640
+ if (this.isPreviewMode()) return;
641
+ accumulateVisible();
642
+ const seconds = Math.floor(visibleMs / 1e3);
643
+ if (seconds <= 0) return;
644
+ if (!force && seconds <= lastDwellSecondsSent) return;
645
+ lastDwellSecondsSent = seconds;
646
+ this.track("Time on Page", {
647
+ seconds,
648
+ path: path()
649
+ });
650
+ };
651
+ const onVisibility = () => {
652
+ if (document.visibilityState === "visible") {
653
+ visibleSince = Date.now();
654
+ } else {
655
+ emitDwell(true);
656
+ visibleSince = null;
657
+ }
658
+ };
659
+ const onPageHide = () => {
660
+ emitDwell(true);
661
+ };
662
+ window.addEventListener("scroll", onScroll, { passive: true });
663
+ document.addEventListener("visibilitychange", onVisibility);
664
+ window.addEventListener("pagehide", onPageHide);
665
+ checkScroll();
666
+ const heartbeat = setInterval(() => {
667
+ if (document.visibilityState === "visible") {
668
+ emitDwell(false);
669
+ }
670
+ }, 15e3);
671
+ this.trackingIntervals.push(heartbeat);
672
+ const previousCleanup = this.trackingCleanup;
673
+ this.trackingCleanup = () => {
674
+ window.removeEventListener("scroll", onScroll);
675
+ document.removeEventListener("visibilitychange", onVisibility);
676
+ window.removeEventListener("pagehide", onPageHide);
677
+ if (scrollRaf != null) {
678
+ window.cancelAnimationFrame(scrollRaf);
679
+ scrollRaf = null;
680
+ }
681
+ previousCleanup?.();
682
+ this.pageEngagementActive = false;
683
+ };
684
+ if (this.config?.debug) {
685
+ console.log("[AmplifyUp SDK] Page engagement tracking enabled");
686
+ }
687
+ }
688
+ /**
689
+ * Automatic Component View when component hosts enter the viewport.
690
+ */
691
+ setupComponentViewTracking() {
692
+ if (typeof document === "undefined" || typeof IntersectionObserver === "undefined") {
693
+ return;
694
+ }
695
+ if (this.isPreviewMode()) return;
696
+ this.cleanupComponentViewTracking();
697
+ const hosts = document.querySelectorAll("[data-amplifyup-component]");
698
+ if (hosts.length === 0) {
699
+ if (this.config?.debug) {
700
+ console.log("[AmplifyUp SDK] No component hosts found for Component View");
701
+ }
702
+ return;
703
+ }
704
+ const observer = new IntersectionObserver(
705
+ (entries) => {
706
+ entries.forEach((entry) => {
707
+ if (!entry.isIntersecting) return;
708
+ const el = entry.target;
709
+ const componentId = el.getAttribute("data-amplifyup-component") || el.getAttribute("data-component-id");
710
+ if (!componentId || this.componentViewSeen.has(componentId)) {
711
+ observer.unobserve(el);
712
+ return;
713
+ }
714
+ this.componentViewSeen.add(componentId);
715
+ const componentName = el.getAttribute("data-component-name") || void 0;
716
+ this.track("Component View", {
717
+ componentId,
718
+ componentName,
719
+ path: this.currentPath()
720
+ });
721
+ observer.unobserve(el);
722
+ });
723
+ },
724
+ { threshold: 0.5 }
725
+ );
726
+ hosts.forEach((host) => observer.observe(host));
727
+ this.componentViewObservers.push(observer);
728
+ if (this.config?.debug) {
729
+ console.log(
730
+ "[AmplifyUp SDK] Component View tracking enabled for",
731
+ hosts.length,
732
+ "hosts"
733
+ );
734
+ }
735
+ }
736
+ cleanupComponentViewTracking() {
737
+ this.componentViewObservers.forEach((obs) => obs.disconnect());
738
+ this.componentViewObservers = [];
573
739
  }
574
740
  /**
575
741
  * Track a page view
@@ -609,9 +775,13 @@ var AmplifyUpSDK = class {
609
775
  instanceId,
610
776
  trackingId: this.config?.trackingId,
611
777
  url: typeof window !== "undefined" ? window.location.href : void 0,
778
+ path: properties?.path || (typeof window !== "undefined" ? window.location.pathname : void 0),
612
779
  // Timestamp is included in event payload
613
780
  ...properties
614
781
  };
782
+ if (!trackProperties.path && typeof window !== "undefined") {
783
+ trackProperties.path = window.location.pathname;
784
+ }
615
785
  this.adapter.track(eventName, trackProperties);
616
786
  }
617
787
  /**
@@ -900,6 +1070,13 @@ Available Console Commands:
900
1070
  if (pageConfig?.eventTracking) {
901
1071
  this.setupEventTracking(pageConfig.eventTracking);
902
1072
  }
1073
+ if (typeof window !== "undefined") {
1074
+ window.setTimeout(() => this.setupComponentViewTracking(), 150);
1075
+ window.setTimeout(() => {
1076
+ this.setupComponentViewTracking();
1077
+ this.refreshEventTracking();
1078
+ }, 800);
1079
+ }
903
1080
  return pageConfig;
904
1081
  }
905
1082
  /**
@@ -907,10 +1084,10 @@ Available Console Commands:
907
1084
  */
908
1085
  setupEventTracking(eventConfig) {
909
1086
  if (typeof document === "undefined") return;
910
- this.cleanupEventTracking();
911
- this.eventTrackingConfig = eventConfig;
1087
+ this.detachEventListeners();
1088
+ this.eventTrackingConfig = Array.isArray(eventConfig) ? [...eventConfig] : [];
912
1089
  if (this.config?.debug) {
913
- console.log("[AmplifyUp SDK] Setting up event tracking:", eventConfig.length, "events");
1090
+ console.log("[AmplifyUp SDK] Setting up event tracking:", this.eventTrackingConfig.length, "events");
914
1091
  }
915
1092
  if (document.readyState === "loading") {
916
1093
  document.addEventListener("DOMContentLoaded", () => this.attachEventListeners());
@@ -925,19 +1102,35 @@ Available Console Commands:
925
1102
  if (typeof document === "undefined") return;
926
1103
  this.eventTrackingConfig.forEach((eventConfig) => {
927
1104
  if (eventConfig.enabled === false) return;
1105
+ if (!eventConfig.selector) {
1106
+ if (this.config?.debug) {
1107
+ console.warn(`[AmplifyUp SDK] Event ${eventConfig.eventName} has no selector, skipping`);
1108
+ }
1109
+ return;
1110
+ }
928
1111
  let targetElements = [];
929
- if (eventConfig.selector) {
930
- try {
931
- targetElements = document.querySelectorAll(eventConfig.selector);
932
- } catch (e) {
1112
+ try {
1113
+ const escapeAttr = (value) => typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(value) : value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1114
+ const scopeRoot = eventConfig.componentId ? document.querySelector(
1115
+ `[data-amplifyup-component="${escapeAttr(eventConfig.componentId)}"], [data-component-id="${escapeAttr(eventConfig.componentId)}"]`
1116
+ ) : document;
1117
+ if (!scopeRoot) {
933
1118
  if (this.config?.debug) {
934
- console.warn(`[AmplifyUp SDK] Invalid selector: ${eventConfig.selector}`, e);
1119
+ console.log(
1120
+ `[AmplifyUp SDK] Component host not found for ${eventConfig.componentId}`
1121
+ );
935
1122
  }
936
1123
  return;
937
1124
  }
938
- } else {
1125
+ targetElements = Array.from(
1126
+ scopeRoot.querySelectorAll(eventConfig.selector)
1127
+ );
1128
+ if (scopeRoot instanceof Element && scopeRoot !== document.documentElement && scopeRoot.matches?.(eventConfig.selector)) {
1129
+ targetElements.unshift(scopeRoot);
1130
+ }
1131
+ } catch (e) {
939
1132
  if (this.config?.debug) {
940
- console.warn(`[AmplifyUp SDK] Event ${eventConfig.eventName} has no selector, skipping`);
1133
+ console.warn(`[AmplifyUp SDK] Invalid selector: ${eventConfig.selector}`, e);
941
1134
  }
942
1135
  return;
943
1136
  }
@@ -993,8 +1186,15 @@ Available Console Commands:
993
1186
  handleTrackedEvent(event, config, element) {
994
1187
  const properties = {
995
1188
  eventType: config.eventType,
996
- selector: config.selector
1189
+ selector: config.selector,
1190
+ path: this.currentPath()
997
1191
  };
1192
+ if (config.componentId) {
1193
+ properties.componentId = config.componentId;
1194
+ }
1195
+ if (config.componentName) {
1196
+ properties.componentName = config.componentName;
1197
+ }
998
1198
  if (config.properties && config.properties.length > 0) {
999
1199
  config.properties.forEach((prop) => {
1000
1200
  const dataAttrValue = element.getAttribute(`data-${prop}`);
@@ -1065,9 +1265,9 @@ Available Console Commands:
1065
1265
  element._amplifyupViewObserver = observer;
1066
1266
  }
1067
1267
  /**
1068
- * Clean up all attached event listeners
1268
+ * Detach listeners/observers without clearing the saved event config.
1069
1269
  */
1070
- cleanupEventTracking() {
1270
+ detachEventListeners() {
1071
1271
  this.attachedEventListeners.forEach(({ element, eventType, handler }) => {
1072
1272
  element.removeEventListener(eventType, handler);
1073
1273
  });
@@ -1081,6 +1281,12 @@ Available Console Commands:
1081
1281
  }
1082
1282
  });
1083
1283
  }
1284
+ }
1285
+ /**
1286
+ * Clean up all attached event listeners and clear config
1287
+ */
1288
+ cleanupEventTracking() {
1289
+ this.detachEventListeners();
1084
1290
  this.eventTrackingConfig = [];
1085
1291
  if (this.config?.debug) {
1086
1292
  console.log("[AmplifyUp SDK] Cleaned up event tracking");
@@ -1090,11 +1296,13 @@ Available Console Commands:
1090
1296
  * Manually trigger event tracking setup (useful after dynamic content loads)
1091
1297
  */
1092
1298
  refreshEventTracking() {
1093
- if (this.eventTrackingConfig.length > 0) {
1094
- this.cleanupEventTracking();
1095
- const config = [...this.eventTrackingConfig];
1096
- this.eventTrackingConfig = config;
1097
- this.attachEventListeners();
1299
+ if (this.eventTrackingConfig.length === 0) return;
1300
+ const config = [...this.eventTrackingConfig];
1301
+ this.detachEventListeners();
1302
+ this.eventTrackingConfig = config;
1303
+ this.attachEventListeners();
1304
+ if (this.config?.debug) {
1305
+ console.log("[AmplifyUp SDK] Refreshed event tracking:", config.length, "events");
1098
1306
  }
1099
1307
  }
1100
1308
  /** Origins allowed to send Composer postMessage commands to the SDK. */
@@ -1205,6 +1413,10 @@ Available Console Commands:
1205
1413
  this.clearComposerDragHighlight();
1206
1414
  return;
1207
1415
  }
1416
+ if (event.data?.type === "CLEAR_SELECTION") {
1417
+ this.clearComposerSelection();
1418
+ return;
1419
+ }
1208
1420
  if (event.data?.type === "GET_ELEMENT_POSITION") {
1209
1421
  const { componentId, slotName, nodeId, isPageSlot } = event.data;
1210
1422
  let element = null;
@@ -1246,6 +1458,7 @@ Available Console Commands:
1246
1458
  found: !!element
1247
1459
  });
1248
1460
  if (element) {
1461
+ this.markComposerSelection(element);
1249
1462
  const rect = element.getBoundingClientRect();
1250
1463
  const position = {
1251
1464
  x: rect.left + rect.width / 2,
@@ -1313,6 +1526,7 @@ Available Console Commands:
1313
1526
  break;
1314
1527
  case "SHOW_COMPONENT_TOOLTIP":
1315
1528
  case "HIDE_ALL_TOOLTIPS":
1529
+ this.clearComposerSelection();
1316
1530
  break;
1317
1531
  case "ENABLE_EVENT_SELECTION":
1318
1532
  console.log("[AmplifyUp SDK] Enable event selection mode:", message.enabled);
@@ -1550,29 +1764,46 @@ Available Console Commands:
1550
1764
  */
1551
1765
  enableHighlighting(componentRegistry, highlightComponents, showZones) {
1552
1766
  if (typeof document === "undefined") return;
1767
+ const previouslySelected = Array.from(
1768
+ document.querySelectorAll(".amplifyup-selected")
1769
+ );
1553
1770
  this.componentRegistry = componentRegistry;
1554
1771
  this.highlightingEnabled = true;
1555
1772
  this.highlightComponentsEnabled = highlightComponents;
1556
1773
  this.showZonesEnabled = showZones;
1557
- this.disableHighlighting();
1774
+ this.disableHighlighting({ clearSelection: false });
1558
1775
  this.highlightingEnabled = true;
1559
1776
  this.injectComposerHighlightStyles(highlightComponents, showZones);
1560
1777
  if (highlightComponents || showZones) {
1561
1778
  this.applyComponentHighlights(highlightComponents, showZones);
1562
1779
  this.setupMutationObserver();
1563
- }
1564
- if (showZones) {
1565
1780
  this.setupComposerDragDrop();
1566
1781
  }
1782
+ previouslySelected.forEach((el) => {
1783
+ if (document.contains(el)) {
1784
+ el.classList.add("amplifyup-selected");
1785
+ }
1786
+ });
1567
1787
  }
1568
1788
  /** Document-level drag/drop for cross-iframe drags from Composer sidebar. */
1569
1789
  setupComposerDragDrop() {
1570
1790
  if (typeof document === "undefined") return;
1571
1791
  this.teardownComposerDragDrop();
1572
1792
  const slotSelector = "[data-slot-id], [data-amplifyup-slot]";
1793
+ const componentSelector = "[data-amplifyup-component], [data-component-id]";
1573
1794
  const clearDragOverState = () => {
1574
1795
  this.clearComposerDragHighlight();
1575
1796
  };
1797
+ const clearComponentHover = () => {
1798
+ document.querySelectorAll(".amplifyup-component-hover").forEach((el) => {
1799
+ el.classList.remove("amplifyup-component-hover");
1800
+ });
1801
+ };
1802
+ const clearSlotHover = () => {
1803
+ document.querySelectorAll(`${slotSelector}.amplifyup-slot-hover`).forEach((el) => {
1804
+ el.classList.remove("amplifyup-slot-hover");
1805
+ });
1806
+ };
1576
1807
  const dragenter = (e) => {
1577
1808
  e.preventDefault();
1578
1809
  };
@@ -1603,31 +1834,59 @@ Available Console Commands:
1603
1834
  this.postDropOnSlot(slot);
1604
1835
  };
1605
1836
  const mouseover = (e) => {
1606
- if (!this.showZonesEnabled) return;
1837
+ if (!this.highlightComponentsEnabled && !this.showZonesEnabled) return;
1607
1838
  const target = e.target;
1608
- const slot = target?.closest?.(slotSelector);
1609
- if (!slot) return;
1610
- document.querySelectorAll(`${slotSelector}.amplifyup-slot-hover`).forEach((el) => {
1611
- el.classList.remove("amplifyup-slot-hover");
1612
- });
1613
- slot.classList.add("amplifyup-slot-hover");
1839
+ if (!target?.closest) return;
1840
+ const component = target.closest(componentSelector);
1841
+ const slot = target.closest(slotSelector);
1842
+ if (this.highlightComponentsEnabled && component) {
1843
+ if (!component.classList.contains("amplifyup-component-hover")) {
1844
+ clearComponentHover();
1845
+ component.classList.add("amplifyup-component-hover");
1846
+ }
1847
+ if (slot && !component.contains(slot)) {
1848
+ clearSlotHover();
1849
+ }
1850
+ return;
1851
+ }
1852
+ clearComponentHover();
1853
+ if (this.showZonesEnabled && slot) {
1854
+ if (!slot.classList.contains("amplifyup-slot-hover")) {
1855
+ clearSlotHover();
1856
+ slot.classList.add("amplifyup-slot-hover");
1857
+ }
1858
+ }
1614
1859
  };
1615
1860
  const mouseout = (e) => {
1616
- if (!this.showZonesEnabled) return;
1861
+ if (!this.highlightComponentsEnabled && !this.showZonesEnabled) return;
1617
1862
  const related = e.relatedTarget;
1618
- if (!related?.closest?.(slotSelector)) {
1619
- document.querySelectorAll(`${slotSelector}.amplifyup-slot-hover`).forEach((el) => {
1620
- el.classList.remove("amplifyup-slot-hover");
1621
- });
1863
+ if (this.highlightComponentsEnabled) {
1864
+ if (!related?.closest?.(componentSelector)) {
1865
+ clearComponentHover();
1866
+ }
1867
+ }
1868
+ if (this.showZonesEnabled) {
1869
+ if (!related?.closest?.(slotSelector)) {
1870
+ clearSlotHover();
1871
+ }
1622
1872
  }
1623
1873
  };
1624
- document.addEventListener("dragenter", dragenter, false);
1625
- document.addEventListener("dragover", dragover, false);
1626
- document.addEventListener("dragleave", dragleave, false);
1627
- document.addEventListener("drop", drop, false);
1628
1874
  document.addEventListener("mouseover", mouseover, true);
1629
1875
  document.addEventListener("mouseout", mouseout, true);
1630
- this.composerDragHandlers = { dragenter, dragover, dragleave, drop, mouseover, mouseout };
1876
+ if (this.showZonesEnabled) {
1877
+ document.addEventListener("dragenter", dragenter, false);
1878
+ document.addEventListener("dragover", dragover, false);
1879
+ document.addEventListener("dragleave", dragleave, false);
1880
+ document.addEventListener("drop", drop, false);
1881
+ }
1882
+ this.composerDragHandlers = {
1883
+ dragenter,
1884
+ dragover,
1885
+ dragleave,
1886
+ drop,
1887
+ mouseover,
1888
+ mouseout
1889
+ };
1631
1890
  }
1632
1891
  teardownComposerDragDrop() {
1633
1892
  if (!this.composerDragHandlers || typeof document === "undefined") return;
@@ -1650,6 +1909,20 @@ Available Console Commands:
1650
1909
  document.querySelectorAll("[data-slot-id].amplifyup-slot-hover, [data-amplifyup-slot].amplifyup-slot-hover").forEach((el) => {
1651
1910
  el.classList.remove("amplifyup-slot-hover");
1652
1911
  });
1912
+ document.querySelectorAll(".amplifyup-component-hover").forEach((el) => {
1913
+ el.classList.remove("amplifyup-component-hover");
1914
+ });
1915
+ }
1916
+ clearComposerSelection() {
1917
+ if (typeof document === "undefined") return;
1918
+ document.querySelectorAll(
1919
+ "[data-slot-id].amplifyup-selected, [data-amplifyup-slot].amplifyup-selected, [data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected"
1920
+ ).forEach((el) => el.classList.remove("amplifyup-selected"));
1921
+ }
1922
+ markComposerSelection(element) {
1923
+ if (typeof document === "undefined") return;
1924
+ this.clearComposerSelection();
1925
+ element.classList.add("amplifyup-selected");
1653
1926
  }
1654
1927
  /** Visual outlines for Composer (direct iframe path — no preview-frame proxy). */
1655
1928
  injectComposerHighlightStyles(highlightComponents, showZones) {
@@ -1657,16 +1930,29 @@ Available Console Commands:
1657
1930
  if (!highlightComponents && !showZones) return;
1658
1931
  const existing = document.getElementById("amplifyup-preview-highlights");
1659
1932
  if (existing) existing.remove();
1933
+ const primary = "hsl(82 92% 42%)";
1660
1934
  const lines = [];
1661
1935
  if (highlightComponents) {
1662
1936
  lines.push(
1663
1937
  "[data-amplifyup-component], [data-component-id] {",
1664
- " outline: 1px dashed rgba(59, 130, 246, 0.8) !important;",
1665
- " outline-offset: 2px !important;",
1666
1938
  " cursor: pointer !important;",
1667
1939
  "}",
1668
- "[data-amplifyup-component]:hover, [data-component-id]:hover {",
1669
- " outline-color: rgba(59, 130, 246, 1) !important;",
1940
+ "[data-amplifyup-component].amplifyup-selected, [data-component-id].amplifyup-selected {",
1941
+ ` outline: 2px solid ${primary} !important;`,
1942
+ " outline-offset: -2px !important;",
1943
+ " box-shadow: inset 0 0 0 1px hsl(82 92% 42% / 0.25) !important;",
1944
+ "}",
1945
+ "[data-amplifyup-component].amplifyup-component-hover:not(.amplifyup-selected),",
1946
+ "[data-component-id].amplifyup-component-hover:not(.amplifyup-selected) {",
1947
+ ` outline: 2px solid ${primary} !important;`,
1948
+ " outline-offset: -2px !important;",
1949
+ "}"
1950
+ );
1951
+ }
1952
+ if (highlightComponents || showZones) {
1953
+ lines.push(
1954
+ "[data-slot-id].amplifyup-selected, [data-amplifyup-slot].amplifyup-selected {",
1955
+ " background-color: rgba(245, 245, 220, 0.35) !important;",
1670
1956
  "}"
1671
1957
  );
1672
1958
  }
@@ -1801,8 +2087,9 @@ Available Console Commands:
1801
2087
  /**
1802
2088
  * Disable component highlighting
1803
2089
  */
1804
- disableHighlighting() {
2090
+ disableHighlighting(opts) {
1805
2091
  if (typeof document === "undefined") return;
2092
+ const clearSelection = opts?.clearSelection !== false;
1806
2093
  this.highlightingEnabled = false;
1807
2094
  this.teardownComposerDragDrop();
1808
2095
  if (this.mutationObserver) {
@@ -1831,10 +2118,10 @@ Available Console Commands:
1831
2118
  delete htmlEl._amplifyupSlotHandlers;
1832
2119
  htmlEl.classList.remove("amplifyup-slot-highlight");
1833
2120
  });
2121
+ if (clearSelection) {
2122
+ this.clearComposerSelection();
2123
+ }
1834
2124
  }
1835
- /**
1836
- * Build component hierarchy for ancestor selection
1837
- */
1838
2125
  buildComponentHierarchy(element) {
1839
2126
  const hierarchy = [];
1840
2127
  let current = element;
@@ -1898,6 +2185,7 @@ Available Console Commands:
1898
2185
  window.parent.postMessage(message, "*");
1899
2186
  console.log("[AmplifyUp SDK] Sent selection message:", message);
1900
2187
  }
2188
+ this.markComposerSelection(element);
1901
2189
  }
1902
2190
  /**
1903
2191
  * Send component tree to orchestrator
@@ -2007,6 +2295,7 @@ function getSDK(adapter) {
2007
2295
  return sdkInstance;
2008
2296
  }
2009
2297
  var trackContentView = (contentId, contentType, properties) => getSDK().trackContentView(contentId, contentType, properties);
2298
+ var refreshEventTracking = () => getSDK().refreshEventTracking();
2010
2299
  getSDK();
2011
2300
  function AmplifyRenderer({
2012
2301
  renderComponent,
@@ -2047,6 +2336,32 @@ function AmplifyRenderer({
2047
2336
  });
2048
2337
  }
2049
2338
  }, [pageConfig]);
2339
+ useEffect(() => {
2340
+ if (!pageConfig?.eventTracking?.length) return;
2341
+ const sdk = getSDK();
2342
+ if (!sdk.isInitialized()) return;
2343
+ sdk.setupEventTracking(pageConfig.eventTracking);
2344
+ const t1 = window.setTimeout(() => {
2345
+ sdk.setupComponentViewTracking();
2346
+ refreshEventTracking();
2347
+ }, 200);
2348
+ const t2 = window.setTimeout(() => {
2349
+ sdk.setupComponentViewTracking();
2350
+ refreshEventTracking();
2351
+ }, 1e3);
2352
+ return () => {
2353
+ window.clearTimeout(t1);
2354
+ window.clearTimeout(t2);
2355
+ };
2356
+ }, [pageConfig?.id]);
2357
+ useEffect(() => {
2358
+ if (!pageConfig) return;
2359
+ const t = window.setTimeout(() => {
2360
+ getSDK().setupComponentViewTracking();
2361
+ refreshEventTracking();
2362
+ }, 100);
2363
+ return () => window.clearTimeout(t);
2364
+ }, [variantCache, pageConfig?.id]);
2050
2365
  useEffect(() => {
2051
2366
  const isVisualEditorMode = () => {
2052
2367
  if (typeof window === "undefined") return false;