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