@xapps-platform/marketplace-ui 0.1.4 → 0.1.6

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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/MarketplaceContext.tsx
2
- import { createContext as createContext2, useContext as useContext2 } from "react";
2
+ import { createContext as createContext2, useContext as useContext2, useEffect } from "react";
3
3
 
4
4
  // ../platform-i18n/src/index.tsx
5
5
  import { createContext, useContext, useMemo } from "react";
@@ -235,11 +235,13 @@ var MARKETPLACE_CATALOGS = {
235
235
  "activity.show_details": "Show details",
236
236
  "activity.hide_details": "Hide details",
237
237
  "activity.response_title": "Response",
238
+ "activity.payment_pending": "Payment Pending",
238
239
  "activity.payment_required": "Payment Required",
239
240
  "activity.complete_payment": "Complete Payment",
240
241
  "activity.confirm_payment": "Confirm Payment",
241
242
  "activity.confirming_payment": "Confirming...",
242
243
  "activity.refresh_status": "Refresh Status",
244
+ "activity.waiting_for_payment": "Waiting for payment confirmation\u2026",
243
245
  "activity.waiting_for_response": "Waiting for response\u2026",
244
246
  "activity.execution_timeline": "Execution Timeline",
245
247
  "activity.artifacts_title": "Artifacts",
@@ -490,11 +492,13 @@ var MARKETPLACE_CATALOGS = {
490
492
  "activity.show_details": "Arat\u0103 detalii",
491
493
  "activity.hide_details": "Ascunde detalii",
492
494
  "activity.response_title": "R\u0103spuns",
495
+ "activity.payment_pending": "Plat\u0103 \xEEn a\u0219teptare",
493
496
  "activity.payment_required": "Plata este necesar\u0103",
494
497
  "activity.complete_payment": "Finalizeaz\u0103 plata",
495
498
  "activity.confirm_payment": "Confirm\u0103 plata",
496
499
  "activity.confirming_payment": "Se confirm\u0103...",
497
500
  "activity.refresh_status": "Re\xEEmprosp\u0103teaz\u0103 starea",
501
+ "activity.waiting_for_payment": "\xCEn a\u0219teptarea confirm\u0103rii pl\u0103\u021Bii\u2026",
498
502
  "activity.waiting_for_response": "\xCEn a\u0219teptarea r\u0103spunsului\u2026",
499
503
  "activity.execution_timeline": "Cronologia execu\u021Biei",
500
504
  "activity.artifacts_title": "Artefacte",
@@ -625,27 +629,110 @@ function useMarketplaceI18n() {
625
629
  return useI18n();
626
630
  }
627
631
  function resolveMarketplaceText(value, locale) {
628
- if (typeof value === "string") return value;
629
- if (!value || typeof value !== "object" || Array.isArray(value)) return "";
632
+ let candidateValue = value;
633
+ if (typeof candidateValue === "string") {
634
+ const trimmed = candidateValue.trim();
635
+ if (!trimmed) return "";
636
+ if (trimmed.startsWith("{")) {
637
+ try {
638
+ const parsed = JSON.parse(trimmed);
639
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
640
+ candidateValue = parsed;
641
+ } else {
642
+ return trimmed;
643
+ }
644
+ } catch {
645
+ return trimmed;
646
+ }
647
+ } else {
648
+ return trimmed;
649
+ }
650
+ }
651
+ if (!candidateValue || typeof candidateValue !== "object" || Array.isArray(candidateValue)) {
652
+ return "";
653
+ }
630
654
  const currentLocale = String(locale || "en").trim() || "en";
631
- const direct = value[currentLocale];
655
+ const direct = candidateValue[currentLocale];
632
656
  if (typeof direct === "string" && direct.trim()) return direct;
633
657
  const base = currentLocale.split("-")[0];
634
- const baseValue = value[base];
658
+ const baseValue = candidateValue[base];
635
659
  if (typeof baseValue === "string" && baseValue.trim()) return baseValue;
636
- const english = value.en;
660
+ const english = candidateValue.en;
637
661
  if (typeof english === "string" && english.trim()) return english;
638
- for (const localized of Object.values(value)) {
662
+ for (const localized of Object.values(candidateValue)) {
639
663
  if (typeof localized === "string" && localized.trim()) return localized;
640
664
  }
641
665
  return "";
642
666
  }
643
667
 
644
668
  // src/MarketplaceContext.tsx
645
- import { jsx as jsx3 } from "react/jsx-runtime";
669
+ import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
646
670
  var Ctx = createContext2(null);
671
+ function applyMarketplaceThemeToDocument(theme) {
672
+ if (!theme || typeof document === "undefined") return;
673
+ const root = document.documentElement;
674
+ const map = [
675
+ ["primary", ["--cx-primary", "--mx-primary"]],
676
+ ["primaryDark", ["--cx-primary-dark", "--mx-primary-hover"]],
677
+ ["bg", ["--cx-bg", "--mx-bg"]],
678
+ ["bgSubtle", ["--cx-bg-subtle", "--mx-bg-subtle"]],
679
+ ["card", ["--cx-card", "--mx-card-bg"]],
680
+ ["border", ["--cx-border", "--mx-border"]],
681
+ ["text", ["--cx-text", "--mx-text-main"]],
682
+ ["muted", ["--cx-muted", "--mx-text-muted"]],
683
+ ["shadowSm", ["--cx-shadow-sm", "--mx-shadow-sm"]],
684
+ ["shadow", ["--cx-shadow", "--mx-shadow"]],
685
+ ["shadowLg", ["--cx-shadow-lg", "--mx-shadow-lg"]],
686
+ ["radiusSm", ["--cx-radius-sm", "--mx-radius-sm"]],
687
+ ["radiusMd", ["--cx-radius-md", "--mx-radius-md"]],
688
+ ["radius", ["--cx-radius", "--cx-radius-lg", "--mx-radius-md", "--mx-radius-lg"]],
689
+ ["radiusLg", ["--cx-radius-lg", "--mx-radius-lg"]],
690
+ ["fontFamily", ["--mx-font-family"]]
691
+ ];
692
+ for (const [key, cssVars] of map) {
693
+ const rawValue = theme[key];
694
+ const value = typeof rawValue === "string" ? rawValue.trim() : "";
695
+ if (!value) continue;
696
+ for (const cssVar of cssVars) root.style.setProperty(cssVar, value);
697
+ }
698
+ if (typeof theme.radius === "string" && theme.radius.trim() && !(typeof theme.radiusSm === "string" && theme.radiusSm.trim())) {
699
+ root.style.setProperty("--cx-radius-sm", theme.radius.trim());
700
+ root.style.setProperty("--mx-radius-sm", theme.radius.trim());
701
+ }
702
+ if (typeof theme.bg === "string" && theme.bg.trim() && !theme.bgSubtle) {
703
+ root.style.setProperty("--cx-bg-subtle", theme.bg.trim());
704
+ root.style.setProperty("--mx-bg-subtle", theme.bg.trim());
705
+ }
706
+ const directTokens = theme.tokens && typeof theme.tokens === "object" && !Array.isArray(theme.tokens) ? theme.tokens : null;
707
+ if (directTokens) {
708
+ for (const [cssVar, rawValue] of Object.entries(directTokens)) {
709
+ const value = typeof rawValue === "string" ? rawValue.trim() : "";
710
+ if (!value) continue;
711
+ if (!cssVar.startsWith("--mx-") && !cssVar.startsWith("--cx-") && !cssVar.startsWith("--xapps-")) {
712
+ continue;
713
+ }
714
+ root.style.setProperty(cssVar, value);
715
+ }
716
+ }
717
+ const themeMode = typeof theme.mode === "string" ? theme.mode.trim().toLowerCase() : typeof theme.themeMode === "string" ? theme.themeMode.trim().toLowerCase() : "";
718
+ if (themeMode === "dark" || themeMode === "light") {
719
+ root.dataset.xappsThemeMode = themeMode;
720
+ }
721
+ }
722
+ function MarketplaceRuntimeBridge(props) {
723
+ useEffect(() => {
724
+ const locale = String(props.env?.locale || props.host.locale || "").trim();
725
+ if (locale && typeof document !== "undefined") {
726
+ document.documentElement.lang = locale;
727
+ }
728
+ }, [props.env?.locale, props.host.locale]);
729
+ useEffect(() => {
730
+ applyMarketplaceThemeToDocument(props.host.theme || null);
731
+ }, [props.host.theme]);
732
+ return /* @__PURE__ */ jsx3(Fragment, { children: props.children });
733
+ }
647
734
  function MarketplaceProvider(props) {
648
- return /* @__PURE__ */ jsx3(MarketplaceI18nProvider, { locale: props.env?.locale, children: /* @__PURE__ */ jsx3(Ctx.Provider, { value: { client: props.client, host: props.host, env: props.env }, children: props.children }) });
735
+ return /* @__PURE__ */ jsx3(MarketplaceI18nProvider, { locale: props.env?.locale, children: /* @__PURE__ */ jsx3(MarketplaceRuntimeBridge, { host: props.host, env: props.env, children: /* @__PURE__ */ jsx3(Ctx.Provider, { value: { client: props.client, host: props.host, env: props.env }, children: props.children }) }) });
649
736
  }
650
737
  function useMarketplace() {
651
738
  const v = useContext2(Ctx);
@@ -657,11 +744,11 @@ function useMarketplace() {
657
744
  import { Route, Routes } from "react-router-dom";
658
745
 
659
746
  // src/pages/CatalogPage.tsx
660
- import { useEffect as useEffect2, useMemo as useMemo2, useState } from "react";
747
+ import { useEffect as useEffect3, useMemo as useMemo2, useState } from "react";
661
748
  import { Link as Link2, useLocation, useNavigate } from "react-router-dom";
662
749
 
663
750
  // src/components/ConfirmActionModal.tsx
664
- import { useEffect } from "react";
751
+ import { useEffect as useEffect2 } from "react";
665
752
  import { jsx as jsx4, jsxs } from "react/jsx-runtime";
666
753
  function ConfirmActionModal(props) {
667
754
  const { t } = useMarketplaceI18n();
@@ -674,7 +761,7 @@ function ConfirmActionModal(props) {
674
761
  onConfirm,
675
762
  onCancel
676
763
  } = props;
677
- useEffect(() => {
764
+ useEffect2(() => {
678
765
  if (!open || typeof window === "undefined") return;
679
766
  const handleKeyDown = (event) => {
680
767
  if (event.key === "Escape") {
@@ -839,7 +926,7 @@ function normalizeExpandStage(value, expanded) {
839
926
  }
840
927
 
841
928
  // src/pages/CatalogPage.tsx
842
- import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
929
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
843
930
  function useQueryToken() {
844
931
  const loc = useLocation();
845
932
  const qs = new URLSearchParams(loc.search);
@@ -941,22 +1028,22 @@ function CatalogPage() {
941
1028
  setBusy(false);
942
1029
  }
943
1030
  }
944
- useEffect2(() => {
1031
+ useEffect3(() => {
945
1032
  void refresh();
946
1033
  host.refreshInstallations();
947
1034
  }, []);
948
- useEffect2(() => {
1035
+ useEffect3(() => {
949
1036
  const stored = readStoredCatalogFilters(storageKey);
950
1037
  setInstalledOnly(Boolean(stored?.addedOnly));
951
1038
  setSelectedTag(typeof stored?.selectedTag === "string" ? stored.selectedTag : defaultTag);
952
1039
  }, [defaultTag, storageKey]);
953
- useEffect2(() => {
1040
+ useEffect3(() => {
954
1041
  const restrictedTags = env?.tags ?? [];
955
1042
  if (selectedTag && restrictedTags.length > 0 && !restrictedTags.includes(selectedTag)) {
956
1043
  setSelectedTag(defaultTag);
957
1044
  }
958
1045
  }, [defaultTag, env?.tags, selectedTag]);
959
- useEffect2(() => {
1046
+ useEffect3(() => {
960
1047
  writeStoredCatalogFilters(storageKey, {
961
1048
  addedOnly: installedOnly,
962
1049
  selectedTag: selectedTag || ""
@@ -981,10 +1068,22 @@ function CatalogPage() {
981
1068
  if (!Array.isArray(tags) || !tags.includes(selectedTag)) return false;
982
1069
  }
983
1070
  if (!qq) return true;
984
- const hay = `${x.manifest?.title ?? x.name} ${x.manifest?.description ?? x.description ?? ""} ${x.slug}`.toLowerCase();
1071
+ const manifest = asRecord(x.manifest);
1072
+ const title = resolveMarketplaceText(manifest.title, locale) || readFirstString(x.name);
1073
+ const description = resolveMarketplaceText(manifest.description, locale) || readFirstString(x.description);
1074
+ const hay = `${title} ${description} ${x.slug}`.toLowerCase();
985
1075
  return hay.includes(qq);
986
1076
  });
987
- }, [items, installationsByXappId, installedOnly, q, selectedTag, env?.tags, env?.publishers]);
1077
+ }, [
1078
+ env?.publishers,
1079
+ env?.tags,
1080
+ installationsByXappId,
1081
+ installedOnly,
1082
+ items,
1083
+ locale,
1084
+ q,
1085
+ selectedTag
1086
+ ]);
988
1087
  return /* @__PURE__ */ jsxs3("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
989
1088
  /* @__PURE__ */ jsxs3("header", { className: "mx-header", children: [
990
1089
  /* @__PURE__ */ jsx6("h1", { className: "mx-title", children: env?.title ?? t("common.marketplace", void 0, "Marketplace") }),
@@ -1083,7 +1182,7 @@ function CatalogPage() {
1083
1182
  /* @__PURE__ */ jsx6("div", { className: "mx-skeleton-line mx-skeleton-line-full" }),
1084
1183
  /* @__PURE__ */ jsx6("div", { className: "mx-skeleton-line mx-skeleton-line-short" })
1085
1184
  ] })
1086
- ] }, i)) }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
1185
+ ] }, i)) }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
1087
1186
  !busy && /* @__PURE__ */ jsx6("div", { className: "mx-results-bar", children: /* @__PURE__ */ jsx6("div", { className: "mx-results-count", children: filtered.length === items.length ? t(
1088
1187
  "catalog.results_all",
1089
1188
  {
@@ -1248,7 +1347,7 @@ function CatalogPage() {
1248
1347
  }
1249
1348
 
1250
1349
  // src/pages/InvoicesPage.tsx
1251
- import { useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
1350
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState2 } from "react";
1252
1351
  import { Link as Link4, useLocation as useLocation2 } from "react-router-dom";
1253
1352
 
1254
1353
  // src/components/MarketplaceActivityTabs.tsx
@@ -1301,7 +1400,7 @@ function MarketplaceActivityTabs(props) {
1301
1400
  }
1302
1401
 
1303
1402
  // src/pages/InvoicesPage.tsx
1304
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1403
+ import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1305
1404
  function useQueryToken2() {
1306
1405
  const loc = useLocation2();
1307
1406
  const qs = new URLSearchParams(loc.search);
@@ -1376,7 +1475,7 @@ function InvoicesPage() {
1376
1475
  setBusy(false);
1377
1476
  }
1378
1477
  }
1379
- useEffect3(() => {
1478
+ useEffect4(() => {
1380
1479
  void refresh(pageParam);
1381
1480
  host.notifyNavigation?.({
1382
1481
  path: typeof window !== "undefined" ? window.location.pathname : "",
@@ -1384,7 +1483,7 @@ function InvoicesPage() {
1384
1483
  params: { xappId: xappIdFilter || null }
1385
1484
  });
1386
1485
  }, [installationIdFilter, pageParam, paymentSessionIdFilter, xappIdFilter]);
1387
- useEffect3(() => {
1486
+ useEffect4(() => {
1388
1487
  if (!focusedInvoiceId || !client.getMyInvoiceHistory) {
1389
1488
  setFocusedInvoice(null);
1390
1489
  setFocusedHistory([]);
@@ -1413,7 +1512,7 @@ function InvoicesPage() {
1413
1512
  cancelled = true;
1414
1513
  };
1415
1514
  }, [client, focusedInvoiceId]);
1416
- useEffect3(() => {
1515
+ useEffect4(() => {
1417
1516
  if (!xappIdFilter) {
1418
1517
  setXappTitle("");
1419
1518
  return;
@@ -1461,7 +1560,7 @@ function InvoicesPage() {
1461
1560
  return /* @__PURE__ */ jsxs4("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
1462
1561
  /* @__PURE__ */ jsxs4("div", { className: "mx-breadcrumb", children: [
1463
1562
  /* @__PURE__ */ jsx8(Link4, { to: isEmbedded ? "/" : "/marketplace", children: t("common.marketplace", void 0, "Marketplace") }),
1464
- xappLink && /* @__PURE__ */ jsxs4(Fragment2, { children: [
1563
+ xappLink && /* @__PURE__ */ jsxs4(Fragment3, { children: [
1465
1564
  /* @__PURE__ */ jsx8("span", { className: "mx-breadcrumb-sep", children: "/" }),
1466
1565
  /* @__PURE__ */ jsx8(Link4, { to: xappLink, children: xappTitle || xappIdFilter })
1467
1566
  ] }),
@@ -1539,7 +1638,7 @@ function InvoicesPage() {
1539
1638
  ] }),
1540
1639
  /* @__PURE__ */ jsx8(Link4, { to: listHref, className: "mx-btn mx-btn-ghost", children: t("activity.back_to_invoice_list", void 0, "Back to invoice list") })
1541
1640
  ] }),
1542
- focusedError ? /* @__PURE__ */ jsx8("div", { className: "mx-alert mx-alert-error mx-alert-panel", children: focusedError }) : focusedInvoice ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
1641
+ focusedError ? /* @__PURE__ */ jsx8("div", { className: "mx-alert mx-alert-error mx-alert-panel", children: focusedError }) : focusedInvoice ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
1543
1642
  /* @__PURE__ */ jsxs4("div", { className: "mx-record-grid", children: [
1544
1643
  /* @__PURE__ */ jsxs4("div", { className: "mx-record-field", children: [
1545
1644
  /* @__PURE__ */ jsx8("div", { className: "mx-record-label", children: t("common.status", void 0, "Status") }),
@@ -1734,9 +1833,9 @@ function InvoicesPage() {
1734
1833
  }
1735
1834
 
1736
1835
  // src/pages/NotificationsPage.tsx
1737
- import { useEffect as useEffect4, useMemo as useMemo4, useState as useState3 } from "react";
1836
+ import { useEffect as useEffect5, useMemo as useMemo4, useState as useState3 } from "react";
1738
1837
  import { Link as Link5, useLocation as useLocation3 } from "react-router-dom";
1739
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1838
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1740
1839
  function useQueryToken3() {
1741
1840
  const loc = useLocation3();
1742
1841
  const qs = new URLSearchParams(loc.search);
@@ -1850,7 +1949,7 @@ function NotificationsPage() {
1850
1949
  setError(readFirstString(asRecord(e).message) || String(e));
1851
1950
  }
1852
1951
  }
1853
- useEffect4(() => {
1952
+ useEffect5(() => {
1854
1953
  void refresh();
1855
1954
  host.notifyNavigation?.({
1856
1955
  path: typeof window !== "undefined" ? window.location.pathname : "",
@@ -1858,7 +1957,7 @@ function NotificationsPage() {
1858
1957
  params: { xappId: xappIdFilter || null }
1859
1958
  });
1860
1959
  }, [focusedNotificationId, installationIdFilter, xappIdFilter]);
1861
- useEffect4(() => {
1960
+ useEffect5(() => {
1862
1961
  if (!focusedNotificationId) {
1863
1962
  setFocusedNotification(null);
1864
1963
  setFocusedError(null);
@@ -1887,7 +1986,7 @@ function NotificationsPage() {
1887
1986
  cancelled = true;
1888
1987
  };
1889
1988
  }, [client, focusedNotificationId, installationIdFilter, xappIdFilter]);
1890
- useEffect4(() => {
1989
+ useEffect5(() => {
1891
1990
  if (!xappIdFilter) {
1892
1991
  setXappTitle("");
1893
1992
  return;
@@ -1934,7 +2033,7 @@ function NotificationsPage() {
1934
2033
  return /* @__PURE__ */ jsxs5("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
1935
2034
  /* @__PURE__ */ jsxs5("div", { className: "mx-breadcrumb", children: [
1936
2035
  /* @__PURE__ */ jsx9(Link5, { to: isEmbedded ? "/" : "/marketplace", children: t("common.marketplace", void 0, "Marketplace") }),
1937
- xappLink && /* @__PURE__ */ jsxs5(Fragment3, { children: [
2036
+ xappLink && /* @__PURE__ */ jsxs5(Fragment4, { children: [
1938
2037
  /* @__PURE__ */ jsx9("span", { className: "mx-breadcrumb-sep", children: "/" }),
1939
2038
  /* @__PURE__ */ jsx9(Link5, { to: xappLink, children: xappTitle || xappIdFilter })
1940
2039
  ] }),
@@ -2157,9 +2256,9 @@ function NotificationsPage() {
2157
2256
  }
2158
2257
 
2159
2258
  // src/pages/PaymentsPage.tsx
2160
- import { useEffect as useEffect5, useMemo as useMemo5, useState as useState4 } from "react";
2259
+ import { useEffect as useEffect6, useMemo as useMemo5, useState as useState4 } from "react";
2161
2260
  import { Link as Link6, useLocation as useLocation4 } from "react-router-dom";
2162
- import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2261
+ import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2163
2262
  function useQueryToken4() {
2164
2263
  const loc = useLocation4();
2165
2264
  const qs = new URLSearchParams(loc.search);
@@ -2219,7 +2318,7 @@ function PaymentsPage() {
2219
2318
  setBusy(false);
2220
2319
  }
2221
2320
  }
2222
- useEffect5(() => {
2321
+ useEffect6(() => {
2223
2322
  void refresh();
2224
2323
  host.notifyNavigation?.({
2225
2324
  path: typeof window !== "undefined" ? window.location.pathname : "",
@@ -2227,7 +2326,7 @@ function PaymentsPage() {
2227
2326
  params: { xappId: xappIdFilter || null }
2228
2327
  });
2229
2328
  }, [focusedPaymentSessionId, installationIdFilter, xappIdFilter]);
2230
- useEffect5(() => {
2329
+ useEffect6(() => {
2231
2330
  if (!focusedPaymentSessionId || !client.getMyPaymentSession) {
2232
2331
  setFocusedSession(null);
2233
2332
  setFocusedError(null);
@@ -2251,7 +2350,7 @@ function PaymentsPage() {
2251
2350
  cancelled = true;
2252
2351
  };
2253
2352
  }, [client, focusedPaymentSessionId]);
2254
- useEffect5(() => {
2353
+ useEffect6(() => {
2255
2354
  if (!xappIdFilter) {
2256
2355
  setXappTitle("");
2257
2356
  return;
@@ -2298,7 +2397,7 @@ function PaymentsPage() {
2298
2397
  return /* @__PURE__ */ jsxs6("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
2299
2398
  /* @__PURE__ */ jsxs6("div", { className: "mx-breadcrumb", children: [
2300
2399
  /* @__PURE__ */ jsx10(Link6, { to: isEmbedded ? "/" : "/marketplace", children: t("common.marketplace", void 0, "Marketplace") }),
2301
- xappLink && /* @__PURE__ */ jsxs6(Fragment4, { children: [
2400
+ xappLink && /* @__PURE__ */ jsxs6(Fragment5, { children: [
2302
2401
  /* @__PURE__ */ jsx10("span", { className: "mx-breadcrumb-sep", children: "/" }),
2303
2402
  /* @__PURE__ */ jsx10(Link6, { to: xappLink, children: xappTitle || xappIdFilter })
2304
2403
  ] }),
@@ -2516,7 +2615,7 @@ function PaymentsPage() {
2516
2615
  }
2517
2616
 
2518
2617
  // src/pages/RequestDetailPage.tsx
2519
- import { useEffect as useEffect6, useMemo as useMemo6, useState as useState5 } from "react";
2618
+ import { useEffect as useEffect7, useMemo as useMemo6, useState as useState5 } from "react";
2520
2619
  import { Link as Link7, useLocation as useLocation5, useNavigate as useNavigate2, useParams } from "react-router-dom";
2521
2620
 
2522
2621
  // src/components/SchemaOutputView.tsx
@@ -2604,6 +2703,10 @@ function normalizeActionKind(raw) {
2604
2703
  function resolveText(t, key, fallback) {
2605
2704
  return typeof t === "function" ? t(key, fallback) : fallback;
2606
2705
  }
2706
+ function isSettledPaymentStatus(value) {
2707
+ const normalized = readString3(value).toLowerCase();
2708
+ return normalized === "paid" || normalized === "settled" || normalized === "succeeded" || normalized === "completed";
2709
+ }
2607
2710
  function resolveCtaLabel(actionKind, t) {
2608
2711
  if (actionKind === "complete_payment") {
2609
2712
  return resolveText(t, "payment_lock.complete_payment", "Complete Payment");
@@ -2702,7 +2805,11 @@ function resolvePaymentLockStateFromGuardSummary(summaryInput, options) {
2702
2805
  })();
2703
2806
  const isPaymentKind = actionKind === "complete_payment" || actionKind === "payment_required";
2704
2807
  const isPaymentReason = reason === "payment_required" || reason === "payment_evidence_missing" || reason === "payment_receipt_already_used";
2705
- const isLocked = isPaymentKind || isPaymentReason;
2808
+ const requestStatus = readString3(options?.requestStatus).toUpperCase();
2809
+ const paymentSettled = isSettledPaymentStatus(options?.paymentStatus);
2810
+ const isHeldForPayment = requestStatus === "PAYMENT_PENDING";
2811
+ const isResolvedPastHold = paymentSettled && requestStatus !== "" && !isHeldForPayment;
2812
+ const isLocked = !isResolvedPastHold && (isPaymentKind || isPaymentReason);
2706
2813
  return {
2707
2814
  isLocked,
2708
2815
  reason,
@@ -2717,8 +2824,137 @@ function resolvePaymentLockStateFromGuardSummary(summaryInput, options) {
2717
2824
  };
2718
2825
  }
2719
2826
 
2827
+ // src/utils/operationalSurfaces.ts
2828
+ function readPathEmbedded() {
2829
+ return typeof window !== "undefined" && window.location.pathname.startsWith("/embed");
2830
+ }
2831
+ function getOperationalSurfaces(detail) {
2832
+ const value = detail?.operational_surfaces;
2833
+ if (!value || typeof value !== "object") return null;
2834
+ return value;
2835
+ }
2836
+ function readOperationalSurfaceMode(input) {
2837
+ const policy = input.env?.operationalSurfacesVisibility;
2838
+ return input.isEmbedded ? policy?.embed ?? "contract" : policy?.portal ?? "contract";
2839
+ }
2840
+ function isOperationalSurfaceVisible(detail, surface, options) {
2841
+ const surfaces = getOperationalSurfaces(detail);
2842
+ const descriptor = surfaces?.[surface];
2843
+ if (!descriptor?.enabled) return false;
2844
+ const isEmbedded = options?.isEmbedded ?? readPathEmbedded();
2845
+ return isEmbedded ? descriptor.visibility.embed : descriptor.visibility.portal;
2846
+ }
2847
+ function surfaceClientAvailable(client, surface) {
2848
+ if (surface === "requests") return typeof client.listMyRequests === "function";
2849
+ if (surface === "payments") return typeof client.listMyPaymentSessions === "function";
2850
+ if (surface === "invoices") return typeof client.listMyInvoices === "function";
2851
+ if (surface === "notifications") return typeof client.listMyNotifications === "function";
2852
+ return false;
2853
+ }
2854
+ function buildOperationalSurfaceHref(input) {
2855
+ const isEmbedded = input.isEmbedded ?? readPathEmbedded();
2856
+ const params = new URLSearchParams({
2857
+ xappId: input.xappId,
2858
+ ...input.installationId ? { installationId: input.installationId } : {},
2859
+ ...input.paymentSessionId ? { paymentSessionId: input.paymentSessionId } : {},
2860
+ ...input.invoiceId ? { invoiceId: input.invoiceId } : {},
2861
+ ...input.notificationId ? { notificationId: input.notificationId } : {},
2862
+ ...input.token ? { token: input.token } : {}
2863
+ });
2864
+ const base = isEmbedded ? `/${input.surface}` : `/marketplace/${input.surface}`;
2865
+ const detailSegment = input.surface === "requests" && input.requestId ? `/${encodeURIComponent(input.requestId)}` : "";
2866
+ return `${base}${detailSegment}?${params.toString()}`;
2867
+ }
2868
+ function getVisibleOperationalSurfaces(input) {
2869
+ const isEmbedded = input.isEmbedded ?? readPathEmbedded();
2870
+ const mode = readOperationalSurfaceMode({
2871
+ env: input.env,
2872
+ isEmbedded
2873
+ });
2874
+ const allSurfaces = [
2875
+ "requests",
2876
+ "payments",
2877
+ "invoices",
2878
+ "notifications"
2879
+ ];
2880
+ if (mode === "testing_all") {
2881
+ return allSurfaces.filter((surface) => {
2882
+ if (surface === "requests" && input.env?.requestsEnabled === false) return false;
2883
+ return surfaceClientAvailable(input.client, surface);
2884
+ });
2885
+ }
2886
+ const surfaces = getOperationalSurfaces(input.detail);
2887
+ if (!surfaces) return [];
2888
+ return allSurfaces.filter(
2889
+ (surface) => surfaceClientAvailable(input.client, surface) && isOperationalSurfaceVisible(input.detail, surface, { isEmbedded })
2890
+ );
2891
+ }
2892
+ function getOperationalSurfaceLabel(surface) {
2893
+ if (surface === "requests") return "Requests";
2894
+ if (surface === "payments") return "Payments";
2895
+ if (surface === "invoices") return "Invoices";
2896
+ return "Notifications";
2897
+ }
2898
+ function resolveOperationalSurfacePlacement(input) {
2899
+ const isEmbedded = input.isEmbedded ?? readPathEmbedded();
2900
+ const policy = input.env?.operationalSurfacePlacement;
2901
+ const scopePolicy = isEmbedded ? policy?.embed : policy?.portal;
2902
+ const bySurface = scopePolicy?.bySurface?.[input.surface];
2903
+ if (bySurface) return bySurface;
2904
+ return scopePolicy?.default ?? "in_router";
2905
+ }
2906
+ async function discoverOperationalSurfaceData(input) {
2907
+ const xappId = String(input.xappId || "").trim();
2908
+ const installationId = String(input.installationId || "").trim();
2909
+ if (!xappId) return [];
2910
+ const queryBase = {
2911
+ xappId,
2912
+ ...installationId ? { installationId } : {}
2913
+ };
2914
+ const checks = await Promise.all([
2915
+ (async () => {
2916
+ if (typeof input.client.listMyPaymentSessions !== "function") return null;
2917
+ try {
2918
+ const res = await input.client.listMyPaymentSessions({
2919
+ ...queryBase,
2920
+ limit: 1
2921
+ });
2922
+ return Array.isArray(res?.items) && res.items.length > 0 ? "payments" : null;
2923
+ } catch {
2924
+ return null;
2925
+ }
2926
+ })(),
2927
+ (async () => {
2928
+ if (typeof input.client.listMyInvoices !== "function") return null;
2929
+ try {
2930
+ const res = await input.client.listMyInvoices({
2931
+ ...queryBase,
2932
+ page: 1,
2933
+ pageSize: 1
2934
+ });
2935
+ return Array.isArray(res?.items) && res.items.length > 0 ? "invoices" : null;
2936
+ } catch {
2937
+ return null;
2938
+ }
2939
+ })(),
2940
+ (async () => {
2941
+ if (typeof input.client.listMyNotifications !== "function") return null;
2942
+ try {
2943
+ const res = await input.client.listMyNotifications({
2944
+ ...queryBase,
2945
+ limit: 1
2946
+ });
2947
+ return Array.isArray(res?.items) && res.items.length > 0 || Number(res?.unread_count || 0) > 0 ? "notifications" : null;
2948
+ } catch {
2949
+ return null;
2950
+ }
2951
+ })()
2952
+ ]);
2953
+ return checks.filter((surface) => Boolean(surface));
2954
+ }
2955
+
2720
2956
  // src/pages/RequestDetailPage.tsx
2721
- import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2957
+ import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2722
2958
  function useQueryToken5() {
2723
2959
  const loc = useLocation5();
2724
2960
  const qs = new URLSearchParams(loc.search);
@@ -2728,9 +2964,21 @@ function useQuery4() {
2728
2964
  const loc = useLocation5();
2729
2965
  return useMemo6(() => new URLSearchParams(loc.search), [loc.search]);
2730
2966
  }
2967
+ function navigateToExternalOrHost(url) {
2968
+ const next = String(url || "").trim();
2969
+ if (!next || typeof window === "undefined") return;
2970
+ try {
2971
+ if (window.parent && window.parent !== window) {
2972
+ window.parent.postMessage({ type: "XAPPS_UI_NAVIGATE", data: { path: next } }, "*");
2973
+ return;
2974
+ }
2975
+ } catch {
2976
+ }
2977
+ window.location.href = next;
2978
+ }
2731
2979
  function RequestDetailPage() {
2732
2980
  const { client, host, env } = useMarketplace();
2733
- const { t } = useMarketplaceI18n();
2981
+ const { t, locale } = useMarketplaceI18n();
2734
2982
  const { id } = useParams();
2735
2983
  const token = useQueryToken5();
2736
2984
  const query = useQuery4();
@@ -2747,10 +2995,13 @@ function RequestDetailPage() {
2747
2995
  const dataRecord = asRecord(data);
2748
2996
  const requestRecord = asRecord(dataRecord.request);
2749
2997
  const toolRecord = asRecord(dataRecord.tool);
2998
+ const manifestRecord = asRecord(dataRecord.manifest);
2999
+ const requestPayment = asRecord(requestRecord.payment);
3000
+ const requestPaymentSummary = asRecord(requestRecord.payment_summary);
2750
3001
  const status = readFirstString(requestRecord.status) || void 0;
2751
3002
  const isTerminal = status === "COMPLETED" || status === "FAILED";
2752
3003
  const effectiveXappId = readFirstString(requestRecord.xapp_id, xappIdFilter);
2753
- const effectiveXappTitle = readFirstString(requestRecord.xapp_name);
3004
+ const effectiveXappTitle = resolveMarketplaceText(manifestRecord.title, locale) || readFirstString(requestRecord.xapp_name);
2754
3005
  const xappCrumbLabel = effectiveXappTitle || effectiveXappId;
2755
3006
  const isEmbedded = typeof window !== "undefined" && window.location.pathname.startsWith("/embed");
2756
3007
  const marketplaceTo = {
@@ -2779,6 +3030,8 @@ function RequestDetailPage() {
2779
3030
  if (!resolvePaymentLockStateFromGuardSummary(
2780
3031
  asRecord(asRecord(res).request).guard_summary ?? null,
2781
3032
  {
3033
+ requestStatus: readFirstString(asRecord(asRecord(res).request).status),
3034
+ paymentStatus: readFirstString(asRecord(asRecord(res).request).payment_status),
2782
3035
  t: (key, fallback) => t(key, void 0, fallback)
2783
3036
  }
2784
3037
  ).isLocked) {
@@ -2790,31 +3043,7 @@ function RequestDetailPage() {
2790
3043
  setBusy(false);
2791
3044
  }
2792
3045
  }
2793
- async function reconcilePaymentFinality() {
2794
- if (!id || reconcileBusy || !client.reconcileMyRequestPayment) return;
2795
- setReconcileError(null);
2796
- setReconcileState("confirming_payment");
2797
- setReconcileBusy(true);
2798
- try {
2799
- const res = await client.reconcileMyRequestPayment({
2800
- requestId: String(id),
2801
- paymentSessionId: requestPaymentLock.paymentSessionId
2802
- });
2803
- setReconcileState(res?.finality_state || "none");
2804
- const redirectUrl = String(res?.redirect_url || "").trim();
2805
- if (redirectUrl) {
2806
- window.location.href = redirectUrl;
2807
- return;
2808
- }
2809
- await refreshOnce();
2810
- } catch (e) {
2811
- setReconcileError(readFirstString(asRecord(e).message) || String(e));
2812
- setReconcileState("failed");
2813
- } finally {
2814
- setReconcileBusy(false);
2815
- }
2816
- }
2817
- useEffect6(() => {
3046
+ useEffect7(() => {
2818
3047
  if (!id) return;
2819
3048
  let alive = true;
2820
3049
  let timer = null;
@@ -2842,7 +3071,7 @@ function RequestDetailPage() {
2842
3071
  };
2843
3072
  }, [id]);
2844
3073
  const emptyState = error === "Subject required" || error === "Session token required";
2845
- const title = readFirstString(toolRecord.title, requestRecord.tool_name) || t("activity.request_detail_title", void 0, "Request Details");
3074
+ const title = resolveMarketplaceText(toolRecord.title, locale) || readFirstString(requestRecord.tool_name) || t("activity.request_detail_title", void 0, "Request Details");
2846
3075
  const artifacts = Array.isArray(dataRecord.artifacts) ? dataRecord.artifacts : [];
2847
3076
  function attachArtifactLinks(value, arts) {
2848
3077
  if (typeof value === "string") {
@@ -2907,11 +3136,62 @@ function RequestDetailPage() {
2907
3136
  }, [toolRecord]);
2908
3137
  const requestPaymentLock = useMemo6(
2909
3138
  () => resolvePaymentLockStateFromGuardSummary(requestRecord.guard_summary ?? null, {
3139
+ requestStatus: readFirstString(requestRecord.status),
3140
+ paymentStatus: readFirstString(requestRecord.payment_status),
2910
3141
  reconcileState,
2911
3142
  t: (key, fallback) => t(key, void 0, fallback)
2912
3143
  }),
2913
3144
  [requestRecord.guard_summary, reconcileState, t]
2914
3145
  );
3146
+ const isPaymentPending = String(status || "").trim().toUpperCase() === "PAYMENT_PENDING";
3147
+ const showPaymentWaitState = requestPaymentLock.isLocked || isPaymentPending;
3148
+ const eventPaymentSessionId = useMemo6(() => {
3149
+ const events = Array.isArray(dataRecord.events) ? dataRecord.events : [];
3150
+ for (let index = events.length - 1; index >= 0; index -= 1) {
3151
+ const candidate = readPaymentSessionIdFromUnknown(getEventPayload(events[index]));
3152
+ if (candidate) return candidate;
3153
+ }
3154
+ return "";
3155
+ }, [dataRecord.events]);
3156
+ const effectivePaymentSessionId = readFirstString(
3157
+ requestPaymentLock.paymentSessionId,
3158
+ requestRecord.payment_session_id,
3159
+ requestRecord.paymentSessionId,
3160
+ requestPayment.payment_session_id,
3161
+ requestPayment.paymentSessionId,
3162
+ requestPaymentSummary.payment_session_id,
3163
+ requestPaymentSummary.paymentSessionId,
3164
+ eventPaymentSessionId
3165
+ ) || "";
3166
+ const directPaymentUrl = readFirstString(
3167
+ requestRecord.payment_resume_url,
3168
+ requestRecord.paymentResumeUrl,
3169
+ requestPayment.resume_url,
3170
+ requestPayment.resumeUrl,
3171
+ requestPaymentSummary.payment_resume_url,
3172
+ requestPaymentSummary.paymentResumeUrl,
3173
+ requestPaymentLock.actionUrl
3174
+ ) || "";
3175
+ const paymentSurfaceHref = (() => {
3176
+ if (!effectivePaymentSessionId) return "";
3177
+ const installationId = readFirstString(requestRecord.installation_id) || void 0;
3178
+ if (effectiveXappId) {
3179
+ return buildOperationalSurfaceHref({
3180
+ surface: "payments",
3181
+ xappId: effectiveXappId,
3182
+ installationId,
3183
+ paymentSessionId: effectivePaymentSessionId,
3184
+ token: token || void 0,
3185
+ isEmbedded
3186
+ });
3187
+ }
3188
+ const params = new URLSearchParams({
3189
+ paymentSessionId: effectivePaymentSessionId,
3190
+ ...installationId ? { installationId } : {},
3191
+ ...token ? { token } : {}
3192
+ });
3193
+ return `${isEmbedded ? "/payments" : "/marketplace/payments"}?${params.toString()}`;
3194
+ })();
2915
3195
  function getEventPayload(ev) {
2916
3196
  const eventRecord = asRecord(ev);
2917
3197
  if (!Object.keys(eventRecord).length) return null;
@@ -2928,6 +3208,39 @@ function RequestDetailPage() {
2928
3208
  }
2929
3209
  return null;
2930
3210
  }
3211
+ function readPaymentSessionIdFromUnknown(value) {
3212
+ const record = asRecord(value);
3213
+ const direct = readFirstString(
3214
+ record.payment_session_id,
3215
+ record.paymentSessionId,
3216
+ asRecord(record.action).payment_session_id,
3217
+ asRecord(record.action).paymentSessionId,
3218
+ asRecord(record.guard).payment_session_id,
3219
+ asRecord(asRecord(record.guard).action).payment_session_id,
3220
+ asRecord(asRecord(record.guard).action).paymentSessionId
3221
+ );
3222
+ if (direct) return direct;
3223
+ const url = readFirstString(
3224
+ record.url,
3225
+ record.payment_url,
3226
+ record.paymentUrl,
3227
+ asRecord(record.action).url,
3228
+ asRecord(asRecord(record.guard).action).url
3229
+ );
3230
+ if (!url) return "";
3231
+ try {
3232
+ const parsed = new URL(
3233
+ url,
3234
+ typeof window !== "undefined" ? window.location.href : "http://localhost"
3235
+ );
3236
+ return readFirstString(
3237
+ parsed.searchParams.get("payment_session_id"),
3238
+ parsed.searchParams.get("paymentSessionId")
3239
+ ) || "";
3240
+ } catch {
3241
+ return "";
3242
+ }
3243
+ }
2931
3244
  function extractGuardSummary(payload) {
2932
3245
  const p = asRecord(payload);
2933
3246
  const guard = asRecord(p.guard);
@@ -3005,7 +3318,7 @@ function RequestDetailPage() {
3005
3318
  if (raw == null) return null;
3006
3319
  const enriched = attachArtifactLinks(raw, artifacts);
3007
3320
  const isOpen = expandedPayloads[idx] ?? false;
3008
- return /* @__PURE__ */ jsxs8(Fragment5, { children: [
3321
+ return /* @__PURE__ */ jsxs8(Fragment6, { children: [
3009
3322
  /* @__PURE__ */ jsxs8(
3010
3323
  "button",
3011
3324
  {
@@ -3034,14 +3347,56 @@ function RequestDetailPage() {
3034
3347
  }
3035
3348
  function StatusBadge4({ status: status2 }) {
3036
3349
  const s = String(status2 || "");
3350
+ const normalized = s.trim().toUpperCase();
3037
3351
  const className = s === "COMPLETED" ? "mx-badge-success" : s === "FAILED" ? "mx-badge-danger" : "mx-badge-warning";
3038
- return /* @__PURE__ */ jsx12("span", { className: `mx-badge ${className}`, children: s || "\u2014" });
3352
+ const label = normalized === "PAYMENT_PENDING" ? t("activity.payment_pending", void 0, "Payment Pending") : s || "\u2014";
3353
+ return /* @__PURE__ */ jsx12("span", { className: `mx-badge ${className}`, children: label });
3354
+ }
3355
+ async function continuePayment() {
3356
+ if (client.reconcileMyRequestPayment && isPaymentPending) {
3357
+ setReconcileError(null);
3358
+ setReconcileState("confirming_payment");
3359
+ setReconcileBusy(true);
3360
+ try {
3361
+ const hostReturnUrl = readHostReturnUrl(loc.search);
3362
+ const currentReturnUrl = String(
3363
+ hostReturnUrl || (typeof window !== "undefined" ? window.location.href : "") || ""
3364
+ ).trim();
3365
+ const res = await client.reconcileMyRequestPayment({
3366
+ requestId: String(id),
3367
+ paymentSessionId: effectivePaymentSessionId || void 0,
3368
+ returnUrl: currentReturnUrl || void 0,
3369
+ cancelUrl: currentReturnUrl || void 0
3370
+ });
3371
+ setReconcileState(res?.finality_state || "none");
3372
+ const redirectUrl = String(res?.redirect_url || "").trim();
3373
+ if (redirectUrl) {
3374
+ navigateToExternalOrHost(redirectUrl);
3375
+ return;
3376
+ }
3377
+ await refreshOnce();
3378
+ return;
3379
+ } catch (e) {
3380
+ setReconcileError(readFirstString(asRecord(e).message) || String(e));
3381
+ setReconcileState("failed");
3382
+ return;
3383
+ } finally {
3384
+ setReconcileBusy(false);
3385
+ }
3386
+ }
3387
+ if (directPaymentUrl) {
3388
+ navigateToExternalOrHost(directPaymentUrl);
3389
+ return;
3390
+ }
3391
+ if (paymentSurfaceHref) {
3392
+ void navigate(paymentSurfaceHref);
3393
+ }
3039
3394
  }
3040
3395
  return /* @__PURE__ */ jsxs8("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
3041
3396
  /* @__PURE__ */ jsxs8("div", { className: "mx-breadcrumb", children: [
3042
3397
  !env?.singleXappMode && /* @__PURE__ */ jsx12(Link7, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") }),
3043
3398
  env?.singleXappMode && !env?.embedMode && /* @__PURE__ */ jsx12(Link7, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") }),
3044
- xappTo && /* @__PURE__ */ jsxs8(Fragment5, { children: [
3399
+ xappTo && /* @__PURE__ */ jsxs8(Fragment6, { children: [
3045
3400
  (!env?.singleXappMode || env?.singleXappMode && !env?.embedMode) && /* @__PURE__ */ jsx12("span", { className: "mx-breadcrumb-sep", children: "/" }),
3046
3401
  /* @__PURE__ */ jsx12(Link7, { to: xappTo, children: xappCrumbLabel })
3047
3402
  ] }),
@@ -3109,8 +3464,8 @@ function RequestDetailPage() {
3109
3464
  /* @__PURE__ */ jsxs8("div", { children: [
3110
3465
  /* @__PURE__ */ jsx12("h2", { className: "mx-title mx-request-section-title", children: title }),
3111
3466
  /* @__PURE__ */ jsxs8("div", { className: "mx-request-meta-row", children: [
3112
- /* @__PURE__ */ jsx12("span", { children: readString(requestRecord.xapp_name) }),
3113
- readString(requestRecord.xapp_version) && /* @__PURE__ */ jsxs8(Fragment5, { children: [
3467
+ /* @__PURE__ */ jsx12("span", { children: effectiveXappTitle || "\u2014" }),
3468
+ readString(requestRecord.xapp_version) && /* @__PURE__ */ jsxs8(Fragment6, { children: [
3114
3469
  /* @__PURE__ */ jsx12("span", { children: "\xB7" }),
3115
3470
  /* @__PURE__ */ jsxs8("span", { children: [
3116
3471
  "v",
@@ -3128,7 +3483,7 @@ function RequestDetailPage() {
3128
3483
  ] }),
3129
3484
  /* @__PURE__ */ jsxs8("div", { className: "mx-meta-item", children: [
3130
3485
  /* @__PURE__ */ jsx12("span", { className: "mx-meta-label", children: t("common.tool", void 0, "Tool") }),
3131
- /* @__PURE__ */ jsx12("span", { className: "mx-meta-value", children: readFirstString(requestRecord.tool_name) || "\u2014" })
3486
+ /* @__PURE__ */ jsx12("span", { className: "mx-meta-value", children: title || readFirstString(requestRecord.tool_name) || "\u2014" })
3132
3487
  ] }),
3133
3488
  /* @__PURE__ */ jsxs8("div", { className: "mx-meta-item", children: [
3134
3489
  /* @__PURE__ */ jsx12("span", { className: "mx-meta-label", children: t("common.created", void 0, "Created") }),
@@ -3142,34 +3497,32 @@ function RequestDetailPage() {
3142
3497
  ] }),
3143
3498
  /* @__PURE__ */ jsxs8("section", { className: "mx-table-container mx-request-section", children: [
3144
3499
  /* @__PURE__ */ jsx12("h3", { className: "mx-section-title mx-section-title-md", children: t("activity.response_title", void 0, "Response") }),
3145
- requestPaymentLock.isLocked && requestPaymentLock.actionUrl ? /* @__PURE__ */ jsxs8("div", { className: "mx-payment-lock-banner", children: [
3146
- /* @__PURE__ */ jsx12("div", { className: "mx-payment-lock-title", children: t("activity.payment_required", void 0, "Payment Required") }),
3147
- /* @__PURE__ */ jsx12("div", { className: "mx-payment-lock-message", children: requestPaymentLock.message }),
3500
+ showPaymentWaitState ? /* @__PURE__ */ jsxs8("div", { className: "mx-payment-lock-banner", children: [
3501
+ /* @__PURE__ */ jsx12("div", { className: "mx-payment-lock-title", children: isPaymentPending ? t("activity.payment_pending", void 0, "Payment Pending") : t("activity.payment_required", void 0, "Payment Required") }),
3502
+ /* @__PURE__ */ jsx12("div", { className: "mx-payment-lock-message", children: requestPaymentLock.isLocked ? requestPaymentLock.message : t(
3503
+ "activity.waiting_for_payment",
3504
+ void 0,
3505
+ "Waiting for payment confirmation\u2026"
3506
+ ) }),
3148
3507
  /* @__PURE__ */ jsxs8("div", { className: "mx-payment-lock-actions", children: [
3149
- /* @__PURE__ */ jsx12(
3508
+ isPaymentPending || effectivePaymentSessionId || directPaymentUrl || paymentSurfaceHref ? /* @__PURE__ */ jsx12(
3150
3509
  "button",
3151
3510
  {
3152
3511
  className: "mx-btn mx-btn-primary",
3153
- onClick: () => {
3154
- window.location.href = requestPaymentLock.actionUrl;
3155
- },
3156
- children: requestPaymentLock.ctaLabel || t("activity.complete_payment", void 0, "Complete Payment")
3157
- }
3158
- ),
3159
- client.reconcileMyRequestPayment && requestPaymentLock.paymentSessionId ? /* @__PURE__ */ jsx12(
3160
- "button",
3161
- {
3162
- className: "mx-btn mx-btn-secondary",
3163
- onClick: () => void reconcilePaymentFinality(),
3164
- disabled: reconcileBusy || requestPaymentLock.reconcileState === "confirmed_paid",
3165
- children: reconcileBusy ? t("activity.confirming_payment", void 0, "Confirming...") : t("activity.confirm_payment", void 0, "Confirm Payment")
3512
+ onClick: () => void continuePayment(),
3513
+ disabled: reconcileBusy,
3514
+ children: t("activity.complete_payment", void 0, "Complete Payment")
3166
3515
  }
3167
3516
  ) : null,
3168
3517
  /* @__PURE__ */ jsx12("button", { className: "mx-btn mx-btn-secondary", onClick: () => void refreshOnce(), children: t("activity.refresh_status", void 0, "Refresh Status") })
3169
3518
  ] }),
3170
3519
  reconcileError ? /* @__PURE__ */ jsx12("div", { className: "mx-payment-lock-error", children: reconcileError }) : null
3171
3520
  ] }) : null,
3172
- !isTerminal ? /* @__PURE__ */ jsx12("div", { className: "mx-waiting-state", children: t("activity.waiting_for_response", void 0, "Waiting for response\u2026") }) : /* @__PURE__ */ jsx12(SchemaOutputView, { schema: outputSchema, value: responsePayload })
3521
+ !isTerminal ? showPaymentWaitState ? /* @__PURE__ */ jsx12("div", { className: "mx-waiting-state", children: t(
3522
+ "activity.waiting_for_payment",
3523
+ void 0,
3524
+ "Waiting for payment confirmation\u2026"
3525
+ ) }) : /* @__PURE__ */ jsx12("div", { className: "mx-waiting-state", children: t("activity.waiting_for_response", void 0, "Waiting for response\u2026") }) : /* @__PURE__ */ jsx12(SchemaOutputView, { schema: outputSchema, value: responsePayload })
3173
3526
  ] }),
3174
3527
  Array.isArray(dataRecord.events) && dataRecord.events.length > 0 && (() => {
3175
3528
  const evts = dataRecord.events;
@@ -3422,7 +3775,7 @@ function RequestDetailPage() {
3422
3775
  onClick: () => {
3423
3776
  const installationId = readFirstString(requestRecord.installation_id);
3424
3777
  const widgetId = readFirstString(widget.id);
3425
- const widgetName = readFirstString(widget.title, widget.widget_name) || t("common.widget", void 0, "Widget");
3778
+ const widgetName = resolveMarketplaceText(widget.title, locale) || readFirstString(widget.widget_name) || t("common.widget", void 0, "Widget");
3426
3779
  if (!installationId || !widgetId) return;
3427
3780
  if (env?.embedMode) {
3428
3781
  navigate({
@@ -3435,7 +3788,7 @@ function RequestDetailPage() {
3435
3788
  installationId,
3436
3789
  widgetId,
3437
3790
  xappId: readString(requestRecord.xapp_id),
3438
- xappTitle: readString(requestRecord.xapp_name),
3791
+ xappTitle: effectiveXappTitle,
3439
3792
  widgetName,
3440
3793
  toolName: readString(requestRecord.tool_name)
3441
3794
  });
@@ -3443,9 +3796,9 @@ function RequestDetailPage() {
3443
3796
  children: t(
3444
3797
  "activity.open_widget",
3445
3798
  {
3446
- widget: readFirstString(widget.title, widget.widget_name) || t("common.widget", void 0, "Widget")
3799
+ widget: resolveMarketplaceText(widget.title, locale) || readFirstString(widget.widget_name) || t("common.widget", void 0, "Widget")
3447
3800
  },
3448
- `Open ${readFirstString(widget.title, widget.widget_name) || t("common.widget", void 0, "Widget")}`
3801
+ `Open ${resolveMarketplaceText(widget.title, locale) || readFirstString(widget.widget_name) || t("common.widget", void 0, "Widget")}`
3449
3802
  )
3450
3803
  },
3451
3804
  readFirstString(widget.id)
@@ -3467,9 +3820,9 @@ function RequestDetailPage() {
3467
3820
  }
3468
3821
 
3469
3822
  // src/pages/RequestsPage.tsx
3470
- import { useEffect as useEffect7, useMemo as useMemo7, useState as useState6 } from "react";
3823
+ import { useEffect as useEffect8, useMemo as useMemo7, useState as useState6 } from "react";
3471
3824
  import { Link as Link8, useLocation as useLocation6 } from "react-router-dom";
3472
- import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3825
+ import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3473
3826
  function useQueryToken6() {
3474
3827
  const loc = useLocation6();
3475
3828
  const qs = new URLSearchParams(loc.search);
@@ -3482,10 +3835,9 @@ function useQuery5() {
3482
3835
  function renderGuardActionHint(summary) {
3483
3836
  const action = asRecord(summary.action);
3484
3837
  const kind = readString(action.kind);
3485
- const url = readString(action.url);
3486
- if (kind === "upgrade_subscription") return `Upgrade subscription${url ? ` (${url})` : ""}`;
3487
- if (kind === "complete_payment") return `Complete payment${url ? ` (${url})` : ""}`;
3488
- if (kind === "step_up_auth") return `Complete step-up authentication${url ? ` (${url})` : ""}`;
3838
+ if (kind === "upgrade_subscription") return "Upgrade subscription";
3839
+ if (kind === "complete_payment") return "Complete payment";
3840
+ if (kind === "step_up_auth") return "Complete step-up authentication";
3489
3841
  if (kind === "confirm_action") {
3490
3842
  const msg = readString(action.message);
3491
3843
  return msg ? `Confirm action (${msg})` : "Confirm action";
@@ -3528,7 +3880,7 @@ function RequestsPage() {
3528
3880
  setBusy(false);
3529
3881
  }
3530
3882
  }
3531
- useEffect7(() => {
3883
+ useEffect8(() => {
3532
3884
  void refresh(pageParam);
3533
3885
  host.notifyNavigation?.({
3534
3886
  path: window.location.pathname,
@@ -3536,7 +3888,7 @@ function RequestsPage() {
3536
3888
  params: { xappId: xappIdFilter }
3537
3889
  });
3538
3890
  }, [xappIdFilter, pageParam]);
3539
- useEffect7(() => {
3891
+ useEffect8(() => {
3540
3892
  if (!xappIdFilter) {
3541
3893
  setXappTitle("");
3542
3894
  return;
@@ -3574,8 +3926,10 @@ function RequestsPage() {
3574
3926
  };
3575
3927
  function StatusBadge4({ status }) {
3576
3928
  const s = String(status || "");
3929
+ const normalized = s.trim().toUpperCase();
3577
3930
  const className = s === "COMPLETED" ? "mx-badge-success" : s === "FAILED" ? "mx-badge-danger" : "mx-badge-warning";
3578
- return /* @__PURE__ */ jsx13("span", { className: `mx-badge ${className}`, children: s || "\u2014" });
3931
+ const label = normalized === "PAYMENT_PENDING" ? t("activity.payment_pending", void 0, "Payment Pending") : s || "\u2014";
3932
+ return /* @__PURE__ */ jsx13("span", { className: `mx-badge ${className}`, children: label });
3579
3933
  }
3580
3934
  if (env?.requestsEnabled === false) {
3581
3935
  return /* @__PURE__ */ jsx13("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: /* @__PURE__ */ jsxs9("div", { className: "mx-table-container mx-unavailable", children: [
@@ -3595,7 +3949,7 @@ function RequestsPage() {
3595
3949
  /* @__PURE__ */ jsxs9("div", { className: "mx-breadcrumb", children: [
3596
3950
  !env?.singleXappMode && /* @__PURE__ */ jsx13(Link8, { to: isEmbedded ? "/" : "/marketplace", children: t("common.marketplace", void 0, "Marketplace") }),
3597
3951
  env?.singleXappMode && !isEmbedded && /* @__PURE__ */ jsx13(Link8, { to: isEmbedded ? "/" : "/marketplace", children: t("common.marketplace", void 0, "Marketplace") }),
3598
- xappIdFilter && xappLink && /* @__PURE__ */ jsxs9(Fragment6, { children: [
3952
+ xappIdFilter && xappLink && /* @__PURE__ */ jsxs9(Fragment7, { children: [
3599
3953
  (!env?.singleXappMode || env?.singleXappMode && !isEmbedded) && /* @__PURE__ */ jsx13("span", { className: "mx-breadcrumb-sep", children: "/" }),
3600
3954
  /* @__PURE__ */ jsx13(Link8, { to: xappLink, children: xappTitle || xappIdFilter })
3601
3955
  ] }),
@@ -3706,7 +4060,7 @@ function RequestsPage() {
3706
4060
  "..."
3707
4061
  ] }) }),
3708
4062
  /* @__PURE__ */ jsxs9("td", { "data-label": t("common.tool", void 0, "Tool"), children: [
3709
- /* @__PURE__ */ jsx13("div", { className: "mx-cell-bold", children: readFirstString(request.tool_name) || "\u2014" }),
4063
+ /* @__PURE__ */ jsx13("div", { className: "mx-cell-bold", children: resolveMarketplaceText(request.tool_title, locale) || readFirstString(request.tool_name) || "\u2014" }),
3710
4064
  tags.length > 0 && /* @__PURE__ */ jsx13("div", { className: "mx-card-tags mx-card-tags-inline", children: tags.slice(0, 3).map((t2) => /* @__PURE__ */ jsx13("span", { className: "mx-tag mx-tag-compact", children: t2 }, t2)) }),
3711
4065
  hasGuardInfo && /* @__PURE__ */ jsxs9("div", { className: "mx-guard-summary", children: [
3712
4066
  /* @__PURE__ */ jsxs9("div", { children: [
@@ -3780,140 +4134,9 @@ function RequestsPage() {
3780
4134
  }
3781
4135
 
3782
4136
  // src/pages/XappDetailPage.tsx
3783
- import { useEffect as useEffect8, useMemo as useMemo8, useRef, useState as useState7 } from "react";
4137
+ import { useEffect as useEffect9, useMemo as useMemo8, useRef, useState as useState7 } from "react";
3784
4138
  import { Link as Link9, useLocation as useLocation7, useNavigate as useNavigate3, useParams as useParams2 } from "react-router-dom";
3785
-
3786
- // src/utils/operationalSurfaces.ts
3787
- function readPathEmbedded() {
3788
- return typeof window !== "undefined" && window.location.pathname.startsWith("/embed");
3789
- }
3790
- function getOperationalSurfaces(detail) {
3791
- const value = detail?.operational_surfaces;
3792
- if (!value || typeof value !== "object") return null;
3793
- return value;
3794
- }
3795
- function readOperationalSurfaceMode(input) {
3796
- const policy = input.env?.operationalSurfacesVisibility;
3797
- return input.isEmbedded ? policy?.embed ?? "contract" : policy?.portal ?? "contract";
3798
- }
3799
- function isOperationalSurfaceVisible(detail, surface, options) {
3800
- const surfaces = getOperationalSurfaces(detail);
3801
- const descriptor = surfaces?.[surface];
3802
- if (!descriptor?.enabled) return false;
3803
- const isEmbedded = options?.isEmbedded ?? readPathEmbedded();
3804
- return isEmbedded ? descriptor.visibility.embed : descriptor.visibility.portal;
3805
- }
3806
- function surfaceClientAvailable(client, surface) {
3807
- if (surface === "requests") return typeof client.listMyRequests === "function";
3808
- if (surface === "payments") return typeof client.listMyPaymentSessions === "function";
3809
- if (surface === "invoices") return typeof client.listMyInvoices === "function";
3810
- if (surface === "notifications") return typeof client.listMyNotifications === "function";
3811
- return false;
3812
- }
3813
- function buildOperationalSurfaceHref(input) {
3814
- const isEmbedded = input.isEmbedded ?? readPathEmbedded();
3815
- const params = new URLSearchParams({
3816
- xappId: input.xappId,
3817
- ...input.installationId ? { installationId: input.installationId } : {},
3818
- ...input.paymentSessionId ? { paymentSessionId: input.paymentSessionId } : {},
3819
- ...input.invoiceId ? { invoiceId: input.invoiceId } : {},
3820
- ...input.notificationId ? { notificationId: input.notificationId } : {},
3821
- ...input.token ? { token: input.token } : {}
3822
- });
3823
- const base = isEmbedded ? `/${input.surface}` : `/marketplace/${input.surface}`;
3824
- const detailSegment = input.surface === "requests" && input.requestId ? `/${encodeURIComponent(input.requestId)}` : "";
3825
- return `${base}${detailSegment}?${params.toString()}`;
3826
- }
3827
- function getVisibleOperationalSurfaces(input) {
3828
- const isEmbedded = input.isEmbedded ?? readPathEmbedded();
3829
- const mode = readOperationalSurfaceMode({
3830
- env: input.env,
3831
- isEmbedded
3832
- });
3833
- const allSurfaces = [
3834
- "requests",
3835
- "payments",
3836
- "invoices",
3837
- "notifications"
3838
- ];
3839
- if (mode === "testing_all") {
3840
- return allSurfaces.filter((surface) => {
3841
- if (surface === "requests" && input.env?.requestsEnabled === false) return false;
3842
- return surfaceClientAvailable(input.client, surface);
3843
- });
3844
- }
3845
- const surfaces = getOperationalSurfaces(input.detail);
3846
- if (!surfaces) return [];
3847
- return allSurfaces.filter(
3848
- (surface) => surfaceClientAvailable(input.client, surface) && isOperationalSurfaceVisible(input.detail, surface, { isEmbedded })
3849
- );
3850
- }
3851
- function getOperationalSurfaceLabel(surface) {
3852
- if (surface === "requests") return "Requests";
3853
- if (surface === "payments") return "Payments";
3854
- if (surface === "invoices") return "Invoices";
3855
- return "Notifications";
3856
- }
3857
- function resolveOperationalSurfacePlacement(input) {
3858
- const isEmbedded = input.isEmbedded ?? readPathEmbedded();
3859
- const policy = input.env?.operationalSurfacePlacement;
3860
- const scopePolicy = isEmbedded ? policy?.embed : policy?.portal;
3861
- const bySurface = scopePolicy?.bySurface?.[input.surface];
3862
- if (bySurface) return bySurface;
3863
- return scopePolicy?.default ?? "in_router";
3864
- }
3865
- async function discoverOperationalSurfaceData(input) {
3866
- const xappId = String(input.xappId || "").trim();
3867
- const installationId = String(input.installationId || "").trim();
3868
- if (!xappId) return [];
3869
- const queryBase = {
3870
- xappId,
3871
- ...installationId ? { installationId } : {}
3872
- };
3873
- const checks = await Promise.all([
3874
- (async () => {
3875
- if (typeof input.client.listMyPaymentSessions !== "function") return null;
3876
- try {
3877
- const res = await input.client.listMyPaymentSessions({
3878
- ...queryBase,
3879
- limit: 1
3880
- });
3881
- return Array.isArray(res?.items) && res.items.length > 0 ? "payments" : null;
3882
- } catch {
3883
- return null;
3884
- }
3885
- })(),
3886
- (async () => {
3887
- if (typeof input.client.listMyInvoices !== "function") return null;
3888
- try {
3889
- const res = await input.client.listMyInvoices({
3890
- ...queryBase,
3891
- page: 1,
3892
- pageSize: 1
3893
- });
3894
- return Array.isArray(res?.items) && res.items.length > 0 ? "invoices" : null;
3895
- } catch {
3896
- return null;
3897
- }
3898
- })(),
3899
- (async () => {
3900
- if (typeof input.client.listMyNotifications !== "function") return null;
3901
- try {
3902
- const res = await input.client.listMyNotifications({
3903
- ...queryBase,
3904
- limit: 1
3905
- });
3906
- return Array.isArray(res?.items) && res.items.length > 0 || Number(res?.unread_count || 0) > 0 ? "notifications" : null;
3907
- } catch {
3908
- return null;
3909
- }
3910
- })()
3911
- ]);
3912
- return checks.filter((surface) => Boolean(surface));
3913
- }
3914
-
3915
- // src/pages/XappDetailPage.tsx
3916
- import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
4139
+ import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3917
4140
  function useQueryToken7() {
3918
4141
  const loc = useLocation7();
3919
4142
  const qs = new URLSearchParams(loc.search);
@@ -4074,7 +4297,7 @@ function XappDetailPage() {
4074
4297
  setBusy(false);
4075
4298
  }
4076
4299
  }
4077
- useEffect8(() => {
4300
+ useEffect9(() => {
4078
4301
  void refresh();
4079
4302
  host.refreshInstallations();
4080
4303
  host.notifyNavigation?.({
@@ -4083,7 +4306,7 @@ function XappDetailPage() {
4083
4306
  params: { xappId }
4084
4307
  });
4085
4308
  }, [client, installation?.installationId, xappId]);
4086
- useEffect8(() => {
4309
+ useEffect9(() => {
4087
4310
  const currentXappId = String(xappId ?? "").trim();
4088
4311
  if (!currentXappId) {
4089
4312
  setDiscoveredOperationalSurfaces([]);
@@ -4127,11 +4350,11 @@ function XappDetailPage() {
4127
4350
  };
4128
4351
  const terms = asRecord4(manifest?.terms);
4129
4352
  const termsTitle = resolveMarketplaceText(terms?.title, locale) || t("xapp.terms_title", void 0, "Terms & Conditions");
4130
- const termsText = readString4(terms?.text);
4353
+ const termsText = resolveMarketplaceText(terms?.text, locale) || readString4(terms?.text);
4131
4354
  const termsUrl = readString4(terms?.url);
4132
4355
  const hasTermsContent = Boolean(termsText || termsUrl);
4133
4356
  const requiresTerms = Boolean(terms || action === "install" || action === "update");
4134
- useEffect8(() => {
4357
+ useEffect9(() => {
4135
4358
  if (action === "install") {
4136
4359
  setTermsAccepted(false);
4137
4360
  setTermsAction("install");
@@ -4144,7 +4367,7 @@ function XappDetailPage() {
4144
4367
  setTermsOpen(true);
4145
4368
  }
4146
4369
  }, [action, installation]);
4147
- useEffect8(() => {
4370
+ useEffect9(() => {
4148
4371
  if (action !== "open-widget") return;
4149
4372
  if (env?.embedMode) return;
4150
4373
  if (!installation || !widgetsEnabled) return;
@@ -4164,7 +4387,7 @@ function XappDetailPage() {
4164
4387
  widgetId,
4165
4388
  xappId: String(xappId ?? ""),
4166
4389
  xappTitle: String(title),
4167
- widgetName: readString4(widget?.title) || readString4(widget?.widget_name) || readString4(widget?.name) || t("common.widget", void 0, "Widget"),
4390
+ widgetName: resolveMarketplaceText(widget?.title, locale) || readString4(widget?.widget_name) || readString4(widget?.name) || t("common.widget", void 0, "Widget"),
4168
4391
  toolName: readString4(widget?.bind_tool_name)
4169
4392
  });
4170
4393
  }, [
@@ -4172,6 +4395,7 @@ function XappDetailPage() {
4172
4395
  env?.embedMode,
4173
4396
  host,
4174
4397
  installation,
4398
+ locale,
4175
4399
  queryToolName,
4176
4400
  requestedWidget,
4177
4401
  title,
@@ -4285,7 +4509,7 @@ function XappDetailPage() {
4285
4509
  ) })
4286
4510
  ] }),
4287
4511
  error && /* @__PURE__ */ jsx14("div", { className: "mx-detail-error", children: error }),
4288
- busy && !data ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
4512
+ busy && !data ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
4289
4513
  /* @__PURE__ */ jsxs10("div", { className: "mx-detail-skeleton-header", "aria-busy": "true", children: [
4290
4514
  /* @__PURE__ */ jsx14("div", { className: "mx-detail-skeleton-icon" }),
4291
4515
  /* @__PURE__ */ jsxs10("div", { className: "mx-detail-skeleton-info", children: [
@@ -4319,7 +4543,7 @@ function XappDetailPage() {
4319
4543
  /* @__PURE__ */ jsx14("div", { className: "mx-skeleton-line mx-skeleton-line-short" })
4320
4544
  ] }) })
4321
4545
  ] })
4322
- ] }) : /* @__PURE__ */ jsxs10(Fragment7, { children: [
4546
+ ] }) : /* @__PURE__ */ jsxs10(Fragment8, { children: [
4323
4547
  /* @__PURE__ */ jsxs10("header", { className: "mx-detail-header", children: [
4324
4548
  /* @__PURE__ */ jsx14("img", { src: imageUrl, alt: title, className: "mx-detail-icon" }),
4325
4549
  /* @__PURE__ */ jsxs10("div", { className: "mx-detail-info", children: [
@@ -4339,7 +4563,7 @@ function XappDetailPage() {
4339
4563
  updateAvailable ? /* @__PURE__ */ jsx14("div", { className: "mx-detail-update-pill", children: t("xapp.update_available", void 0, "Update available") }) : null
4340
4564
  ] })
4341
4565
  ] }),
4342
- /* @__PURE__ */ jsx14("div", { className: "mx-detail-actions", children: canMutate ? /* @__PURE__ */ jsxs10(Fragment7, { children: [
4566
+ /* @__PURE__ */ jsx14("div", { className: "mx-detail-actions", children: canMutate ? /* @__PURE__ */ jsxs10(Fragment8, { children: [
4343
4567
  installation && updateAvailable && host.requestUpdate ? /* @__PURE__ */ jsx14(
4344
4568
  "button",
4345
4569
  {
@@ -4421,7 +4645,7 @@ function XappDetailPage() {
4421
4645
  void 0,
4422
4646
  "No app views are currently available."
4423
4647
  ) }) : /* @__PURE__ */ jsx14("div", { className: "mx-detail-widget-list", children: widgets.map((w, idx) => {
4424
- const name = readString4(w.title) || readString4(w.widget_name) || readString4(w.name) || readString4(w.id) || t("common.widget", void 0, "Widget");
4648
+ const name = resolveMarketplaceText(w.title, locale) || readString4(w.widget_name) || readString4(w.name) || readString4(w.id) || t("common.widget", void 0, "Widget");
4425
4649
  const disabled = !widgetsEnabled;
4426
4650
  const isDefault = readBoolean(w.default, false) || idx === 0 && !widgets.some((ww) => readBoolean(ww.default, false));
4427
4651
  const widgetType = String(w.type || "").toLowerCase();
@@ -4776,7 +5000,7 @@ function XappDetailPage() {
4776
5000
  widgetId: readString4(defaultWidget.id),
4777
5001
  xappId: String(xappId ?? ""),
4778
5002
  xappTitle: String(title),
4779
- widgetName: readString4(defaultWidget?.title) || readString4(defaultWidget?.widget_name) || readString4(defaultWidget?.name) || t("common.widget", void 0, "Widget"),
5003
+ widgetName: resolveMarketplaceText(defaultWidget?.title, locale) || readString4(defaultWidget?.widget_name) || readString4(defaultWidget?.name) || t("common.widget", void 0, "Widget"),
4780
5004
  toolName: readString4(defaultWidget?.bind_tool_name)
4781
5005
  });
4782
5006
  },
@@ -5024,9 +5248,9 @@ function XappDetailPage() {
5024
5248
  }
5025
5249
 
5026
5250
  // src/pages/WidgetView.tsx
5027
- import { useEffect as useEffect9, useRef as useRef2, useState as useState8 } from "react";
5251
+ import { useEffect as useEffect10, useRef as useRef2, useState as useState8 } from "react";
5028
5252
  import { Link as Link10, useLocation as useLocation8, useNavigate as useNavigate4, useParams as useParams3 } from "react-router-dom";
5029
- import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
5253
+ import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
5030
5254
  function useQueryToken8() {
5031
5255
  const loc = useLocation8();
5032
5256
  const qs = new URLSearchParams(loc.search);
@@ -5085,7 +5309,7 @@ function toSessionExpiredUi(input, t) {
5085
5309
  }
5086
5310
  function WidgetView() {
5087
5311
  const { client, host, env } = useMarketplace();
5088
- const { t } = useMarketplaceI18n();
5312
+ const { t, locale } = useMarketplaceI18n();
5089
5313
  const { installationId, widgetId } = useParams3();
5090
5314
  const token = useQueryToken8();
5091
5315
  const iframeRef = useRef2(null);
@@ -5127,7 +5351,7 @@ function WidgetView() {
5127
5351
  page: "portal-home"
5128
5352
  });
5129
5353
  };
5130
- useEffect9(() => {
5354
+ useEffect10(() => {
5131
5355
  if (!installationId) return;
5132
5356
  let alive = true;
5133
5357
  void (async () => {
@@ -5146,7 +5370,7 @@ function WidgetView() {
5146
5370
  setXappDetail(res);
5147
5371
  const detail = asRecord(res);
5148
5372
  setXappTitle(
5149
- readFirstString(asRecord(detail.manifest).title, asRecord(detail.xapp).name) || "App"
5373
+ resolveMarketplaceText(asRecord(detail.manifest).title, locale) || readFirstString(asRecord(detail.xapp).name) || "App"
5150
5374
  );
5151
5375
  }
5152
5376
  } catch {
@@ -5155,8 +5379,8 @@ function WidgetView() {
5155
5379
  return () => {
5156
5380
  alive = false;
5157
5381
  };
5158
- }, [installationId, client, host]);
5159
- useEffect9(() => {
5382
+ }, [installationId, client, host, locale]);
5383
+ useEffect10(() => {
5160
5384
  if (!xappId) {
5161
5385
  setDiscoveredOperationalSurfaces([]);
5162
5386
  return;
@@ -5176,7 +5400,7 @@ function WidgetView() {
5176
5400
  cancelled = true;
5177
5401
  };
5178
5402
  }, [client, installationId, xappId]);
5179
- useEffect9(() => {
5403
+ useEffect10(() => {
5180
5404
  if (!installationId || !widgetId || !host.notifyNavigation) return;
5181
5405
  host.notifyNavigation({
5182
5406
  path: window.location.pathname,
@@ -5184,7 +5408,7 @@ function WidgetView() {
5184
5408
  params: { installationId, widgetId }
5185
5409
  });
5186
5410
  }, [installationId, widgetId, host]);
5187
- useEffect9(() => {
5411
+ useEffect10(() => {
5188
5412
  if (!installationId || !widgetId) return;
5189
5413
  let alive = true;
5190
5414
  void (async () => {
@@ -5218,7 +5442,7 @@ function WidgetView() {
5218
5442
  expires_in: Number.isFinite(Number(refreshed?.expires_in)) && Number(refreshed?.expires_in) > 0 ? Number(refreshed?.expires_in) : void 0
5219
5443
  };
5220
5444
  }
5221
- useEffect9(() => {
5445
+ useEffect10(() => {
5222
5446
  return () => {
5223
5447
  for (const [, pending] of nestedExpandPendingRef.current) {
5224
5448
  window.clearTimeout(pending.timeoutId);
@@ -5228,7 +5452,7 @@ function WidgetView() {
5228
5452
  nestedExpandPendingRef.current.clear();
5229
5453
  };
5230
5454
  }, []);
5231
- useEffect9(() => {
5455
+ useEffect10(() => {
5232
5456
  const shell = shellRef.current;
5233
5457
  const rootEl = shell?.parentElement ?? null;
5234
5458
  const htmlEl = document.documentElement;
@@ -5261,7 +5485,7 @@ function WidgetView() {
5261
5485
  }
5262
5486
  };
5263
5487
  }, [env?.embedMode, hostNestedExpandStage]);
5264
- useEffect9(() => {
5488
+ useEffect10(() => {
5265
5489
  if (!env?.embedMode) return;
5266
5490
  const handler = (e) => {
5267
5491
  if (e.source !== window.parent) return;
@@ -5277,7 +5501,7 @@ function WidgetView() {
5277
5501
  window.addEventListener("message", handler);
5278
5502
  return () => window.removeEventListener("message", handler);
5279
5503
  }, [env?.embedMode]);
5280
- useEffect9(() => {
5504
+ useEffect10(() => {
5281
5505
  const handler = (e) => {
5282
5506
  const msg = asRecord(e.data);
5283
5507
  const msgType = readString(msg.type);
@@ -5311,7 +5535,7 @@ function WidgetView() {
5311
5535
  window.addEventListener("message", handler);
5312
5536
  return () => window.removeEventListener("message", handler);
5313
5537
  }, []);
5314
- useEffect9(() => {
5538
+ useEffect10(() => {
5315
5539
  if (!widgetToken) return;
5316
5540
  const postExpandResultToWidget = (target, result) => {
5317
5541
  if (!target || typeof target.postMessage !== "function") return;
@@ -5586,7 +5810,7 @@ function WidgetView() {
5586
5810
  xappId,
5587
5811
  t
5588
5812
  ]);
5589
- useEffect9(() => {
5813
+ useEffect10(() => {
5590
5814
  if (!widgetToken || !env?.locale) return;
5591
5815
  try {
5592
5816
  iframeRef.current?.contentWindow?.postMessage(
@@ -5604,6 +5828,11 @@ function WidgetView() {
5604
5828
  const params = new URLSearchParams({ token: widgetToken });
5605
5829
  const hostReturnUrl = readHostReturnUrl(loc.search);
5606
5830
  if (hostReturnUrl) params.set("xapps_host_return_url", hostReturnUrl);
5831
+ if (env?.embedMode && hostNestedExpandStage !== "inline") {
5832
+ params.set("xapps_host_overlay", "1");
5833
+ } else {
5834
+ params.delete("xapps_host_overlay");
5835
+ }
5607
5836
  const paymentParams = readPaymentEvidenceParams(loc.search);
5608
5837
  for (const [k, v] of paymentParams.entries()) {
5609
5838
  params.set(k, v);
@@ -5614,7 +5843,7 @@ function WidgetView() {
5614
5843
  return /* @__PURE__ */ jsxs11("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
5615
5844
  /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [
5616
5845
  /* @__PURE__ */ jsx15("button", { className: "mx-breadcrumb-link-btn", onClick: onBackToPortal, children: t("common.portal", void 0, "Portal") }),
5617
- !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5846
+ !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5618
5847
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5619
5848
  /* @__PURE__ */ jsx15(Link10, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") })
5620
5849
  ] }),
@@ -5635,7 +5864,7 @@ function WidgetView() {
5635
5864
  return /* @__PURE__ */ jsxs11("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
5636
5865
  /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [
5637
5866
  /* @__PURE__ */ jsx15("button", { className: "mx-breadcrumb-link-btn", onClick: onBackToPortal, children: t("common.portal", void 0, "Portal") }),
5638
- !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5867
+ !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5639
5868
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5640
5869
  /* @__PURE__ */ jsx15(Link10, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") })
5641
5870
  ] }),
@@ -5656,7 +5885,7 @@ function WidgetView() {
5656
5885
  return /* @__PURE__ */ jsxs11("div", { className: `mx-catalog-container ${isEmbedded ? "is-embedded" : ""}`, children: [
5657
5886
  /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [
5658
5887
  /* @__PURE__ */ jsx15("button", { className: "mx-breadcrumb-link-btn", onClick: onBackToPortal, children: t("common.portal", void 0, "Portal") }),
5659
- !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5888
+ !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5660
5889
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5661
5890
  /* @__PURE__ */ jsx15(Link10, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") })
5662
5891
  ] }),
@@ -5689,11 +5918,11 @@ function WidgetView() {
5689
5918
  children: [
5690
5919
  env?.embedMode && hostNestedExpandStage === "inline" && /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb mx-breadcrumb-top", children: [
5691
5920
  /* @__PURE__ */ jsx15("button", { className: "mx-breadcrumb-link-btn", onClick: onBackToPortal, children: t("common.portal", void 0, "Portal") }),
5692
- !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5921
+ !env?.singleXappMode && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5693
5922
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5694
5923
  /* @__PURE__ */ jsx15(Link10, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") })
5695
5924
  ] }),
5696
- xappTo && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5925
+ xappTo && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5697
5926
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5698
5927
  /* @__PURE__ */ jsx15(Link10, { to: xappTo, children: xappTitle || t("common.app", void 0, "App") })
5699
5928
  ] }),
@@ -5702,7 +5931,7 @@ function WidgetView() {
5702
5931
  ] }),
5703
5932
  !env?.embedMode && hostNestedExpandStage === "inline" && /* @__PURE__ */ jsxs11("div", { className: "mx-breadcrumb", children: [
5704
5933
  /* @__PURE__ */ jsx15(Link10, { to: marketplaceTo, children: t("common.marketplace", void 0, "Marketplace") }),
5705
- xappTo && /* @__PURE__ */ jsxs11(Fragment8, { children: [
5934
+ xappTo && /* @__PURE__ */ jsxs11(Fragment9, { children: [
5706
5935
  /* @__PURE__ */ jsx15("span", { className: "mx-breadcrumb-sep", children: "/" }),
5707
5936
  /* @__PURE__ */ jsx15(Link10, { to: xappTo, children: xappTitle || t("common.app", void 0, "App") })
5708
5937
  ] }),
@@ -5753,9 +5982,9 @@ function WidgetView() {
5753
5982
  }
5754
5983
 
5755
5984
  // src/pages/PublishersPage.tsx
5756
- import { useEffect as useEffect10, useMemo as useMemo9, useState as useState9 } from "react";
5985
+ import { useEffect as useEffect11, useMemo as useMemo9, useState as useState9 } from "react";
5757
5986
  import { Link as Link11, useLocation as useLocation9 } from "react-router-dom";
5758
- import { Fragment as Fragment9, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
5987
+ import { Fragment as Fragment10, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
5759
5988
  function useQueryToken9() {
5760
5989
  const loc = useLocation9();
5761
5990
  const qs = new URLSearchParams(loc.search);
@@ -5813,7 +6042,7 @@ function PublishersPage() {
5813
6042
  }
5814
6043
  setItems(Array.from(grouped.values()).sort((a, b) => a.name.localeCompare(b.name)));
5815
6044
  }
5816
- useEffect10(() => {
6045
+ useEffect11(() => {
5817
6046
  void (async () => {
5818
6047
  setBusy(true);
5819
6048
  setError(null);
@@ -5931,7 +6160,7 @@ function PublishersPage() {
5931
6160
  /* @__PURE__ */ jsx16("div", { className: "mx-skeleton-line mx-skeleton-line-title" }),
5932
6161
  /* @__PURE__ */ jsx16("div", { className: "mx-skeleton-line mx-skeleton-line-short" })
5933
6162
  ] })
5934
- ] }) }) }, i)) }) : /* @__PURE__ */ jsxs12(Fragment9, { children: [
6163
+ ] }) }) }, i)) }) : /* @__PURE__ */ jsxs12(Fragment10, { children: [
5935
6164
  !busy && /* @__PURE__ */ jsx16("div", { className: "mx-results-bar", children: /* @__PURE__ */ jsx16("div", { className: "mx-results-count", children: t(
5936
6165
  "publisher.results_count",
5937
6166
  { count: ordered.length, suffix: ordered.length === 1 ? "" : "s" },
@@ -6008,9 +6237,9 @@ function PublishersPage() {
6008
6237
  }
6009
6238
 
6010
6239
  // src/pages/PublisherDetailPage.tsx
6011
- import { useEffect as useEffect11, useMemo as useMemo10, useState as useState10 } from "react";
6240
+ import { useEffect as useEffect12, useMemo as useMemo10, useState as useState10 } from "react";
6012
6241
  import { Link as Link12, useLocation as useLocation10, useParams as useParams4 } from "react-router-dom";
6013
- import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
6242
+ import { Fragment as Fragment11, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
6014
6243
  function useQueryToken10() {
6015
6244
  const loc = useLocation10();
6016
6245
  const qs = new URLSearchParams(loc.search);
@@ -6049,7 +6278,7 @@ function PublisherDetailPage() {
6049
6278
  setBusy(false);
6050
6279
  }
6051
6280
  }
6052
- useEffect11(() => {
6281
+ useEffect12(() => {
6053
6282
  void refresh();
6054
6283
  }, [publisherSlug]);
6055
6284
  const publisherName = useMemo10(() => {
@@ -6140,7 +6369,7 @@ function PublisherDetailPage() {
6140
6369
  /* @__PURE__ */ jsx17("div", { className: "mx-skeleton-line mx-skeleton-line-full" }),
6141
6370
  /* @__PURE__ */ jsx17("div", { className: "mx-skeleton-line mx-skeleton-line-short" })
6142
6371
  ] })
6143
- ] }, i)) }) : /* @__PURE__ */ jsxs13(Fragment10, { children: [
6372
+ ] }, i)) }) : /* @__PURE__ */ jsxs13(Fragment11, { children: [
6144
6373
  !busy && /* @__PURE__ */ jsx17("div", { className: "mx-results-bar", children: /* @__PURE__ */ jsx17("div", { className: "mx-results-count", children: filteredItems.length === items.length ? `${filteredItems.length} xapp${filteredItems.length === 1 ? "" : "s"}` : `${filteredItems.length} of ${items.length} xapp${items.length === 1 ? "" : "s"}` }) }),
6145
6374
  /* @__PURE__ */ jsx17("div", { className: "mx-grid", children: filteredItems.length === 0 && !busy ? /* @__PURE__ */ jsxs13("div", { className: "mx-empty-catalog", children: [
6146
6375
  /* @__PURE__ */ jsx17("div", { className: "mx-empty-catalog-icon", children: "\u2315" }),