@elementor/editor-audits 4.4.0-1111 → 4.4.0-1113

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.mjs CHANGED
@@ -6,7 +6,7 @@ import { __registerSlice as registerSlice } from "@elementor/store";
6
6
  import { utilitiesMenu } from "@elementor/editor-app-bar";
7
7
 
8
8
  // src/hooks/use-audit-toggle-props.ts
9
- import { ShieldCheckIcon as ShieldCheckIcon3 } from "@elementor/icons";
9
+ import { ShieldCheckIcon as ShieldCheckIcon2 } from "@elementor/icons";
10
10
  import { __ as __24 } from "@wordpress/i18n";
11
11
 
12
12
  // src/editor-panel.tsx
@@ -14,18 +14,45 @@ import { createFloatingPanel } from "@elementor/editor-floating-panels";
14
14
 
15
15
  // src/components/audit-panel.tsx
16
16
  import * as React25 from "react";
17
- import { getCurrentDocumentId as getCurrentDocumentId2 } from "@elementor/editor-elements";
17
+ import { getHostDocumentId as getHostDocumentId3 } from "@elementor/editor-elements";
18
18
  import { FloatingPanelBody, FloatingPanelFooter, FloatingPanelHeader } from "@elementor/editor-floating-panels";
19
19
  import { Box as Box21, Button as Button5, Typography as Typography16 } from "@elementor/ui";
20
20
  import { __ as __23 } from "@wordpress/i18n";
21
21
 
22
+ // src/constants.ts
23
+ import { __ } from "@wordpress/i18n";
24
+ var AUDIT_PANEL_ID = "audit-panel";
25
+ var REPORT_STORAGE_KEY_PREFIX = "elementor/audits/report";
26
+ var CREATE_WIDGET_EVENT = "elementor/editor/create-widget";
27
+ var ANGIE_FIX_ENTRY_POINT = "audit_violation";
28
+ var FEEDBACK_EXPERIMENT_NAME = "in_editor_feedback";
29
+ var FEEDBACK_ENTRY_POINT = "audit_panel";
30
+ var FEEDBACK_CLICKED_EVENT = "audit_feedback_clicked";
31
+ var FEEDBACK_SENT_EVENT = "audit_feedback_sent";
32
+ var FEEDBACK_CANCELLED_EVENT = "audit_feedback_cancelled";
33
+ var FEEDBACK_CLOSED_EVENT = "audit_feedback_closed";
34
+ var ALL_CATEGORIES = [
35
+ "best-practices",
36
+ "seo",
37
+ "accessibility",
38
+ "performance",
39
+ "compliance"
40
+ ];
41
+ var CATEGORY_LABELS = {
42
+ "best-practices": __("Best Practices", "elementor"),
43
+ seo: __("SEO", "elementor"),
44
+ accessibility: __("Accessibility", "elementor"),
45
+ performance: __("Performance", "elementor"),
46
+ compliance: __("Site compliance", "elementor")
47
+ };
48
+
22
49
  // src/hooks/use-audit-report.ts
23
50
  import { useEffect } from "react";
24
- import { getCurrentDocumentId } from "@elementor/editor-elements";
51
+ import { getHostDocumentId as getHostDocumentId2 } from "@elementor/editor-elements";
25
52
  import { __useDispatch as useDispatch, __useSelector as useSelector } from "@elementor/store";
26
53
 
27
54
  // src/runner.ts
28
- import { getElements } from "@elementor/editor-elements";
55
+ import { getHostDocumentElements, getHostDocumentId } from "@elementor/editor-elements";
29
56
 
30
57
  // src/api/page-context-client.ts
31
58
  import { httpService } from "@elementor/http-client";
@@ -110,33 +137,6 @@ function getRegisteredAudits() {
110
137
  return Array.from(registry.values());
111
138
  }
112
139
 
113
- // src/constants.ts
114
- import { __ } from "@wordpress/i18n";
115
- var AUDIT_PANEL_ID = "audit-panel";
116
- var REPORT_STORAGE_KEY_PREFIX = "elementor/audits/report";
117
- var CREATE_WIDGET_EVENT = "elementor/editor/create-widget";
118
- var ANGIE_FIX_ENTRY_POINT = "audit_violation";
119
- var FEEDBACK_EXPERIMENT_NAME = "in_editor_feedback";
120
- var FEEDBACK_ENTRY_POINT = "audit_panel";
121
- var FEEDBACK_CLICKED_EVENT = "audit_feedback_clicked";
122
- var FEEDBACK_SENT_EVENT = "audit_feedback_sent";
123
- var FEEDBACK_CANCELLED_EVENT = "audit_feedback_cancelled";
124
- var FEEDBACK_CLOSED_EVENT = "audit_feedback_closed";
125
- var ALL_CATEGORIES = [
126
- "best-practices",
127
- "seo",
128
- "accessibility",
129
- "performance",
130
- "compliance"
131
- ];
132
- var CATEGORY_LABELS = {
133
- "best-practices": __("Best Practices", "elementor"),
134
- seo: __("SEO", "elementor"),
135
- accessibility: __("Accessibility", "elementor"),
136
- performance: __("Performance", "elementor"),
137
- compliance: __("Site compliance", "elementor")
138
- };
139
-
140
140
  // src/utils/audit-status-summary.ts
