@elementor/editor-audits 4.5.0-1150 → 4.5.0-1154

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/index.d.mts CHANGED
@@ -44,6 +44,7 @@ type AuditViolation = {
44
44
  ctaLabel?: string;
45
45
  secondaryCtaLabel?: string;
46
46
  secondaryCtaUrl?: string;
47
+ appInstalled?: boolean;
47
48
  };
48
49
  type PageContextResponse = {
49
50
  post_title: string | null;
package/dist/index.d.ts CHANGED
@@ -44,6 +44,7 @@ type AuditViolation = {
44
44
  ctaLabel?: string;
45
45
  secondaryCtaLabel?: string;
46
46
  secondaryCtaUrl?: string;
47
+ appInstalled?: boolean;
47
48
  };
48
49
  type PageContextResponse = {
49
50
  post_title: string | null;
package/dist/index.js CHANGED
@@ -38,7 +38,7 @@ module.exports = __toCommonJS(index_exports);
38
38
 
39
39
  // src/init.ts
40
40
  var import_editor_floating_panels6 = require("@elementor/editor-floating-panels");
41
- var import_store7 = require("@elementor/store");
41
+ var import_store9 = require("@elementor/store");
42
42
 
43
43
  // src/editor-app-bar.tsx
44
44
  var import_editor_app_bar = require("@elementor/editor-app-bar");
@@ -130,7 +130,7 @@ var import_editor_floating_panels5 = require("@elementor/editor-floating-panels"
130
130
 
131
131
  // src/components/audit-panel.tsx
132
132
  var React21 = __toESM(require("react"));
133
- var import_editor_elements6 = require("@elementor/editor-elements");
133
+ var import_editor_elements7 = require("@elementor/editor-elements");
134
134
  var import_editor_floating_panels4 = require("@elementor/editor-floating-panels");
135
135
  var import_ui20 = require("@elementor/ui");
136
136
  var import_i18n17 = require("@wordpress/i18n");
@@ -147,6 +147,16 @@ var FEEDBACK_CLICKED_EVENT = "audit_feedback_clicked";
147
147
  var FEEDBACK_SENT_EVENT = "audit_feedback_sent";
148
148
  var FEEDBACK_CANCELLED_EVENT = "audit_feedback_cancelled";
149
149
  var FEEDBACK_CLOSED_EVENT = "audit_feedback_closed";
150
+ var PANEL_VIEWED_EVENT = "page_audit_panel_viewed";
151
+ var PANEL_CLOSED_EVENT = "page_audit_panel_closed";
152
+ var RUN_STARTED_EVENT = "page_audit_run_started";
153
+ var RUN_COMPLETED_EVENT = "page_audit_run_completed";
154
+ var FINDING_CLICKED_EVENT = "page_audit_finding_clicked";
155
+ var TRACKING_WINDOW_NAME = "page_audit";
156
+ var TRACKING_TARGET_LOCATION = "panel";
157
+ var TRACKING_LOCATION_L1 = "audit_panel";
158
+ var FIRST_OPEN_MESSAGE_KEY = "page-audit-panel-opened";
159
+ var AUDIT_ID_PREFIX = "audits/";
150
160
  var ALL_CATEGORIES = [
151
161
  "best-practices",
152
162
  "seo",
@@ -664,13 +674,125 @@ function persistReport(documentId, report) {
664
674
  (0, import_session.setSessionStorageItem)(getStorageKey(documentId), report);
665
675
  }
666
676
 
677
+ // src/utils/tracking.ts
678
+ var import_events = require("@elementor/events");
679
+
680
+ // src/utils/tracking-names.ts
681
+ function toTrackingSeverity(severity) {
682
+ return severity === "info" ? "suggestion" : severity;
683
+ }
684
+ function toCheckName(auditId) {
685
+ return auditId.replace(AUDIT_ID_PREFIX, "").replace(/-/g, "_");
686
+ }
687
+
688
+ // src/utils/build-run-summary.ts
689
+ var SEVERITY_PRIORITY = ["error", "warning", "suggestion"];
690
+ function buildRunSummary(report) {
691
+ const requiredFixes = report.auditResults.filter(({ audit: audit25, result }) => result.status === "fail" && isScoredAudit(audit25)).map(({ audit: audit25 }) => ({ check: toCheckName(audit25.id), severity: toTrackingSeverity(audit25.severity) }));
692
+ const countBySeverity = (severity) => requiredFixes.filter((fix) => fix.severity === severity).length;
693
+ const highestSeverity = SEVERITY_PRIORITY.find((severity) => countBySeverity(severity) > 0);
694
+ return {
695
+ state: highestSeverity ?? "success",
696
+ metadata: {
697
+ score: report.overall,
698
+ fix_count: requiredFixes.length,
699
+ error_count: countBySeverity("error"),
700
+ warning_count: countBySeverity("warning"),
701
+ suggestion_count: countBySeverity("suggestion"),
702
+ required_fixes: requiredFixes
703
+ }
704
+ };
705
+ }
706
+
707
+ // src/utils/tracking.ts
708
+ var dispatch = (eventName, payload) => {
709
+ (0, import_events.getMixpanel)().dispatchEvent?.(eventName, {
710
+ window_name: TRACKING_WINDOW_NAME,
711
+ target_location: TRACKING_TARGET_LOCATION,
712
+ location_l1: TRACKING_LOCATION_L1,
713
+ ...payload
714
+ });
715
+ };
716
+ var trackPanelViewed = ({
717
+ hasPriorReport,
718
+ isFirstOpen
719
+ }) => {
720
+ dispatch(PANEL_VIEWED_EVENT, {
721
+ interaction_type: "view",
722
+ target_type: "panel",
723
+ target_name: "page_audit_panel",
724
+ interaction_result: "panel_viewed",
725
+ metadata: { has_prior_report: hasPriorReport, is_first_open: isFirstOpen }
726
+ });
727
+ };
728
+ var trackPanelClosed = () => {
729
+ dispatch(PANEL_CLOSED_EVENT, {
730
+ interaction_type: "click",
731
+ target_type: "button",
732
+ target_name: "close",
733
+ interaction_result: "panel_closed"
734
+ });
735
+ };
736
+ var trackRunStarted = (trigger) => {
737
+ dispatch(RUN_STARTED_EVENT, {
738
+ interaction_type: "click",
739
+ target_type: "button",
740
+ target_name: trigger,
741
+ interaction_result: "run_initiated"
742
+ });
743
+ };
744
+ var trackRunOutcome = (interactionResult, details) => {
745
+ dispatch(RUN_COMPLETED_EVENT, {
746
+ interaction_type: "view",
747
+ target_type: "report",
748
+ target_name: "audit_report",
749
+ interaction_result: interactionResult,
750
+ ...details
751
+ });
752
+ };
753
+ var trackRunCompleted = (report) => {
754
+ const { state, metadata } = buildRunSummary(report);
755
+ trackRunOutcome("run_completed", { state, metadata });
756
+ };
757
+ var trackRunFailed = () => {
758
+ trackRunOutcome("run_failed", {});
759
+ };
760
+ var trackFixWithApp = (audit25, violation, locationL2) => {
761
+ if (violation.appInstalled === void 0) {
762
+ return;
763
+ }
764
+ trackFindingClicked({
765
+ audit: audit25,
766
+ locationL2,
767
+ actionType: "fix_with_app",
768
+ interactionResult: "app_opened",
769
+ appInstalled: violation.appInstalled
770
+ });
771
+ };
772
+ var trackFindingClicked = (click) => {
773
+ const { audit: audit25, locationL2, actionType, interactionResult } = click;
774
+ dispatch(FINDING_CLICKED_EVENT, {
775
+ interaction_type: "click",
776
+ target_type: "row",
777
+ target_name: "finding_row",
778
+ action_type: actionType,
779
+ target_value: toCheckName(audit25.id),
780
+ interaction_result: interactionResult,
781
+ state: toTrackingSeverity(audit25.severity),
782
+ location_l2: locationL2,
783
+ ...click.actionType === "fix_with_app" && {
784
+ app_status: click.appInstalled ? "installed" : "not_installed"
785
+ }
786
+ });
787
+ };
788
+
667
789
  // src/hooks/use-audit-report.ts
668
790
  function useAuditReport() {
669
791
  const status = (0, import_store4.__useSelector)((state) => selectStatus(state));
670
792
  const report = (0, import_store4.__useSelector)((state) => selectReport(state));
671
793
  const error = (0, import_store4.__useSelector)((state) => selectError(state));
672
794
  const isStale = (0, import_store4.__useSelector)((state) => selectIsStale(state));
673
- const dispatch2 = (0, import_store4.__useDispatch)();
795
+ const dispatch3 = (0, import_store4.__useDispatch)();
674
796
  const documentId = (0, import_editor_elements3.getHostDocumentId)() ?? 0;
675
797
  (0, import_react.useEffect)(() => {
676
798
  if (!documentId || report?.documentId === documentId) {
@@ -678,35 +800,63 @@ function useAuditReport() {
678
800
  }
679
801
  const persisted = getPersistedReport(documentId);
680
802
  if (persisted) {
681
- dispatch2(slice.actions.reportRestored(persisted));
803
+ dispatch3(slice.actions.reportRestored(persisted));
682
804
  } else if (report) {
683
- dispatch2(slice.actions.reportCleared());
805
+ dispatch3(slice.actions.reportCleared());
684
806
  }
685
- }, [documentId, report, dispatch2]);
686
- const run = async (documentIdToRun) => {
687
- dispatch2(slice.actions.runStarted());
807
+ }, [documentId, report, dispatch3]);
808
+ const run = async (documentIdToRun, trigger) => {
809
+ dispatch3(slice.actions.runStarted());
810
+ trackRunStarted(trigger);
688
811
  try {
689
812
  const nextReport = await runPageAudit(documentIdToRun);
690
- dispatch2(slice.actions.runSucceeded(nextReport));
813
+ dispatch3(slice.actions.runSucceeded(nextReport));
691
814
  persistReport(documentIdToRun, nextReport);
815
+ trackRunCompleted(nextReport);
692
816
  } catch (e) {
693
817
  if (e instanceof SessionExpiredError) {
694
- dispatch2(slice.actions.runAborted());
818
+ dispatch3(slice.actions.runAborted());
819
+ trackRunFailed();
695
820
  return;
696
821
  }
697
- dispatch2(slice.actions.runFailed(e instanceof Error ? e.message : "Unknown error"));
822
+ dispatch3(slice.actions.runFailed(e instanceof Error ? e.message : "Unknown error"));
823
+ trackRunFailed();
698
824
  }
699
825
  };
700
826
  return { status, report, error, isStale, run };
701
827
  }
702
828
 
829
+ // src/hooks/use-track-panel-viewed.ts
830
+ var import_react2 = require("react");
831
+ var import_editor_current_user = require("@elementor/editor-current-user");
832
+ var import_editor_elements4 = require("@elementor/editor-elements");
833
+ var import_store6 = require("@elementor/store");
834
+ function useTrackPanelViewed() {
835
+ const { data: currentUser } = (0, import_editor_current_user.useCurrentUser)();
836
+ const [isFirstOpenMessageSuppressed, suppressFirstOpenMessage] = (0, import_editor_current_user.useSuppressedMessage)(FIRST_OPEN_MESSAGE_KEY);
837
+ const report = (0, import_store6.__useSelector)((state) => selectReport(state));
838
+ const [hasPriorReport] = (0, import_react2.useState)(() => {
839
+ const documentId = (0, import_editor_elements4.getHostDocumentId)() ?? 0;
840
+ return Boolean(report) || Boolean(documentId && getPersistedReport(documentId));
841
+ });
842
+ const hasTracked = (0, import_react2.useRef)(false);
843
+ (0, import_react2.useEffect)(() => {
844
+ if (!currentUser || hasTracked.current) {
845
+ return;
846
+ }
847
+ hasTracked.current = true;
848
+ trackPanelViewed({ hasPriorReport, isFirstOpen: !isFirstOpenMessageSuppressed });
849
+ suppressFirstOpenMessage();
850
+ }, [currentUser, hasPriorReport, isFirstOpenMessageSuppressed, suppressFirstOpenMessage]);
851
+ }
852
+
703
853
  // src/components/audit-feedback.tsx
704
854
  var React2 = __toESM(require("react"));
705
- var import_react2 = require("react");
855
+ var import_react3 = require("react");
706
856
  var import_editor_floating_panels = require("@elementor/editor-floating-panels");
707
857
  var import_editor_notifications = require("@elementor/editor-notifications");
708
858
  var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
709
- var import_events = require("@elementor/events");
859
+ var import_events2 = require("@elementor/events");
710
860
  var import_http_client2 = require("@elementor/http-client");
711
861
  var import_icons2 = require("@elementor/icons");
712
862
  var import_ui2 = require("@elementor/ui");
@@ -729,10 +879,10 @@ var notifyError = () => (0, import_editor_notifications.notify)({
729
879
  message: (0, import_i18n2.__)("Something went wrong. Please try sending your feedback again.", "elementor")
730
880
  });
731
881
  function AuditFeedback() {
732
- const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
733
- const [feedbackText, setFeedbackText] = (0, import_react2.useState)("");
734
- const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
735
- const { dispatchEvent: trackEvent = (...args) => void args } = (0, import_events.useMixpanel)();
882
+ const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
883
+ const [feedbackText, setFeedbackText] = (0, import_react3.useState)("");
884
+ const [isSubmitting, setIsSubmitting] = (0, import_react3.useState)(false);
885
+ const { dispatchEvent: trackEvent = (...args) => void args } = (0, import_events2.useMixpanel)();
736
886
  const panelZIndex = (0, import_editor_floating_panels.useFloatingPanelZIndex)(AUDIT_PANEL_ID);
737
887
  if (!(0, import_editor_v1_adapters.isExperimentActive)(FEEDBACK_EXPERIMENT_NAME)) {
738
888
  return null;
@@ -870,7 +1020,7 @@ function WelcomePage() {
870
1020
 
871
1021
  // src/components/report-shell.tsx
872
1022
  var React19 = __toESM(require("react"));
873
- var import_react5 = require("react");
1023
+ var import_react6 = require("react");
874
1024
  var import_ui18 = require("@elementor/ui");
875
1025
 
876
1026
  // src/components/pages/category-page.tsx
@@ -879,9 +1029,9 @@ var import_ui12 = require("@elementor/ui");
879
1029
  var import_i18n11 = require("@wordpress/i18n");
880
1030
 
881
1031
  // src/hooks/use-single-expanded-card.ts
882
- var import_react3 = require("react");
1032
+ var import_react4 = require("react");
883
1033
  function useSingleExpandedCard(initialId = null) {
884
- const [expandedId, setExpandedId] = (0, import_react3.useState)(initialId);
1034
+ const [expandedId, setExpandedId] = (0, import_react4.useState)(initialId);
885
1035
  const toggle = (id) => {
886
1036
  setExpandedId((current) => current === id ? null : id);
887
1037
  };
@@ -900,12 +1050,12 @@ var CATEGORY_ICONS = {
900
1050
 
901
1051
  // src/components/status-section.tsx
902
1052
  var React6 = __toESM(require("react"));
903
- var import_react4 = require("react");
1053
+ var import_react5 = require("react");
904
1054
  var import_icons4 = require("@elementor/icons");
905
1055
  var import_ui6 = require("@elementor/ui");
906
1056
  var import_i18n6 = require("@wordpress/i18n");
907
1057
  function StatusSection({ label, count, color = "default", defaultExpanded = false, children }) {
908
- const [expanded, setExpanded] = (0, import_react4.useState)(defaultExpanded);
1058
+ const [expanded, setExpanded] = (0, import_react5.useState)(defaultExpanded);
909
1059
  if (React6.Children.count(children) === 0) {
910
1060
  return null;
911
1061
  }
@@ -948,21 +1098,21 @@ function SubpageHeader({ title, onBack, backLabel, icon }) {
948
1098
 
949
1099
  // src/components/violation-row.tsx
950
1100
  var React12 = __toESM(require("react"));
951
- var import_editor_elements5 = require("@elementor/editor-elements");
1101
+ var import_editor_elements6 = require("@elementor/editor-elements");
952
1102
  var import_editor_floating_panels2 = require("@elementor/editor-floating-panels");
953
1103
  var import_icons10 = require("@elementor/icons");
954
1104
  var import_ui11 = require("@elementor/ui");
955
1105
  var import_i18n10 = require("@wordpress/i18n");
956
1106
 
957
1107
  // src/hooks/focus-violation.ts
958
- var import_editor_elements4 = require("@elementor/editor-elements");
1108
+ var import_editor_elements5 = require("@elementor/editor-elements");
959
1109
  var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
960
1110
  var SCROLL_TO_VIEW_DELAY_MS = 200;
961
1111
  function focusViolation(violation) {
962
1112
  if (violation.elementId) {
963
- const container = (0, import_editor_elements4.getContainer)(violation.elementId);
1113
+ const container = (0, import_editor_elements5.getContainer)(violation.elementId);
964
1114
  if (container) {
965
- (0, import_editor_elements4.selectElement)(violation.elementId);
1115
+ (0, import_editor_elements5.selectElement)(violation.elementId);
966
1116
  const domElement = container.view?.getDomElement?.();
967
1117
  if (domElement) {
968
1118
  window.elementor?.helpers?.scrollToView?.(domElement, SCROLL_TO_VIEW_DELAY_MS);
@@ -971,25 +1121,27 @@ function focusViolation(violation) {
971
1121
  if (violation.targetHint === "element-settings") {
972
1122
  (0, import_editor_v1_adapters2.__privateRunCommand)("panel/editor/open");
973
1123
  }
974
- return;
1124
+ return container ? "element_focused" : null;
975
1125
  }
976
1126
  if (violation.externalUrl) {
977
1127
  window.open(violation.externalUrl, "_blank");
978
- return;
1128
+ return "external_url_opened";
979
1129
  }
980
1130
  if (violation.targetHint === "page-settings") {
981
1131
  (0, import_editor_v1_adapters2.__privateOpenRoute)("panel/page-settings/settings");
982
- return;
1132
+ return "page_settings_opened";
983
1133
  }
984
1134
  if (violation.targetHint === "site-settings") {
985
1135
  (0, import_editor_v1_adapters2.__privateRunCommand)("panel/global/open");
986
- return;
1136
+ return "site_settings_opened";
987
1137
  }
988
1138
  if (violation.targetHint === "site-identity-settings") {
989
1139
  void (0, import_editor_v1_adapters2.__privateRunCommand)("panel/global/open").then(() => {
990
1140
  (0, import_editor_v1_adapters2.__privateOpenRoute)("panel/global/settings-site-identity");
991
1141
  });
1142
+ return "site_settings_opened";
992
1143
  }
1144
+ return null;
993
1145
  }
994
1146
 
995
1147
  // src/utils/build-angie-prompt.ts
@@ -1018,7 +1170,7 @@ var import_editor_mcp = require("@elementor/editor-mcp");
1018
1170
  var import_icons6 = require("@elementor/icons");
1019
1171
  var import_ui8 = require("@elementor/ui");
1020
1172
  var import_i18n9 = require("@wordpress/i18n");
1021
- function FixViolationWithAngie({ prompt, panelZIndex, variant = "icon" }) {
1173
+ function FixViolationWithAngie({ audit: audit25, prompt, panelZIndex, variant = "icon" }) {
1022
1174
  const label = (0, import_i18n9.__)("Fix with Angie", "elementor");
1023
1175
  const href = `#angie-prompt=${encodeURIComponent(prompt)}`;
1024
1176
  const handleClick = (event) => {
@@ -1026,6 +1178,12 @@ function FixViolationWithAngie({ prompt, panelZIndex, variant = "icon" }) {
1026
1178
  event.preventDefault();
1027
1179
  if ((0, import_editor_mcp.isAngieAvailable)()) {
1028
1180
  (0, import_editor_mcp.sendPromptToAngie)(prompt);
1181
+ trackFindingClicked({
1182
+ audit: audit25,
1183
+ locationL2: "issues",
1184
+ actionType: "fix_with_angie",
1185
+ interactionResult: "angie_prompt_sent"
1186
+ });
1029
1187
  return;
1030
1188
  }
1031
1189
  window.dispatchEvent(
@@ -1074,11 +1232,18 @@ function SeverityIcon({ severity }) {
1074
1232
  var React10 = __toESM(require("react"));
1075
1233
  var import_icons8 = require("@elementor/icons");
1076
1234
  var import_ui9 = require("@elementor/ui");
1077
- function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined", withIcon = false }) {
1235
+ function ViolationCtaButton({
1236
+ ctaLabel,
1237
+ externalUrl,
1238
+ variant = "outlined",
1239
+ withIcon = false,
1240
+ onOpen
1241
+ }) {
1078
1242
  const handleClick = (event) => {
1079
1243
  event.stopPropagation();
1080
1244
  event.preventDefault();
1081
1245
  window.open(externalUrl, "_blank", "noopener");
1246
+ onOpen?.();
1082
1247
  };
1083
1248
  return /* @__PURE__ */ React10.createElement(
1084
1249
  import_ui9.Button,
@@ -1129,6 +1294,7 @@ function StatusIndicator({ audit: audit25, violations }) {
1129
1294
  return /* @__PURE__ */ React12.createElement(import_icons10.CheckIcon, { fontSize: "small", color: "success" });
1130
1295
  }
1131
1296
  function GuidanceAction({
1297
+ audit: audit25,
1132
1298
  violation,
1133
1299
  sharedAngiePrompt,
1134
1300
  panelZIndex
@@ -1142,7 +1308,8 @@ function GuidanceAction({
1142
1308
  {
1143
1309
  ctaLabel: violation.ctaLabel,
1144
1310
  externalUrl: violation.externalUrl,
1145
- withIcon: true
1311
+ withIcon: true,
1312
+ onOpen: () => trackFixWithApp(audit25, violation, "issues")
1146
1313
  }
1147
1314
  ), hasPrimaryCta && violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React12.createElement(
1148
1315
  ViolationCtaButton,
@@ -1151,7 +1318,15 @@ function GuidanceAction({
1151
1318
  externalUrl: violation.secondaryCtaUrl,
1152
1319
  variant: "text"
1153
1320
  }
1154
- ), sharedAngiePrompt && /* @__PURE__ */ React12.createElement(FixViolationWithAngie, { prompt: sharedAngiePrompt, panelZIndex, variant: "button" }));
1321
+ ), sharedAngiePrompt && /* @__PURE__ */ React12.createElement(
1322
+ FixViolationWithAngie,
1323
+ {
1324
+ audit: audit25,
1325
+ prompt: sharedAngiePrompt,
1326
+ panelZIndex,
1327
+ variant: "button"
1328
+ }
1329
+ ));
1155
1330
  }
1156
1331
  function getSharedAngiePrompt(violations) {
1157
1332
  if (!violations || violations.length < 2) {
@@ -1171,9 +1346,20 @@ function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, vi
1171
1346
  const isGuidanceFocusable = !!primaryViolation;
1172
1347
  const panelZIndex = (0, import_editor_floating_panels2.useFloatingPanelZIndex)(AUDIT_PANEL_ID);
1173
1348
  const sharedAngiePrompt = getSharedAngiePrompt(violations);
1349
+ const viewIssue = (violation) => {
1350
+ const interactionResult = focusViolation(violation);
1351
+ if (interactionResult) {
1352
+ trackFindingClicked({
1353
+ audit: audit25,
1354
+ locationL2: "issues",
1355
+ actionType: "view_issue",
1356
+ interactionResult
1357
+ });
1358
+ }
1359
+ };
1174
1360
  const handleGuidanceClick = () => {
1175
1361
  if (isGuidanceFocusable && primaryViolation) {
1176
- focusViolation(primaryViolation);
1362
+ viewIssue(primaryViolation);
1177
1363
  }
1178
1364
  };
1179
1365
  return /* @__PURE__ */ React12.createElement(import_ui11.Box, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React12.createElement(import_ui11.Box, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React12.createElement(
@@ -1223,14 +1409,15 @@ function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, vi
1223
1409
  primaryViolation && /* @__PURE__ */ React12.createElement(
1224
1410
  GuidanceAction,
1225
1411
  {
1412
+ audit: audit25,
1226
1413
  violation: primaryViolation,
1227
1414
  sharedAngiePrompt,
1228
1415
  panelZIndex
1229
1416
  }
1230
1417
  )
1231
1418
  ))), violations && violations.length > 0 && /* @__PURE__ */ React12.createElement(import_ui11.Box, { role: "list", sx: { paddingBlockEnd: 1 } }, violations.map((violation, idx) => {
1232
- const widgetIcon = violation.elementId ? (0, import_editor_elements5.getElementIcon)(violation.elementId) : null;
1233
- const elementTitle = violation.elementId ? (0, import_editor_elements5.getElementTitle)(violation.elementId) : null;
1419
+ const widgetIcon = violation.elementId ? (0, import_editor_elements6.getElementIcon)(violation.elementId) : null;
1420
+ const elementTitle = violation.elementId ? (0, import_editor_elements6.getElementTitle)(violation.elementId) : null;
1234
1421
  const displayLabel = elementTitle ?? violation.label;
1235
1422
  const angiePromptContext = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
1236
1423
  const showsOwnFixAction = !!violation.angieFix && !sharedAngiePrompt;
@@ -1240,8 +1427,8 @@ function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, vi
1240
1427
  key: idx,
1241
1428
  role: "button",
1242
1429
  tabIndex: 0,
1243
- onClick: () => focusViolation(violation),
1244
- onKeyDown: onKeyboardClick(() => focusViolation(violation)),
1430
+ onClick: () => viewIssue(violation),
1431
+ onKeyDown: onKeyboardClick(() => viewIssue(violation)),
1245
1432
  sx: {
1246
1433
  display: "flex",
1247
1434
  alignItems: "center",
@@ -1267,6 +1454,7 @@ function ViolationRow({ audit: audit25, expanded, onToggleExpand, skipReason, vi
1267
1454
  /* @__PURE__ */ React12.createElement(
1268
1455
  FixViolationWithAngie,
1269
1456
  {
1457
+ audit: audit25,
1270
1458
  prompt: violation.angiePrompt ?? buildAngiePrompt(angiePromptContext),
1271
1459
  panelZIndex
1272
1460
  }
@@ -1530,8 +1718,12 @@ function Promotions({ report }) {
1530
1718
  ctaLabel: config.ctaLabel,
1531
1719
  ctaDisabled: !ctaUrl,
1532
1720
  onCtaClick: () => {
1533
- if (ctaUrl) {
1534
- window.open(ctaUrl, "_blank");
1721
+ if (!ctaUrl) {
1722
+ return;
1723
+ }
1724
+ window.open(ctaUrl, "_blank", "noopener");
1725
+ if (run.result.status === "fail") {
1726
+ trackFixWithApp(run.audit, run.result.violations[0], "overview");
1535
1727
  }
1536
1728
  }
1537
1729
  }
@@ -1584,7 +1776,7 @@ function isCategoryPage(page) {
1584
1776
  return typeof page === "object" && "category" in page;
1585
1777
  }
1586
1778
  function ReportShell({ report }) {
1587
- const [activePage, setActivePage] = (0, import_react5.useState)("overview");
1779
+ const [activePage, setActivePage] = (0, import_react6.useState)("overview");
1588
1780
  const openCategory = (category) => setActivePage({ category });
1589
1781
  const backToOverview = () => setActivePage("overview");
1590
1782
  return /* @__PURE__ */ React19.createElement(import_ui18.Box, { sx: { flex: 1, minHeight: 0, overflowY: "auto" } }, activePage === "overview" && /* @__PURE__ */ React19.createElement(OverviewPage, { report, onCategoryClick: openCategory }), isCategoryPage(activePage) && /* @__PURE__ */ React19.createElement(CategoryPage, { category: activePage.category, report, onBack: backToOverview }));
@@ -1622,8 +1814,9 @@ function RescanButton({ hasScanned, isStale, disabled, onClick }) {
1622
1814
  // src/components/audit-panel.tsx
1623
1815
  function AuditPanel() {
1624
1816
  const { status, report, error, isStale, run } = useAuditReport();
1625
- const hostDocumentId = (0, import_editor_elements6.getHostDocumentId)() ?? 0;
1626
- const onRun = () => run(hostDocumentId);
1817
+ useTrackPanelViewed();
1818
+ const hostDocumentId = (0, import_editor_elements7.getHostDocumentId)() ?? 0;
1819
+ const onRun = () => run(hostDocumentId, report ? "rescan" : "run_audit");
1627
1820
  const lastScanLabel = report ? new Date(report.runAt).toLocaleTimeString() : null;
1628
1821
  return /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement(
1629
1822
  import_editor_floating_panels4.FloatingPanelHeader,
@@ -1631,7 +1824,8 @@ function AuditPanel() {
1631
1824
  panelId: AUDIT_PANEL_ID,
1632
1825
  title: (0, import_i18n17.__)("Page Audit", "elementor"),
1633
1826
  badge: (0, import_i18n17.__)("Beta", "elementor"),
1634
- titleVariant: "subtitle2"
1827
+ titleVariant: "subtitle2",
1828
+ onClose: trackPanelClosed
1635
1829
  }
1636
1830
  ), /* @__PURE__ */ React21.createElement(
1637
1831
  import_editor_floating_panels4.FloatingPanelBody,
@@ -1748,7 +1942,8 @@ var audit2 = {
1748
1942
  externalUrl: isReady ? ctx.pageContext.ally_accessibility_statement_url : ctx.pageContext.ally_plugin_url,
1749
1943
  ctaLabel: (0, import_i18n20.__)("Create", "elementor"),
1750
1944
  secondaryCtaLabel: (0, import_i18n20.__)("Learn more", "elementor"),
1751
- secondaryCtaUrl: "https://elementor.com/help/start-using-ally/#statement"
1945
+ secondaryCtaUrl: "https://elementor.com/help/start-using-ally/#statement",
1946
+ appInstalled: isReady
1752
1947
  }
1753
1948
  ]
1754
1949
  };
@@ -1791,7 +1986,8 @@ var audit3 = {
1791
1986
  auditId: audit3.id,
1792
1987
  label: (0, import_i18n21.__)("No accessibility widget is active on this site.", "elementor"),
1793
1988
  externalUrl: isReady ? ctx.pageContext.ally_widget_settings_url : ctx.pageContext.ally_plugin_url,
1794
- ctaLabel: (0, import_i18n21.__)("Activate", "elementor")
1989
+ ctaLabel: (0, import_i18n21.__)("Activate", "elementor"),
1990
+ appInstalled: isReady
1795
1991
  }
1796
1992
  ]
1797
1993
  };
@@ -1822,7 +2018,8 @@ var audit4 = {
1822
2018
  auditId: audit4.id,
1823
2019
  label: (0, import_i18n22.__)("Cookiez plugin is not installed or active.", "elementor"),
1824
2020
  externalUrl: ctx.pageContext.cookiez_plugin_url,
1825
- ctaLabel: (0, import_i18n22.__)("Set up cookie consent", "elementor")
2021
+ ctaLabel: (0, import_i18n22.__)("Set up cookie consent", "elementor"),
2022
+ appInstalled: ctx.pageContext.cookiez_plugin_active
1826
2023
  }
1827
2024
  ]
1828
2025
  };
@@ -1830,7 +2027,7 @@ var audit4 = {
1830
2027
  };
1831
2028
 
1832
2029
  // src/audits/deep-nesting.ts
1833
- var import_editor_elements7 = require("@elementor/editor-elements");
2030
+ var import_editor_elements8 = require("@elementor/editor-elements");
1834
2031
  var import_i18n23 = require("@wordpress/i18n");
1835
2032
  var MAX_NESTING_DEPTH = 6;
1836
2033
  function isNestingElement(node, widgetsCache) {
@@ -1854,7 +2051,7 @@ var audit5 = {
1854
2051
  if (ctx.elements.tree.length === 0) {
1855
2052
  return { status: "skipped", reason: (0, import_i18n23.__)("No elements", "elementor") };
1856
2053
  }
1857
- const widgetsCache = (0, import_editor_elements7.getWidgetsCache)();
2054
+ const widgetsCache = (0, import_editor_elements8.getWidgetsCache)();
1858
2055
  const violations = [];
1859
2056
  walkElements(ctx.elements.tree, (node, parents) => {
1860
2057
  if (!isNestingElement(node, widgetsCache)) {
@@ -1905,7 +2102,7 @@ var audit6 = {
1905
2102
  };
1906
2103
 
1907
2104
  // src/audits/deprecated-widgets.ts
1908
- var import_editor_elements8 = require("@elementor/editor-elements");
2105
+ var import_editor_elements9 = require("@elementor/editor-elements");
1909
2106
  var import_i18n25 = require("@wordpress/i18n");
1910
2107
  var DEPRECATION_CONTROL_NAME = "deprecation_message";
1911
2108
  var audit7 = {
@@ -1920,7 +2117,7 @@ var audit7 = {
1920
2117
  severity: "warning",
1921
2118
  weight: 7,
1922
2119
  evaluate: (ctx) => {
1923
- const widgetsCache = (0, import_editor_elements8.getWidgetsCache)();
2120
+ const widgetsCache = (0, import_editor_elements9.getWidgetsCache)();
1924
2121
  if (!widgetsCache) {
1925
2122
  return { status: "skipped", reason: "widgets-cache-unavailable" };
1926
2123
  }
@@ -2008,6 +2205,7 @@ var audit8 = {
2008
2205
  auditId: audit8.id,
2009
2206
  label,
2010
2207
  ctaLabel: (0, import_i18n26.__)("Enable", "elementor"),
2208
+ appInstalled: true,
2011
2209
  externalUrl: ctx.pageContext.cookiez_consent_mode_settings_url
2012
2210
  }
2013
2211
  ]
@@ -2351,7 +2549,8 @@ var audit11 = {
2351
2549
  targetHint: "element-settings",
2352
2550
  label: (0, import_i18n29.__)("Image is missing alt text.", "elementor"),
2353
2551
  externalUrl: isReady ? ctx.pageContext.ally_scan_url : ctx.pageContext.ally_plugin_url,
2354
- ctaLabel: (0, import_i18n29.__)("Fix with Ally", "elementor")
2552
+ ctaLabel: (0, import_i18n29.__)("Fix with Ally", "elementor"),
2553
+ appInstalled: isReady
2355
2554
  });
2356
2555
  }
2357
2556
  });
@@ -2400,7 +2599,8 @@ var audit12 = {
2400
2599
  targetHint: "element-settings",
2401
2600
  label: (0, import_i18n30.__)("Image isn't served in a modern format like WebP or AVIF.", "elementor"),
2402
2601
  externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
2403
- ctaLabel: (0, import_i18n30.__)("Optimize all", "elementor")
2602
+ ctaLabel: (0, import_i18n30.__)("Optimize all", "elementor"),
2603
+ appInstalled: isReady
2404
2604
  }));
2405
2605
  return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { inefficientImageFormatCount } };
2406
2606
  }
@@ -2454,7 +2654,8 @@ var audit13 = {
2454
2654
  kb
2455
2655
  ),
2456
2656
  externalUrl: isReady ? ctx.pageContext.image_optimization_settings_url : ctx.pageContext.image_optimization_plugin_url,
2457
- ctaLabel: (0, import_i18n31.__)("Optimize all", "elementor")
2657
+ ctaLabel: (0, import_i18n31.__)("Optimize all", "elementor"),
2658
+ appInstalled: isReady
2458
2659
  }));
2459
2660
  return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { oversizedImageCount } };
2460
2661
  }
@@ -2895,7 +3096,8 @@ var audit22 = {
2895
3096
  {
2896
3097
  auditId: audit22.id,
2897
3098
  label: (0, import_i18n40.__)("This page has not been scanned for cookies yet.", "elementor"),
2898
- externalUrl: isReady ? ctx.pageContext.cookiez_scan_url : ctx.pageContext.cookiez_plugin_action_url
3099
+ externalUrl: isReady ? ctx.pageContext.cookiez_scan_url : ctx.pageContext.cookiez_plugin_action_url,
3100
+ appInstalled: isReady
2899
3101
  }
2900
3102
  ]
2901
3103
  };
@@ -3023,19 +3225,19 @@ function registerAllAudits() {
3023
3225
 
3024
3226
  // src/sync-report-staleness.ts
3025
3227
  var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
3026
- var import_store6 = require("@elementor/store");
3228
+ var import_store8 = require("@elementor/store");
3027
3229
  function syncReportStaleness() {
3028
3230
  (0, import_editor_v1_adapters3.__privateListenTo)((0, import_editor_v1_adapters3.commandEndEvent)("document/save/set-is-modified"), (e) => {
3029
3231
  const event = e;
3030
3232
  if (event.args?.status) {
3031
- (0, import_store6.__dispatch)(slice.actions.reportStale());
3233
+ (0, import_store8.__dispatch)(slice.actions.reportStale());
3032
3234
  }
3033
3235
  });
3034
3236
  }
3035
3237
 
3036
3238
  // src/init.ts
3037
3239
  function init() {
3038
- (0, import_store7.__registerSlice)(slice);
3240
+ (0, import_store9.__registerSlice)(slice);
3039
3241
  registerAllAudits();
3040
3242
  (0, import_editor_floating_panels6.registerFloatingPanel)(auditPanel.panel);
3041
3243
  registerAppBarAuditsToggle();