141
141
  import { __ as __2 } from "@wordpress/i18n";
142
142
 
@@ -570,7 +570,10 @@ function toSnapshot(element) {
570
570
 
571
571
  // src/runner.ts
572
572
  async function runPageAudit(documentId) {
573
- const tree = buildSnapshotTree(getElements());
573
+ if (documentId !== getHostDocumentId()) {
574
+ throw new Error("runPageAudit: documentId must match the host document.");
575
+ }
576
+ const tree = buildSnapshotTree(getHostDocumentElements());
574
577
  const imageSizeRequests = extractImageSizeRequests(tree);
575
578
  const pageContext = await fetchPageContext(documentId, imageSizeRequests);
576
579
  const elements = { documentId, tree };
@@ -659,7 +662,7 @@ function useAuditReport() {
659
662
  const report = useSelector((state) => selectReport(state));
660
663
  const error = useSelector((state) => selectError(state));
661
664
  const dispatch = useDispatch();
662
- const documentId = getCurrentDocumentId() ?? 0;
665
+ const documentId = getHostDocumentId2() ?? 0;
663
666
  useEffect(() => {
664
667
  if (!documentId || report?.documentId === documentId) {
665
668
  return;
@@ -691,6 +694,7 @@ function useAuditReport() {
691
694
  // src/components/audit-feedback.tsx
692
695
  import * as React from "react";
693
696
  import { useState } from "react";
697
+ import { useFloatingPanelZIndex } from "@elementor/editor-floating-panels";
694
698
  import { notify } from "@elementor/editor-notifications";
695
699
  import { isExperimentActive } from "@elementor/editor-v1-adapters";
696
700
  import { useMixpanel } from "@elementor/events";
@@ -732,6 +736,7 @@ function AuditFeedback() {
732
736
  const [feedbackText, setFeedbackText] = useState("");
733
737
  const [isSubmitting, setIsSubmitting] = useState(false);
734
738
  const { dispatchEvent: trackEvent = (...args) => void args } = useMixpanel();
739
+ const panelZIndex = useFloatingPanelZIndex(AUDIT_PANEL_ID);
735
740
  if (!isExperimentActive(FEEDBACK_EXPERIMENT_NAME)) {
736
741
  return null;
737
742
  }
@@ -773,7 +778,7 @@ function AuditFeedback() {
773
778
  trackEvent(FEEDBACK_SENT_EVENT, { entry_point: FEEDBACK_ENTRY_POINT });
774
779
  }).catch(notifyError).finally(() => setIsSubmitting(false));
775
780
  };
776
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tooltip, { title: triggerLabel, placement: "top" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", "aria-label": triggerLabel, onClick: handleOpen }, /* @__PURE__ */ React.createElement(MessageLinesIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(
781
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tooltip, { title: triggerLabel, placement: "top", PopperProps: { sx: { zIndex: panelZIndex } } }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", "aria-label": triggerLabel, onClick: handleOpen }, /* @__PURE__ */ React.createElement(MessageLinesIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(
777
782
  Dialog,
778
783
  {
779
784
  open: isOpen,
@@ -877,14 +882,24 @@ import * as React12 from "react";
877
882
  import { Box as Box8 } from "@elementor/ui";
878
883
  import { __ as __12 } from "@wordpress/i18n";
879
884
 
885
+ // src/hooks/use-single-expanded-card.ts
886
+ import { useState as useState2 } from "react";
887
+ function useSingleExpandedCard(initialId = null) {
888
+ const [expandedId, setExpandedId] = useState2(initialId);
889
+ const toggle = (id) => {
890
+ setExpandedId((current) => current === id ? null : id);
891
+ };
892
+ return { expandedId, toggle };
893
+ }
894
+
880
895
  // src/components/status-section.tsx
881
896
  import * as React5 from "react";
882
- import { useState as useState2 } from "react";
897
+ import { useState as useState3 } from "react";
883
898
  import { ChevronDownIcon } from "@elementor/icons";
884
899
  import { Box as Box4, Chip, Collapse, IconButton as IconButton2 } from "@elementor/ui";
885
900
  import { __ as __7 } from "@wordpress/i18n";
886
901
  function StatusSection({ label, count, color = "default", defaultExpanded = false, children }) {
887
- const [expanded, setExpanded] = useState2(defaultExpanded);
902
+ const [expanded, setExpanded] = useState3(defaultExpanded);
888
903
  if (React5.Children.count(children) === 0) {
889
904
  return null;
890
905
  }
@@ -927,10 +942,10 @@ function SubpageHeader({ title, onBack, backLabel, icon }) {
927
942
 
928
943
  // src/components/violation-row.tsx
929
944
  import * as React11 from "react";
930
- import { useState as useState3 } from "react";
931
945
  import { getElementIcon, getElementTitle } from "@elementor/editor-elements";
932
- import { AlertCircleIcon as AlertCircleIcon2, BulbIcon as BulbIcon2, CheckIcon, ChevronDownIcon as ChevronDownIcon2, EyeIcon, HelpIcon } from "@elementor/icons";
933
- import { Alert, AlertTitle, Box as Box7, Collapse as Collapse2, IconButton as IconButton5, Tooltip as Tooltip3, Typography as Typography6 } from "@elementor/ui";
946
+ import { useFloatingPanelZIndex as useFloatingPanelZIndex2 } from "@elementor/editor-floating-panels";
947
+ import { CheckIcon, ChevronDownIcon as ChevronDownIcon2, HelpIcon, InfoCircleIcon, WandIcon as WandIcon2 } from "@elementor/icons";
948
+ import { Alert, Box as Box7, Collapse as Collapse2, IconButton as IconButton5, Tooltip as Tooltip3, Typography as Typography6 } from "@elementor/ui";
934
949
  import { __ as __11 } from "@wordpress/i18n";
935
950
 
936
951
  // src/hooks/focus-violation.ts
@@ -997,7 +1012,7 @@ import { isAngieAvailable, sendPromptToAngie } from "@elementor/editor-mcp";
997
1012
  import { AngieIcon } from "@elementor/icons";
998
1013
  import { IconButton as IconButton4, Tooltip as Tooltip2 } from "@elementor/ui";
999
1014
  import { __ as __10 } from "@wordpress/i18n";
1000
- function FixViolationWithAngie({ prompt }) {
1015
+ function FixViolationWithAngie({ prompt, panelZIndex }) {
1001
1016
  const label = __10("Fix with Angie", "elementor");
1002
1017
  const href = `#angie-prompt=${encodeURIComponent(prompt)}`;
1003
1018
  const handleClick = (event) => {
@@ -1016,18 +1031,7 @@ function FixViolationWithAngie({ prompt }) {
1016
1031
  })
1017
1032
  );
1018
1033
  };
1019
- return /* @__PURE__ */ React7.createElement(Tooltip2, { title: label }, /* @__PURE__ */ React7.createElement(
1020
- IconButton4,
1021
- {
1022
- className: "violation-hover-icon",
1023
- component: "a",
1024
- href,
1025
- size: "small",
1026
- "aria-label": label,
1027
- onClick: handleClick
1028
- },
1029
- /* @__PURE__ */ React7.createElement(AngieIcon, { fontSize: "tiny" })
1030
- ));
1034
+ return /* @__PURE__ */ React7.createElement(Tooltip2, { title: label, placement: "top", PopperProps: { sx: { zIndex: panelZIndex } } }, /* @__PURE__ */ React7.createElement(IconButton4, { component: "a", href, size: "small", "aria-label": label, onClick: handleClick }, /* @__PURE__ */ React7.createElement(AngieIcon, { fontSize: "tiny" })));
1031
1035
  }
1032
1036
 
1033
1037
  // src/components/severity-icons.tsx
@@ -1045,19 +1049,30 @@ function SeverityIcon({ severity }) {
1045
1049
 
1046
1050
  // src/components/violation-cta-button.tsx
1047
1051
  import * as React9 from "react";
1052
+ import { WandIcon } from "@elementor/icons";
1048
1053
  import { Button as Button3 } from "@elementor/ui";
1049
- function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined" }) {
1054
+ function ViolationCtaButton({ ctaLabel, externalUrl, variant = "outlined", withIcon = false }) {
1050
1055
  const handleClick = (event) => {
1051
1056
  event.stopPropagation();
1052
1057
  event.preventDefault();
1053
1058
  window.open(externalUrl, "_blank", "noopener");
1054
1059
  };
1055
- return /* @__PURE__ */ React9.createElement(Button3, { variant, color: "secondary", size: "small", onClick: handleClick }, ctaLabel);
1060
+ return /* @__PURE__ */ React9.createElement(
1061
+ Button3,
1062
+ {
1063
+ variant,
1064
+ color: "secondary",
1065
+ size: "small",
1066
+ startIcon: withIcon ? /* @__PURE__ */ React9.createElement(WandIcon, { fontSize: "tiny", "aria-hidden": true }) : void 0,
1067
+ onClick: handleClick
1068
+ },
1069
+ ctaLabel
1070
+ );
1056
1071
  }
1057
1072
 
1058
1073
  // src/components/violation-icons.tsx
1059
1074
  import * as React10 from "react";
1060
- import { FileSettingsIcon, SettingsIcon, ShieldCheckIcon } from "@elementor/icons";
1075
+ import { FileSettingsIcon, SettingsIcon } from "@elementor/icons";
1061
1076
  import { Box as Box6 } from "@elementor/ui";
1062
1077
  function ViolationIcon({ violation, widgetIcon }) {
1063
1078
  if (widgetIcon) {
@@ -1077,7 +1092,7 @@ function ViolationIcon({ violation, widgetIcon }) {
1077
1092
  if (violation.targetHint === "site-settings" || violation.targetHint === "site-identity-settings") {
1078
1093
  return /* @__PURE__ */ React10.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
1079
1094
  }
1080
- return /* @__PURE__ */ React10.createElement(ShieldCheckIcon, { fontSize: "inherit", "aria-hidden": true });
1095
+ return /* @__PURE__ */ React10.createElement(SettingsIcon, { fontSize: "inherit", "aria-hidden": true });
1081
1096
  }
1082
1097
 
1083
1098
  // src/components/violation-row.tsx
@@ -1086,13 +1101,40 @@ function SkipReasonTooltip({ reason }) {
1086
1101
  }
1087
1102
  function StatusIndicator({ audit: audit26, violations }) {
1088
1103
  if (violations) {
1089
- return /* @__PURE__ */ React11.createElement(React11.Fragment, null, isScoredAudit(audit26) && /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length), /* @__PURE__ */ React11.createElement(SeverityIcon, { severity: audit26.severity }));
1104
+ return /* @__PURE__ */ React11.createElement(React11.Fragment, null, /* @__PURE__ */ React11.createElement(SeverityIcon, { severity: audit26.severity }), isScoredAudit(audit26) && /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", color: "text.secondary", fontWeight: "bold" }, violations.length));
1090
1105
  }
1091
1106
  return /* @__PURE__ */ React11.createElement(CheckIcon, { fontSize: "small", color: "success" });
1092
1107
  }
1093
- function ViolationRow({ audit: audit26, skipReason, violations }) {
1094
- const [expanded, setExpanded] = useState3(false);
1095
- const toggleExpanded = () => setExpanded((value) => !value);
1108
+ function GuidanceAction({ violation }) {
1109
+ const hasPrimaryCta = !!(violation.ctaLabel && violation.externalUrl);
1110
+ if (!hasPrimaryCta) {
1111
+ return null;
1112
+ }
1113
+ return /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 1 } }, /* @__PURE__ */ React11.createElement(
1114
+ ViolationCtaButton,
1115
+ {
1116
+ ctaLabel: violation.ctaLabel,
1117
+ externalUrl: violation.externalUrl,
1118
+ withIcon: true
1119
+ }
1120
+ ), violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React11.createElement(
1121
+ ViolationCtaButton,
1122
+ {
1123
+ ctaLabel: violation.secondaryCtaLabel,
1124
+ externalUrl: violation.secondaryCtaUrl,
1125
+ variant: "text"
1126
+ }
1127
+ ));
1128
+ }
1129
+ function ViolationRow({ audit: audit26, expanded, onToggleExpand, skipReason, violations }) {
1130
+ const primaryViolation = violations?.[0];
1131
+ const isGuidanceFocusable = !!primaryViolation;
1132
+ const panelZIndex = useFloatingPanelZIndex2(AUDIT_PANEL_ID);
1133
+ const handleGuidanceClick = () => {
1134
+ if (isGuidanceFocusable && primaryViolation) {
1135
+ focusViolation(primaryViolation);
1136
+ }
1137
+ };
1096
1138
  return /* @__PURE__ */ React11.createElement(Box7, { sx: { borderBottom: 1, borderColor: "divider", paddingBlock: 0.5 } }, /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
1097
1139
  Box7,
1098
1140
  {
@@ -1104,16 +1146,16 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
1104
1146
  gap: 0.5,
1105
1147
  minWidth: 0
1106
1148
  },
1107
- onClick: toggleExpanded
1149
+ onClick: onToggleExpand
1108
1150
  },
1109
- /* @__PURE__ */ React11.createElement(Typography6, { variant: "body2", sx: { flex: 1 } }, audit26.title),
1151
+ /* @__PURE__ */ React11.createElement(Typography6, { variant: "subtitle2", color: "text.secondary", sx: { flex: 1 } }, audit26.title),
1110
1152
  !skipReason && /* @__PURE__ */ React11.createElement(StatusIndicator, { audit: audit26, violations })
1111
1153
  ), skipReason && /* @__PURE__ */ React11.createElement(SkipReasonTooltip, { reason: skipReason }), /* @__PURE__ */ React11.createElement(
1112
1154
  IconButton5,
1113
1155
  {
1114
1156
  size: "small",
1115
1157
  "aria-label": expanded ? __11("Collapse", "elementor") : __11("Expand", "elementor"),
1116
- onClick: toggleExpanded
1158
+ onClick: onToggleExpand
1117
1159
  },
1118
1160
  /* @__PURE__ */ React11.createElement(
1119
1161
  ChevronDownIcon2,
@@ -1125,25 +1167,19 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
1125
1167
  }
1126
1168
  }
1127
1169
  )
1128
- )), /* @__PURE__ */ React11.createElement(Collapse2, { in: expanded }, /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", flexDirection: "column", gap: 1, paddingBlock: 1 } }, /* @__PURE__ */ React11.createElement(
1170
+ )), /* @__PURE__ */ React11.createElement(Collapse2, { in: expanded }, /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", flexDirection: "column", gap: 1, paddingBlock: 1 } }, /* @__PURE__ */ React11.createElement(Tooltip3, { title: audit26.fixHint, placement: "top" }, /* @__PURE__ */ React11.createElement(
1129
1171
  Alert,
1130
1172
  {
1131
1173
  severity: "secondary",
1132
- sx: { p: 1 },
1133
- icon: /* @__PURE__ */ React11.createElement(AlertCircleIcon2, { fontSize: "small", color: "secondary", "aria-hidden": true })
1174
+ sx: { p: 1, cursor: isGuidanceFocusable ? "pointer" : void 0 },
1175
+ icon: /* @__PURE__ */ React11.createElement(InfoCircleIcon, { fontSize: "small", "aria-hidden": true }),
1176
+ role: isGuidanceFocusable ? "button" : void 0,
1177
+ tabIndex: isGuidanceFocusable ? 0 : void 0,
1178
+ onClick: isGuidanceFocusable ? handleGuidanceClick : void 0,
1179
+ onKeyDown: isGuidanceFocusable ? onKeyboardClick(handleGuidanceClick) : void 0
1134
1180
  },
1135
- /* @__PURE__ */ React11.createElement(AlertTitle, null, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("What's the issue", "elementor"))),
1136
1181
  /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit26.description)
1137
- ), /* @__PURE__ */ React11.createElement(
1138
- Alert,
1139
- {
1140
- severity: "info",
1141
- sx: { p: 1 },
1142
- icon: /* @__PURE__ */ React11.createElement(BulbIcon2, { fontSize: "small", color: "info", "aria-hidden": true })
1143
- },
1144
- /* @__PURE__ */ React11.createElement(AlertTitle, null, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.primary", fontWeight: "bold" }, __11("How to resolve", "elementor"))),
1145
- /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", component: "p", color: "text.secondary" }, audit26.fixHint)
1146
- )), violations && violations.length > 0 && /* @__PURE__ */ React11.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1, paddingInlineStart: 2 } }, violations.map((violation, idx) => {
1182
+ )), primaryViolation && /* @__PURE__ */ React11.createElement(GuidanceAction, { violation: primaryViolation })), violations && violations.length > 0 && /* @__PURE__ */ React11.createElement(Box7, { role: "list", sx: { paddingBlockEnd: 1 } }, violations.map((violation, idx) => {
1147
1183
  const widgetIcon = violation.elementId ? getElementIcon(violation.elementId) : null;
1148
1184
  const elementTitle = violation.elementId ? getElementTitle(violation.elementId) : null;
1149
1185
  const rowLabel = elementTitle ? `${elementTitle} - ${violation.label}` : violation.label;
@@ -1160,45 +1196,21 @@ function ViolationRow({ audit: audit26, skipReason, violations }) {
1160
1196
  alignItems: "center",
1161
1197
  gap: 1,
1162
1198
  paddingBlock: 0.5,
1163
- paddingInline: 2,
1199
+ paddingInline: 1,
1164
1200
  borderRadius: 1,
1165
1201
  cursor: "pointer",
1166
- "& .violation-hover-icon": { opacity: 0, transition: "opacity .15s" },
1167
- "&:hover": { bgcolor: "action.hover" },
1168
- "&:hover .violation-hover-icon, &:focus-visible .violation-hover-icon": {
1169
- opacity: 1
1170
- }
1202
+ "&:hover": { bgcolor: "action.hover" }
1171
1203
  }
1172
1204
  },
1173
1205
  /* @__PURE__ */ React11.createElement(ViolationIcon, { violation, widgetIcon }),
1174
1206
  /* @__PURE__ */ React11.createElement(Box7, { sx: { flex: 1 } }, /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption" }, rowLabel), violation.detail && /* @__PURE__ */ React11.createElement(Typography6, { variant: "caption", color: "text.secondary" }, violation.detail)),
1175
- violation.angieFix && /* @__PURE__ */ React11.createElement(
1207
+ violation.angieFix ? /* @__PURE__ */ React11.createElement(
1176
1208
  FixViolationWithAngie,
1177
1209
  {
1178
- prompt: violation.angiePrompt ?? buildAngiePrompt(rowLabel)
1179
- }
1180
- ),
1181
- violation.ctaLabel && violation.externalUrl ? /* @__PURE__ */ React11.createElement(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React11.createElement(
1182
- ViolationCtaButton,
1183
- {
1184
- ctaLabel: violation.ctaLabel,
1185
- externalUrl: violation.externalUrl
1186
- }
1187
- ), violation.secondaryCtaLabel && violation.secondaryCtaUrl && /* @__PURE__ */ React11.createElement(
1188
- ViolationCtaButton,
1189
- {
1190
- ctaLabel: violation.secondaryCtaLabel,
1191
- externalUrl: violation.secondaryCtaUrl,
1192
- variant: "text"
1193
- }
1194
- )) : /* @__PURE__ */ React11.createElement(
1195
- EyeIcon,
1196
- {
1197
- className: "violation-hover-icon",
1198
- fontSize: "tiny",
1199
- "aria-hidden": true
1210
+ prompt: violation.angiePrompt ?? buildAngiePrompt(rowLabel),
1211
+ panelZIndex
1200
1212
  }
1201
- )
1213
+ ) : /* @__PURE__ */ React11.createElement(WandIcon2, { fontSize: "tiny", "aria-hidden": true })
1202
1214
  );
1203
1215
  }))));
1204
1216
  }
@@ -1209,6 +1221,7 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
1209
1221
  const expandFail = !initialExpandedStatus || initialExpandedStatus === "fail";
1210
1222
  const expandPass = initialExpandedStatus === "pass";
1211
1223
  const expandSkipped = initialExpandedStatus === "skipped";
1224
+ const { expandedId, toggle } = useSingleExpandedCard();
1212
1225
  return /* @__PURE__ */ React12.createElement(Box8, { key: initialExpandedStatus ?? "default" }, /* @__PURE__ */ React12.createElement(SubpageHeader, { title: __12("All audits", "elementor"), onBack }), /* @__PURE__ */ React12.createElement(Box8, { sx: { p: 1 } }, /* @__PURE__ */ React12.createElement(
1213
1226
  StatusSection,
1214
1227
  {
@@ -1217,7 +1230,16 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
1217
1230
  color: auditStatusColor("fail"),
1218
1231
  defaultExpanded: expandFail
1219
1232
  },
1220
- failed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
1233
+ failed.map((r) => /* @__PURE__ */ React12.createElement(
1234
+ ViolationRow,
1235
+ {
1236
+ key: r.audit.id,
1237
+ audit: r.audit,
1238
+ violations: r.result.violations,
1239
+ expanded: expandedId === r.audit.id,
1240
+ onToggleExpand: () => toggle(r.audit.id)
1241
+ }
1242
+ ))
1221
1243
  ), /* @__PURE__ */ React12.createElement(
1222
1244
  StatusSection,
1223
1245
  {
@@ -1226,7 +1248,15 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
1226
1248
  color: auditStatusColor("pass"),
1227
1249
  defaultExpanded: expandPass
1228
1250
  },
1229
- passed.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit }))
1251
+ passed.map((r) => /* @__PURE__ */ React12.createElement(
1252
+ ViolationRow,
1253
+ {
1254
+ key: r.audit.id,
1255
+ audit: r.audit,
1256
+ expanded: expandedId === r.audit.id,
1257
+ onToggleExpand: () => toggle(r.audit.id)
1258
+ }
1259
+ ))
1230
1260
  ), /* @__PURE__ */ React12.createElement(
1231
1261
  StatusSection,
1232
1262
  {
@@ -1235,7 +1265,16 @@ function AllAuditsPage({ initialExpandedStatus, onBack, report }) {
1235
1265
  color: auditStatusColor("skipped"),
1236
1266
  defaultExpanded: expandSkipped
1237
1267
  },
1238
- skipped.map((r) => /* @__PURE__ */ React12.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, skipReason: r.result.reason }))
1268
+ skipped.map((r) => /* @__PURE__ */ React12.createElement(
1269
+ ViolationRow,
1270
+ {
1271
+ key: r.audit.id,
1272
+ audit: r.audit,
1273
+ skipReason: r.result.reason,
1274
+ expanded: expandedId === r.audit.id,
1275
+ onToggleExpand: () => toggle(r.audit.id)
1276
+ }
1277
+ ))
1239
1278
  )));
1240
1279
  }
1241
1280
 
@@ -1245,19 +1284,20 @@ import { Box as Box9 } from "@elementor/ui";
1245
1284
  import { __ as __13 } from "@wordpress/i18n";
1246
1285
 
1247
1286
  // src/components/category-icons.ts
1248
- import { BoltIcon, ElementorAccessibilityIcon, FileSearchIcon, Settings2Icon, ShieldCheckIcon as ShieldCheckIcon2 } from "@elementor/icons";
1287
+ import { BoltIcon, ElementorAccessibilityIcon, FileSearchIcon, Settings2Icon, ShieldCheckIcon } from "@elementor/icons";
1249
1288
  var CATEGORY_ICONS = {
1250
1289
  "best-practices": Settings2Icon,
1251
1290
  seo: FileSearchIcon,
1252
1291
  accessibility: ElementorAccessibilityIcon,
1253
1292
  performance: BoltIcon,
1254
- compliance: ShieldCheckIcon2
1293
+ compliance: ShieldCheckIcon
1255
1294
  };
1256
1295
 
1257
1296
  // src/components/pages/category-page.tsx
1258
1297
  function CategoryPage({ category, report, onBack }) {
1259
1298
  const Icon = CATEGORY_ICONS[category];
1260
- const { failed, passed, totalViolations } = partitionAuditResults(report, { category });
1299
+ const { failed, passed, skipped, totalViolations } = partitionAuditResults(report, { category });
1300
+ const { expandedId, toggle } = useSingleExpandedCard();
1261
1301
  return /* @__PURE__ */ React13.createElement(React13.Fragment, null, /* @__PURE__ */ React13.createElement(
1262
1302
  SubpageHeader,
1263
1303
  {
@@ -1274,8 +1314,34 @@ function CategoryPage({ category, report, onBack }) {
1274
1314
  color: "error",
1275
1315
  defaultExpanded: true
1276
1316
  },
1277
- failed.map((r) => /* @__PURE__ */ React13.createElement(ViolationRow, { key: r.audit.id, audit: r.audit, violations: r.result.violations }))
1278
- ), /* @__PURE__ */ React13.createElement(StatusSection, { label: __13("Passed audits", "elementor"), count: passed.length, color: "success" }, passed.map((r) => /* @__PURE__ */ React13.createElement(ViolationRow, { key: r.audit.id, audit: r.audit })))));
1317
+ failed.map((r) => /* @__PURE__ */ React13.createElement(
1318
+ ViolationRow,
1319
+ {
1320
+ key: r.audit.id,
1321
+ audit: r.audit,
1322
+ violations: r.result.violations,
1323
+ expanded: expandedId === r.audit.id,
1324
+ onToggleExpand: () => toggle(r.audit.id)
1325
+ }
1326
+ ))
1327
+ ), /* @__PURE__ */ React13.createElement(StatusSection, { label: __13("Passed audits", "elementor"), count: passed.length, color: "success" }, passed.map((r) => /* @__PURE__ */ React13.createElement(
1328
+ ViolationRow,
1329
+ {
1330
+ key: r.audit.id,
1331
+ audit: r.audit,
1332
+ expanded: expandedId === r.audit.id,
1333
+ onToggleExpand: () => toggle(r.audit.id)
1334
+ }
1335
+ ))), /* @__PURE__ */ React13.createElement(StatusSection, { label: __13("Skipped audits", "elementor"), count: skipped.length, color: "default" }, skipped.map((r) => /* @__PURE__ */ React13.createElement(
1336
+ ViolationRow,
1337
+ {
1338
+ key: r.audit.id,
1339
+ audit: r.audit,
1340
+ skipReason: r.result.reason,
1341
+ expanded: expandedId === r.audit.id,
1342
+ onToggleExpand: () => toggle(r.audit.id)
1343
+ }
1344
+ )))));
1279
1345
  }
1280
1346
 
1281
1347
  // src/components/pages/issues-page.tsx
@@ -1602,26 +1668,6 @@ var PROMOTIONS = [
1602
1668
  );
1603
1669
  },
1604
1670
  getCtaUrl: firstFailExternalUrl
1605
- },
1606
- {
1607
- auditId: "audits/images-inefficient-format",
1608
- icon: ShieldHalfFilledIcon,
1609
- ctaLabel: __19("Optimize all", "elementor"),
1610
- formatSubtitle: (run) => {
1611
- if (run.result.status !== "fail") {
1612
- return null;
1613
- }
1614
- const count = run.result.metadata?.inefficientImageFormatCount ?? 0;
1615
- if (count === 0) {
1616
- return null;
1617
- }
1618
- return sprintf3(
1619
- /* translators: %d: number of images served in an inefficient format. */
1620
- _n("%d image", "%d images", count, "elementor"),
1621
- count
1622
- );
1623
- },
1624
- getCtaUrl: firstFailExternalUrl
1625
1671
  }
1626
1672
  ];
1627
1673
 
@@ -1903,13 +1949,13 @@ function ReportShell({ report }) {
1903
1949
  // src/components/audit-panel.tsx
1904
1950
  function AuditPanel() {
1905
1951
  const { status, report, error, run } = useAuditReport();
1906
- const currentDocumentId = getCurrentDocumentId2() ?? 0;
1907
- const onRun = () => run(currentDocumentId);
1952
+ const hostDocumentId = getHostDocumentId3() ?? 0;
1953
+ const onRun = () => run(hostDocumentId);
1908
1954
  const lastScanLabel = report ? new Date(report.runAt).toLocaleTimeString() : null;
1909
1955
  return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(
1910
1956
  FloatingPanelHeader,
1911
1957
  {
1912
- panelId: "audit-panel",
1958
+ panelId: AUDIT_PANEL_ID,
1913
1959
  title: __23("Page Audit", "elementor"),
1914
1960
  badge: __23("Beta", "elementor"),
1915
1961
  titleVariant: "subtitle2"
@@ -1929,7 +1975,7 @@ function AuditPanel() {
1929
1975
  variant: "contained",
1930
1976
  size: "small",
1931
1977
  onClick: onRun,
1932
- disabled: status === "loading" || currentDocumentId === 0
1978
+ disabled: status === "loading" || hostDocumentId === 0
1933
1979
  },
1934
1980
  lastScanLabel ? __23("Re-scan", "elementor") : __23("Run page audit", "elementor")
1935
1981
  )));
@@ -1957,7 +2003,7 @@ function useAuditToggleProps() {
1957
2003
  const { toggle } = auditPanel.useFloatingPanelActions();
1958
2004
  return {
1959
2005
  title: __24("Audit Page", "elementor"),
1960
- icon: ShieldCheckIcon3,
2006
+ icon: ShieldCheckIcon2,
1961
2007
  selected: isOpen,
1962
2008
  onClick: () => toggle()
1963
2009
  };
@@ -2028,9 +2074,9 @@ var audit2 = {
2028
2074
  auditId: audit2.id,
2029
2075
  label: __26("No accessibility statement has been created for this site.", "elementor"),
2030
2076
  externalUrl: isReady ? ctx.pageContext.ally_accessibility_statement_url : ctx.pageContext.ally_plugin_url,
2031
- ctaLabel: isReady ? __26("Create", "elementor") : void 0,
2077
+ ctaLabel: __26("Create", "elementor"),
2032
2078
  secondaryCtaLabel: __26("Learn more", "elementor"),
2033
- secondaryCtaUrl: "https://go.elementor.com/acc-plg-learn-more"
2079
+ secondaryCtaUrl: "https://elementor.com/help/start-using-ally/#statement"
2034
2080
  }
2035
2081
  ]
2036
2082
  };
@@ -2103,7 +2149,8 @@ var audit4 = {
2103
2149
  {
2104
2150
  auditId: audit4.id,
2105
2151
  label: __28("Cookiez plugin is not installed or active.", "elementor"),
2106
- externalUrl: ctx.pageContext.cookiez_plugin_url
2152
+ externalUrl: ctx.pageContext.cookiez_plugin_url,
2153
+ ctaLabel: __28("Set up cookie consent", "elementor")
2107
2154
  }
2108
2155
  ]
2109
2156
  };
@@ -2615,7 +2662,8 @@ var audit11 = {
2615
2662
  elementId: node.id,
2616
2663
  targetHint: "element-settings",
2617
2664
  label: __35("Image is missing alt text.", "elementor"),
2618
- externalUrl: ctx.pageContext.ally_plugin_url
2665
+ externalUrl: ctx.pageContext.ally_plugin_url,
2666
+ ctaLabel: __35("Fix with Ally", "elementor")
2619
2667
  });
2620
2668
  }
2621
2669
  });
@@ -2665,7 +2713,8 @@ var audit12 = {
2665
2713
  elementId,
2666
2714
  targetHint: "element-settings",
2667
2715
  label: __36("Image isn't served in a modern format like WebP or AVIF.", "elementor"),
2668
- externalUrl: ctx.pageContext.image_optimization_plugin_url
2716
+ externalUrl: ctx.pageContext.image_optimization_plugin_url,
2717
+ ctaLabel: __36("Optimize all", "elementor")
2669
2718
  }));
2670
2719
  return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { inefficientImageFormatCount } };
2671
2720
  }
@@ -2720,7 +2769,8 @@ var audit13 = {
2720
2769
  __37("Image is %d KB (over 500 KB).", "elementor"),
2721
2770
  kb
2722
2771
  ),
2723
- externalUrl: ctx.pageContext.image_optimization_plugin_url
2772
+ externalUrl: ctx.pageContext.image_optimization_plugin_url,
2773
+ ctaLabel: __37("Optimize all", "elementor")
2724
2774
  }));
2725
2775
  return violations.length === 0 ? { status: "pass" } : { status: "fail", violations, metadata: { oversizedImageCount } };
2726
2776
  }