@primestyleai/tryon 5.10.194 → 5.10.196
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/PrimeStyleTryon.d.ts +6 -0
- package/dist/api-client.d.ts +42 -1
- package/dist/clarity.d.ts +13 -0
- package/dist/{index-BiotPzcm.js → index-8lZs7T93.js} +292 -156
- package/dist/index-8lZs7T93.js.map +1 -0
- package/dist/primestyle-tryon.js +173 -94
- package/dist/primestyle-tryon.js.map +1 -1
- package/dist/react/PrimeStyleTryonInner.d.ts +1 -1
- package/dist/react/index.js +5902 -5518
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/types.d.ts +2 -0
- package/dist/replay.d.ts +9 -0
- package/dist/storefront/primestyle-tryon.js +737 -117
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/index-BiotPzcm.js.map +0 -1
|
@@ -9321,53 +9321,6 @@ reactJsxRuntime_production_min.jsxs = q;
|
|
|
9321
9321
|
jsxRuntime.exports = reactJsxRuntime_production_min;
|
|
9322
9322
|
}
|
|
9323
9323
|
var jsxRuntimeExports = jsxRuntime.exports;
|
|
9324
|
-
function cx(base, override) {
|
|
9325
|
-
return override ? `${base} ${override}` : base;
|
|
9326
|
-
}
|
|
9327
|
-
const MOBILE_BREAKPOINT = 768;
|
|
9328
|
-
function useIsMobile() {
|
|
9329
|
-
const [isMobile, setIsMobile] = reactExports.useState(false);
|
|
9330
|
-
reactExports.useEffect(() => {
|
|
9331
|
-
if (typeof window === "undefined") return;
|
|
9332
|
-
const check = () => setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
9333
|
-
check();
|
|
9334
|
-
window.addEventListener("resize", check);
|
|
9335
|
-
return () => window.removeEventListener("resize", check);
|
|
9336
|
-
}, []);
|
|
9337
|
-
return isMobile;
|
|
9338
|
-
}
|
|
9339
|
-
function ErrorView({
|
|
9340
|
-
productImage,
|
|
9341
|
-
productTitle,
|
|
9342
|
-
onManualMeasurements,
|
|
9343
|
-
cn,
|
|
9344
|
-
t: t2
|
|
9345
|
-
}) {
|
|
9346
|
-
const isMobile = useIsMobile();
|
|
9347
|
-
const RightColumn = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-no-chart-content ps-tryon-error-fallback", cn.error), children: [
|
|
9348
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-icon ps-tryon-error-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "44", height: "44", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
9349
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 3l8.5 15H3.5L12 3z" }),
|
|
9350
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 9v4" }),
|
|
9351
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 17h.01" })
|
|
9352
|
-
] }) }),
|
|
9353
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-no-chart-title", children: t2("We couldn't find a matching size for you") }),
|
|
9354
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: cx("ps-tryon-no-chart-msg", cn.errorText), children: t2("Please try the manual measurement screen so we can calculate your fit from your measurements.") }),
|
|
9355
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-actions", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: onManualMeasurements, className: cx("ps-tryon-no-chart-cta", cn.submitButton), children: [
|
|
9356
|
-
t2("Try manual measurements"),
|
|
9357
|
-
" →"
|
|
9358
|
-
] }) })
|
|
9359
|
-
] });
|
|
9360
|
-
if (isMobile) {
|
|
9361
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr", children: [
|
|
9362
|
-
productImage && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-img-col", style: { flex: "0 0 auto", maxHeight: "38vh" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: productImage, alt: productTitle || "", className: "ps-tryon-sr-product-img" }) }),
|
|
9363
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-right-col", children: RightColumn })
|
|
9364
|
-
] });
|
|
9365
|
-
}
|
|
9366
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-split", children: [
|
|
9367
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-img-col", children: productImage && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: productImage, alt: productTitle || "", className: "ps-tryon-sr-product-img" }) }),
|
|
9368
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-right-col ps-tryon-no-chart-right-col", children: RightColumn })
|
|
9369
|
-
] }) });
|
|
9370
|
-
}
|
|
9371
9324
|
const STORAGE_KEY = "ps_session";
|
|
9372
9325
|
const MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
9373
9326
|
const FALLBACK_PREFIX = "ps_mem_";
|
|
@@ -9412,6 +9365,14 @@ function writeRecord(record) {
|
|
|
9412
9365
|
} catch {
|
|
9413
9366
|
}
|
|
9414
9367
|
}
|
|
9368
|
+
function attachReplaySession(sessionId) {
|
|
9369
|
+
if (typeof window === "undefined") return;
|
|
9370
|
+
try {
|
|
9371
|
+
const clarity = window.clarity;
|
|
9372
|
+
if (typeof clarity === "function") clarity("set", STORAGE_KEY, sessionId);
|
|
9373
|
+
} catch {
|
|
9374
|
+
}
|
|
9375
|
+
}
|
|
9415
9376
|
function getOrCreateSessionId() {
|
|
9416
9377
|
const now = Date.now();
|
|
9417
9378
|
const existing = readRecord();
|
|
@@ -9419,10 +9380,12 @@ function getOrCreateSessionId() {
|
|
|
9419
9380
|
if (now - existing.lastSeenAt > 5 * 60 * 1e3) {
|
|
9420
9381
|
writeRecord({ ...existing, lastSeenAt: now });
|
|
9421
9382
|
}
|
|
9383
|
+
attachReplaySession(existing.id);
|
|
9422
9384
|
return existing.id;
|
|
9423
9385
|
}
|
|
9424
9386
|
const fresh = { id: uuid(), issuedAt: now, lastSeenAt: now };
|
|
9425
9387
|
writeRecord(fresh);
|
|
9388
|
+
attachReplaySession(fresh.id);
|
|
9426
9389
|
return fresh.id;
|
|
9427
9390
|
}
|
|
9428
9391
|
function getDeviceHint() {
|
|
@@ -9433,6 +9396,16 @@ function getDeviceHint() {
|
|
|
9433
9396
|
return "desktop";
|
|
9434
9397
|
}
|
|
9435
9398
|
const DEFAULT_API_URL = "http://localhost:4000";
|
|
9399
|
+
function isShopifyProxyBase(baseUrl) {
|
|
9400
|
+
return /\/apps\/primestyle(?:\/|$)/.test(baseUrl) || /\/api\/proxy(?:\/|$)/.test(baseUrl);
|
|
9401
|
+
}
|
|
9402
|
+
function getShopDomain$2() {
|
|
9403
|
+
if (typeof window === "undefined") return null;
|
|
9404
|
+
const w2 = window;
|
|
9405
|
+
if (w2.Shopify?.shop) return w2.Shopify.shop;
|
|
9406
|
+
const hostname = window.location.hostname;
|
|
9407
|
+
return hostname.endsWith(".myshopify.com") ? hostname : null;
|
|
9408
|
+
}
|
|
9436
9409
|
class ApiClient {
|
|
9437
9410
|
constructor(apiKey, apiUrl) {
|
|
9438
9411
|
this.apiKey = apiKey || void 0;
|
|
@@ -9544,8 +9517,69 @@ class ApiClient {
|
|
|
9544
9517
|
}
|
|
9545
9518
|
return res.json();
|
|
9546
9519
|
}
|
|
9547
|
-
|
|
9548
|
-
const
|
|
9520
|
+
async reportEvent(input) {
|
|
9521
|
+
const res = await fetch(`${this.baseUrl}/api/v1/tryon/event`, {
|
|
9522
|
+
method: "POST",
|
|
9523
|
+
headers: this.headers,
|
|
9524
|
+
keepalive: true,
|
|
9525
|
+
body: JSON.stringify({
|
|
9526
|
+
...input,
|
|
9527
|
+
sessionId: getOrCreateSessionId(),
|
|
9528
|
+
deviceHint: getDeviceHint()
|
|
9529
|
+
})
|
|
9530
|
+
});
|
|
9531
|
+
if (!res.ok) {
|
|
9532
|
+
const data = await res.json().catch(() => ({}));
|
|
9533
|
+
throw new PrimeStyleError(
|
|
9534
|
+
data.message || "Failed to report SDK event",
|
|
9535
|
+
"EVENT_REPORT_FAILED"
|
|
9536
|
+
);
|
|
9537
|
+
}
|
|
9538
|
+
return res.json();
|
|
9539
|
+
}
|
|
9540
|
+
async reportClientError(input) {
|
|
9541
|
+
const res = await fetch(`${this.baseUrl}/api/v1/tryon/client-error`, {
|
|
9542
|
+
method: "POST",
|
|
9543
|
+
headers: this.headers,
|
|
9544
|
+
keepalive: true,
|
|
9545
|
+
body: JSON.stringify({
|
|
9546
|
+
...input,
|
|
9547
|
+
sessionId: getOrCreateSessionId(),
|
|
9548
|
+
deviceHint: getDeviceHint()
|
|
9549
|
+
})
|
|
9550
|
+
});
|
|
9551
|
+
if (!res.ok) {
|
|
9552
|
+
const data = await res.json().catch(() => ({}));
|
|
9553
|
+
throw new PrimeStyleError(
|
|
9554
|
+
data.message || "Failed to report SDK client error",
|
|
9555
|
+
"CLIENT_ERROR_REPORT_FAILED"
|
|
9556
|
+
);
|
|
9557
|
+
}
|
|
9558
|
+
return res.json();
|
|
9559
|
+
}
|
|
9560
|
+
async reportReplayChunk(input) {
|
|
9561
|
+
const shopifyProxy = isShopifyProxyBase(this.baseUrl);
|
|
9562
|
+
const shopDomain = shopifyProxy ? getShopDomain$2() : null;
|
|
9563
|
+
const url = shopifyProxy && shopDomain ? `${this.baseUrl}/events/replay` : `${this.baseUrl}/api/v1/tryon/replay`;
|
|
9564
|
+
const headers = shopifyProxy && shopDomain ? jsonHeaders() : this.headers;
|
|
9565
|
+
const body = shopifyProxy && shopDomain ? { shopDomain, ...input } : input;
|
|
9566
|
+
const res = await fetch(url, {
|
|
9567
|
+
method: "POST",
|
|
9568
|
+
headers,
|
|
9569
|
+
body: JSON.stringify(body)
|
|
9570
|
+
});
|
|
9571
|
+
if (!res.ok) {
|
|
9572
|
+
const data = await res.json().catch(() => ({}));
|
|
9573
|
+
throw new PrimeStyleError(
|
|
9574
|
+
data.message || "Failed to report SDK replay",
|
|
9575
|
+
"REPLAY_REPORT_FAILED"
|
|
9576
|
+
);
|
|
9577
|
+
}
|
|
9578
|
+
return res.json();
|
|
9579
|
+
}
|
|
9580
|
+
getStreamUrl(jobId) {
|
|
9581
|
+
const streamPath = jobId ? `/api/v1/tryon/stream/${encodeURIComponent(jobId)}` : "/api/v1/tryon/stream";
|
|
9582
|
+
const streamUrl = `${this.baseUrl}${streamPath}`;
|
|
9549
9583
|
return this.apiKey ? `${streamUrl}?key=${encodeURIComponent(this.apiKey)}` : streamUrl;
|
|
9550
9584
|
}
|
|
9551
9585
|
}
|
|
@@ -9561,6 +9595,89 @@ class PrimeStyleError extends Error {
|
|
|
9561
9595
|
this.code = code;
|
|
9562
9596
|
}
|
|
9563
9597
|
}
|
|
9598
|
+
function detectLocale() {
|
|
9599
|
+
if (typeof navigator === "undefined") return "US";
|
|
9600
|
+
const lang = navigator.language || "";
|
|
9601
|
+
const region = lang.split("-")[1]?.toUpperCase();
|
|
9602
|
+
if (region === "GB") return "UK";
|
|
9603
|
+
if (region) return region;
|
|
9604
|
+
const map = {
|
|
9605
|
+
en: "US",
|
|
9606
|
+
ja: "JP",
|
|
9607
|
+
ko: "KR",
|
|
9608
|
+
zh: "CN",
|
|
9609
|
+
fr: "FR",
|
|
9610
|
+
it: "IT",
|
|
9611
|
+
de: "DE",
|
|
9612
|
+
es: "ES",
|
|
9613
|
+
pt: "BR"
|
|
9614
|
+
};
|
|
9615
|
+
return map[lang.split("-")[0].toLowerCase()] || "US";
|
|
9616
|
+
}
|
|
9617
|
+
function getApiKey() {
|
|
9618
|
+
let key = "";
|
|
9619
|
+
try {
|
|
9620
|
+
key = "shopify-proxy";
|
|
9621
|
+
} catch {
|
|
9622
|
+
}
|
|
9623
|
+
return key;
|
|
9624
|
+
}
|
|
9625
|
+
function getApiUrl(override) {
|
|
9626
|
+
if (override) return override;
|
|
9627
|
+
let envUrl = "";
|
|
9628
|
+
try {
|
|
9629
|
+
envUrl = "";
|
|
9630
|
+
} catch {
|
|
9631
|
+
}
|
|
9632
|
+
return envUrl || "http://localhost:4000";
|
|
9633
|
+
}
|
|
9634
|
+
function cx(base, override) {
|
|
9635
|
+
return override ? `${base} ${override}` : base;
|
|
9636
|
+
}
|
|
9637
|
+
const MOBILE_BREAKPOINT = 768;
|
|
9638
|
+
function useIsMobile() {
|
|
9639
|
+
const [isMobile, setIsMobile] = reactExports.useState(false);
|
|
9640
|
+
reactExports.useEffect(() => {
|
|
9641
|
+
if (typeof window === "undefined") return;
|
|
9642
|
+
const check = () => setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
9643
|
+
check();
|
|
9644
|
+
window.addEventListener("resize", check);
|
|
9645
|
+
return () => window.removeEventListener("resize", check);
|
|
9646
|
+
}, []);
|
|
9647
|
+
return isMobile;
|
|
9648
|
+
}
|
|
9649
|
+
function ErrorView({
|
|
9650
|
+
productImage,
|
|
9651
|
+
productTitle,
|
|
9652
|
+
onManualMeasurements,
|
|
9653
|
+
cn,
|
|
9654
|
+
t: t2
|
|
9655
|
+
}) {
|
|
9656
|
+
const isMobile = useIsMobile();
|
|
9657
|
+
const RightColumn = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-no-chart-content ps-tryon-error-fallback", cn.error), children: [
|
|
9658
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-icon ps-tryon-error-fallback-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "44", height: "44", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
9659
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 3l8.5 15H3.5L12 3z" }),
|
|
9660
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 9v4" }),
|
|
9661
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 17h.01" })
|
|
9662
|
+
] }) }),
|
|
9663
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-no-chart-title", children: t2("We couldn't find a matching size for you") }),
|
|
9664
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: cx("ps-tryon-no-chart-msg", cn.errorText), children: t2("Please try the manual measurement screen so we can calculate your fit from your measurements.") }),
|
|
9665
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-actions", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", onClick: onManualMeasurements, className: cx("ps-tryon-no-chart-cta", cn.submitButton), children: [
|
|
9666
|
+
t2("Try manual measurements"),
|
|
9667
|
+
" →"
|
|
9668
|
+
] }) })
|
|
9669
|
+
] });
|
|
9670
|
+
if (isMobile) {
|
|
9671
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr", children: [
|
|
9672
|
+
productImage && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-img-col", style: { flex: "0 0 auto", maxHeight: "38vh" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: productImage, alt: productTitle || "", className: "ps-tryon-sr-product-img" }) }),
|
|
9673
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-right-col", children: RightColumn })
|
|
9674
|
+
] });
|
|
9675
|
+
}
|
|
9676
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-split", children: [
|
|
9677
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-img-col", children: productImage && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: productImage, alt: productTitle || "", className: "ps-tryon-sr-product-img" }) }),
|
|
9678
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-right-col ps-tryon-no-chart-right-col", children: RightColumn })
|
|
9679
|
+
] }) });
|
|
9680
|
+
}
|
|
9564
9681
|
class SseClient {
|
|
9565
9682
|
constructor(streamUrl) {
|
|
9566
9683
|
this.eventSource = null;
|
|
@@ -10932,42 +11049,6 @@ function installCartHook() {
|
|
|
10932
11049
|
}
|
|
10933
11050
|
console.log(TAG$1, "attribution hook installed");
|
|
10934
11051
|
}
|
|
10935
|
-
function detectLocale() {
|
|
10936
|
-
if (typeof navigator === "undefined") return "US";
|
|
10937
|
-
const lang = navigator.language || "";
|
|
10938
|
-
const region = lang.split("-")[1]?.toUpperCase();
|
|
10939
|
-
if (region === "GB") return "UK";
|
|
10940
|
-
if (region) return region;
|
|
10941
|
-
const map = {
|
|
10942
|
-
en: "US",
|
|
10943
|
-
ja: "JP",
|
|
10944
|
-
ko: "KR",
|
|
10945
|
-
zh: "CN",
|
|
10946
|
-
fr: "FR",
|
|
10947
|
-
it: "IT",
|
|
10948
|
-
de: "DE",
|
|
10949
|
-
es: "ES",
|
|
10950
|
-
pt: "BR"
|
|
10951
|
-
};
|
|
10952
|
-
return map[lang.split("-")[0].toLowerCase()] || "US";
|
|
10953
|
-
}
|
|
10954
|
-
function getApiKey() {
|
|
10955
|
-
let key = "";
|
|
10956
|
-
try {
|
|
10957
|
-
key = "shopify-proxy";
|
|
10958
|
-
} catch {
|
|
10959
|
-
}
|
|
10960
|
-
return key;
|
|
10961
|
-
}
|
|
10962
|
-
function getApiUrl(override) {
|
|
10963
|
-
if (override) return override;
|
|
10964
|
-
let envUrl = "";
|
|
10965
|
-
try {
|
|
10966
|
-
envUrl = "";
|
|
10967
|
-
} catch {
|
|
10968
|
-
}
|
|
10969
|
-
return envUrl || "http://localhost:4000";
|
|
10970
|
-
}
|
|
10971
11052
|
const SESSION_KEY = "primestyle_profile_session";
|
|
10972
11053
|
const AUTH_MESSAGE_TYPE = "PRIMESTYLE_SDK_AUTH";
|
|
10973
11054
|
const POPUP_TIMEOUT_MS = 12e4;
|
|
@@ -11150,6 +11231,30 @@ async function saveRemoteProfiles(apiUrl, accessToken, profiles, activeProfileId
|
|
|
11150
11231
|
});
|
|
11151
11232
|
return normalizeStore(await parseResponse(response));
|
|
11152
11233
|
}
|
|
11234
|
+
function shouldUseShopifyProxy(apiUrl) {
|
|
11235
|
+
if (typeof window === "undefined") return false;
|
|
11236
|
+
try {
|
|
11237
|
+
const w2 = window;
|
|
11238
|
+
if (w2.Shopify?.shop) return true;
|
|
11239
|
+
return /\/apps\/primestyle\/?$/.test(apiUrl);
|
|
11240
|
+
} catch {
|
|
11241
|
+
return false;
|
|
11242
|
+
}
|
|
11243
|
+
}
|
|
11244
|
+
function reportDirectSdkEvent(apiUrl, apiKey, body) {
|
|
11245
|
+
if (!apiKey || shouldUseShopifyProxy(apiUrl)) return;
|
|
11246
|
+
void fetch(`${apiUrl}/api/v1/tryon/event`, {
|
|
11247
|
+
method: "POST",
|
|
11248
|
+
headers: jsonHeaders(apiKey),
|
|
11249
|
+
keepalive: true,
|
|
11250
|
+
body: JSON.stringify({
|
|
11251
|
+
...body,
|
|
11252
|
+
sessionId: getOrCreateSessionId(),
|
|
11253
|
+
deviceHint: getDeviceHint()
|
|
11254
|
+
})
|
|
11255
|
+
}).catch(() => {
|
|
11256
|
+
});
|
|
11257
|
+
}
|
|
11153
11258
|
let cachedMP = null;
|
|
11154
11259
|
const MP_CACHE_TTL_MS = 6e4;
|
|
11155
11260
|
function setCachedMediaPipe(landmarks) {
|
|
@@ -11223,6 +11328,13 @@ async function recommendForProduct(input) {
|
|
|
11223
11328
|
recommendedSize: cached.recommendedSize,
|
|
11224
11329
|
fromCache: true
|
|
11225
11330
|
});
|
|
11331
|
+
reportDirectSdkEvent(apiUrl, apiKey, {
|
|
11332
|
+
eventType: "SIZE_RECOMMENDATION_SHOWN",
|
|
11333
|
+
productId: input.productId,
|
|
11334
|
+
productTitle: input.productTitle,
|
|
11335
|
+
recommendedSize: cached.recommendedSize,
|
|
11336
|
+
metadata: { fromCache: true, profileId: profile.id }
|
|
11337
|
+
});
|
|
11226
11338
|
const reconstructedRaw = cached.sectionsFull ? {
|
|
11227
11339
|
recommendedSize: cached.recommendedSize,
|
|
11228
11340
|
confidence: cached.confidence || "high",
|
|
@@ -11434,6 +11546,19 @@ async function recommendForProduct(input) {
|
|
|
11434
11546
|
size: result.recommendedSize,
|
|
11435
11547
|
recommendedSize: result.recommendedSize
|
|
11436
11548
|
});
|
|
11549
|
+
logSizeShown({
|
|
11550
|
+
productId: input.productId,
|
|
11551
|
+
productTitle: input.productTitle,
|
|
11552
|
+
recommendedSize: result.recommendedSize,
|
|
11553
|
+
fromCache: false
|
|
11554
|
+
});
|
|
11555
|
+
reportDirectSdkEvent(apiUrl, apiKey, {
|
|
11556
|
+
eventType: "SIZE_RECOMMENDATION_SHOWN",
|
|
11557
|
+
productId: input.productId,
|
|
11558
|
+
productTitle: input.productTitle,
|
|
11559
|
+
recommendedSize: result.recommendedSize,
|
|
11560
|
+
metadata: { fromCache: false, profileId: profile.id, found: result.found }
|
|
11561
|
+
});
|
|
11437
11562
|
return {
|
|
11438
11563
|
recommendedSize: result.recommendedSize,
|
|
11439
11564
|
confidence: result.confidence,
|
|
@@ -13117,7 +13242,7 @@ const STYLES = `
|
|
|
13117
13242
|
}
|
|
13118
13243
|
|
|
13119
13244
|
/* ── Product photo strip (single-garment, below the size card) ──
|
|
13120
|
-
|
|
13245
|
+
Two thumbnails per row, evenly spaced, auto-advances. Lives at
|
|
13121
13246
|
the bottom of the right panel as decoration / entertainment. */
|
|
13122
13247
|
.ps-tryon-photo-strip {
|
|
13123
13248
|
margin-top: 0.65vw;
|
|
@@ -13136,17 +13261,16 @@ const STYLES = `
|
|
|
13136
13261
|
}
|
|
13137
13262
|
.ps-tryon-photo-strip-row {
|
|
13138
13263
|
display: grid;
|
|
13139
|
-
grid-template-columns: repeat(
|
|
13264
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
13140
13265
|
gap: 0.45vw;
|
|
13141
13266
|
animation: ps-tryon-photo-strip-fade 0.5s ease;
|
|
13142
13267
|
}
|
|
13143
13268
|
.ps-tryon-photo-strip-row.ps-count-1 {
|
|
13144
|
-
grid-template-columns: minmax(0, calc((100% - 0.
|
|
13269
|
+
grid-template-columns: minmax(0, calc((100% - 0.45vw) / 2));
|
|
13145
13270
|
justify-content: center;
|
|
13146
13271
|
}
|
|
13147
13272
|
.ps-tryon-photo-strip-row.ps-count-2 {
|
|
13148
|
-
grid-template-columns: repeat(2, minmax(0,
|
|
13149
|
-
justify-content: center;
|
|
13273
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
13150
13274
|
}
|
|
13151
13275
|
.ps-tryon-photo-strip-cell {
|
|
13152
13276
|
position: relative;
|
|
@@ -13207,13 +13331,14 @@ const STYLES = `
|
|
|
13207
13331
|
gap: 8px;
|
|
13208
13332
|
}
|
|
13209
13333
|
.ps-tryon-photo-strip-row {
|
|
13210
|
-
grid-template-columns: repeat(
|
|
13334
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
13211
13335
|
}
|
|
13212
13336
|
.ps-tryon-photo-strip-row.ps-count-1 {
|
|
13213
|
-
grid-template-columns: minmax(0, calc((100% -
|
|
13337
|
+
grid-template-columns: minmax(0, calc((100% - 8px) / 2));
|
|
13338
|
+
justify-content: center;
|
|
13214
13339
|
}
|
|
13215
13340
|
.ps-tryon-photo-strip-row.ps-count-2 {
|
|
13216
|
-
grid-template-columns: repeat(2, minmax(0,
|
|
13341
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
13217
13342
|
}
|
|
13218
13343
|
.ps-tryon-photo-strip-cell {
|
|
13219
13344
|
aspect-ratio: 1 / 1; border-radius: 12px;
|
|
@@ -22458,16 +22583,16 @@ const STYLES = `
|
|
|
22458
22583
|
}
|
|
22459
22584
|
.ps-tryon-photo-strip-row {
|
|
22460
22585
|
display: grid !important;
|
|
22461
|
-
grid-template-columns: repeat(
|
|
22586
|
+
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
|
|
22462
22587
|
gap: 8px !important;
|
|
22463
22588
|
}
|
|
22464
22589
|
.ps-tryon-photo-strip-row.ps-count-1 {
|
|
22465
|
-
grid-template-columns: minmax(0, calc((100% -
|
|
22590
|
+
grid-template-columns: minmax(0, calc((100% - 8px) / 2)) !important;
|
|
22466
22591
|
justify-content: center !important;
|
|
22467
22592
|
}
|
|
22468
22593
|
.ps-tryon-photo-strip-row.ps-count-2 {
|
|
22469
|
-
grid-template-columns: repeat(2, minmax(0,
|
|
22470
|
-
justify-content:
|
|
22594
|
+
grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
|
|
22595
|
+
justify-content: stretch !important;
|
|
22471
22596
|
}
|
|
22472
22597
|
.ps-tryon-photo-strip-cell {
|
|
22473
22598
|
aspect-ratio: 1 / 1 !important;
|
|
@@ -23141,6 +23266,232 @@ const STYLES = `
|
|
|
23141
23266
|
}
|
|
23142
23267
|
}
|
|
23143
23268
|
`;
|
|
23269
|
+
const RRWEB_SCRIPT_URL = "https://cdn.jsdelivr.net/npm/rrweb@2.0.1/dist/rrweb.min.js";
|
|
23270
|
+
const CHUNK_SIZE = 20;
|
|
23271
|
+
const FLUSH_MS = 2500;
|
|
23272
|
+
const MAX_EVENT_JSON_BYTES = 5e6;
|
|
23273
|
+
const MAX_CHUNK_JSON_BYTES = 6e6;
|
|
23274
|
+
let globalSequence = 0;
|
|
23275
|
+
let rrwebLoadPromise = null;
|
|
23276
|
+
function estimateJsonBytes(value) {
|
|
23277
|
+
try {
|
|
23278
|
+
return JSON.stringify(value).length;
|
|
23279
|
+
} catch {
|
|
23280
|
+
return MAX_EVENT_JSON_BYTES + 1;
|
|
23281
|
+
}
|
|
23282
|
+
}
|
|
23283
|
+
function canRecord() {
|
|
23284
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
23285
|
+
}
|
|
23286
|
+
function getLoadedRrwebRecord() {
|
|
23287
|
+
const rrweb = window.rrweb;
|
|
23288
|
+
return typeof rrweb?.record === "function" ? rrweb.record : null;
|
|
23289
|
+
}
|
|
23290
|
+
function loadRrwebRecord() {
|
|
23291
|
+
const loaded = getLoadedRrwebRecord();
|
|
23292
|
+
if (loaded) return Promise.resolve(loaded);
|
|
23293
|
+
if (rrwebLoadPromise) return rrwebLoadPromise;
|
|
23294
|
+
rrwebLoadPromise = new Promise((resolve) => {
|
|
23295
|
+
const script = document.createElement("script");
|
|
23296
|
+
script.src = RRWEB_SCRIPT_URL;
|
|
23297
|
+
script.async = true;
|
|
23298
|
+
script.crossOrigin = "anonymous";
|
|
23299
|
+
script.onload = () => resolve(getLoadedRrwebRecord());
|
|
23300
|
+
script.onerror = () => resolve(null);
|
|
23301
|
+
document.head.appendChild(script);
|
|
23302
|
+
});
|
|
23303
|
+
return rrwebLoadPromise;
|
|
23304
|
+
}
|
|
23305
|
+
function startSdkReplay(input) {
|
|
23306
|
+
if (!canRecord()) return () => {
|
|
23307
|
+
};
|
|
23308
|
+
const sessionId = getOrCreateSessionId();
|
|
23309
|
+
const queue = [];
|
|
23310
|
+
let stopped = false;
|
|
23311
|
+
let timer = null;
|
|
23312
|
+
let stopRecord;
|
|
23313
|
+
const flush = (all = false) => {
|
|
23314
|
+
if (timer) {
|
|
23315
|
+
window.clearTimeout(timer);
|
|
23316
|
+
timer = null;
|
|
23317
|
+
}
|
|
23318
|
+
if (!queue.length) return;
|
|
23319
|
+
do {
|
|
23320
|
+
const events = [];
|
|
23321
|
+
let chunkBytes = 0;
|
|
23322
|
+
while (queue.length && events.length < CHUNK_SIZE) {
|
|
23323
|
+
const event = queue[0];
|
|
23324
|
+
const eventBytes = estimateJsonBytes(event);
|
|
23325
|
+
if (events.length && chunkBytes + eventBytes > MAX_CHUNK_JSON_BYTES) break;
|
|
23326
|
+
events.push(queue.shift());
|
|
23327
|
+
chunkBytes += eventBytes;
|
|
23328
|
+
if (chunkBytes >= MAX_CHUNK_JSON_BYTES) break;
|
|
23329
|
+
}
|
|
23330
|
+
if (!events.length) events.push(queue.shift());
|
|
23331
|
+
const sequence = globalSequence++;
|
|
23332
|
+
void input.client.reportReplayChunk({
|
|
23333
|
+
sessionId,
|
|
23334
|
+
sequence,
|
|
23335
|
+
events,
|
|
23336
|
+
productId: input.productId,
|
|
23337
|
+
productTitle: input.productTitle,
|
|
23338
|
+
productUrl: input.productUrl,
|
|
23339
|
+
deviceHint: getDeviceHint()
|
|
23340
|
+
}).catch((error) => {
|
|
23341
|
+
console.warn("[ps-sdk:replay] failed to upload replay chunk", error);
|
|
23342
|
+
});
|
|
23343
|
+
} while (all && queue.length);
|
|
23344
|
+
if (queue.length) scheduleFlush(0);
|
|
23345
|
+
};
|
|
23346
|
+
const scheduleFlush = (delay = FLUSH_MS) => {
|
|
23347
|
+
if (stopped || timer) return;
|
|
23348
|
+
timer = window.setTimeout(flush, delay);
|
|
23349
|
+
};
|
|
23350
|
+
void loadRrwebRecord().then((record) => {
|
|
23351
|
+
if (!record || stopped) return;
|
|
23352
|
+
stopRecord = record({
|
|
23353
|
+
emit(event) {
|
|
23354
|
+
if (stopped) return;
|
|
23355
|
+
if (estimateJsonBytes(event) > MAX_EVENT_JSON_BYTES) return;
|
|
23356
|
+
queue.push(event);
|
|
23357
|
+
if (queue.length >= CHUNK_SIZE) flush();
|
|
23358
|
+
else scheduleFlush();
|
|
23359
|
+
},
|
|
23360
|
+
checkoutEveryNms: 1e4,
|
|
23361
|
+
maskAllInputs: false,
|
|
23362
|
+
maskInputOptions: {
|
|
23363
|
+
password: true,
|
|
23364
|
+
email: true,
|
|
23365
|
+
tel: true
|
|
23366
|
+
},
|
|
23367
|
+
blockClass: "ps-replay-block",
|
|
23368
|
+
blockSelector: "body > *:not([data-ps-tryon-portal]):not(.ps-tryon-root)",
|
|
23369
|
+
inlineStylesheet: true,
|
|
23370
|
+
inlineImages: true,
|
|
23371
|
+
collectFonts: false,
|
|
23372
|
+
recordCanvas: false,
|
|
23373
|
+
recordCrossOriginIframes: false,
|
|
23374
|
+
slimDOMOptions: {
|
|
23375
|
+
script: true,
|
|
23376
|
+
comment: true,
|
|
23377
|
+
headFavicon: true,
|
|
23378
|
+
headMetaDescKeywords: true,
|
|
23379
|
+
headMetaSocial: true,
|
|
23380
|
+
headMetaRobots: true,
|
|
23381
|
+
headMetaHttpEquiv: true,
|
|
23382
|
+
headMetaAuthorship: true,
|
|
23383
|
+
headMetaVerification: true
|
|
23384
|
+
},
|
|
23385
|
+
sampling: {
|
|
23386
|
+
mousemove: 80,
|
|
23387
|
+
mouseInteraction: true,
|
|
23388
|
+
scroll: 150,
|
|
23389
|
+
media: 800,
|
|
23390
|
+
input: "last"
|
|
23391
|
+
},
|
|
23392
|
+
errorHandler(error) {
|
|
23393
|
+
console.warn("[ps-sdk:replay] recorder error", error);
|
|
23394
|
+
}
|
|
23395
|
+
});
|
|
23396
|
+
});
|
|
23397
|
+
return () => {
|
|
23398
|
+
stopped = true;
|
|
23399
|
+
if (timer) {
|
|
23400
|
+
window.clearTimeout(timer);
|
|
23401
|
+
timer = null;
|
|
23402
|
+
}
|
|
23403
|
+
try {
|
|
23404
|
+
stopRecord?.();
|
|
23405
|
+
} catch {
|
|
23406
|
+
}
|
|
23407
|
+
flush(true);
|
|
23408
|
+
};
|
|
23409
|
+
}
|
|
23410
|
+
var define_process_env_default = {};
|
|
23411
|
+
const SCRIPT_ID_PREFIX = "ps-clarity-script";
|
|
23412
|
+
const DEFAULT_PROJECT_ID = "wwb75cfm2z";
|
|
23413
|
+
let initializedProjectId = null;
|
|
23414
|
+
function cleanProjectId(value) {
|
|
23415
|
+
const trimmed = String(value || "").trim();
|
|
23416
|
+
if (!trimmed) return null;
|
|
23417
|
+
return /^[a-z0-9]+$/i.test(trimmed) ? trimmed : null;
|
|
23418
|
+
}
|
|
23419
|
+
function readEnvProjectId() {
|
|
23420
|
+
let id2 = "";
|
|
23421
|
+
try {
|
|
23422
|
+
id2 = define_process_env_default.NEXT_PUBLIC_PRIMESTYLE_CLARITY_PROJECT_ID ?? "";
|
|
23423
|
+
} catch {
|
|
23424
|
+
}
|
|
23425
|
+
if (!id2) {
|
|
23426
|
+
try {
|
|
23427
|
+
id2 = define_process_env_default.NEXT_PUBLIC_CLARITY_PROJECT_ID ?? "";
|
|
23428
|
+
} catch {
|
|
23429
|
+
}
|
|
23430
|
+
}
|
|
23431
|
+
return cleanProjectId(id2);
|
|
23432
|
+
}
|
|
23433
|
+
function readWindowProjectId() {
|
|
23434
|
+
if (typeof window === "undefined") return null;
|
|
23435
|
+
const w2 = window;
|
|
23436
|
+
return cleanProjectId(w2.PrimeStyleAIClarityProjectId || w2.PRIMESTYLE_CLARITY_PROJECT_ID);
|
|
23437
|
+
}
|
|
23438
|
+
function resolveSdkClarityProjectId(projectId) {
|
|
23439
|
+
return cleanProjectId(projectId) || readWindowProjectId() || readEnvProjectId() || DEFAULT_PROJECT_ID;
|
|
23440
|
+
}
|
|
23441
|
+
function getClarity() {
|
|
23442
|
+
if (typeof window === "undefined") return null;
|
|
23443
|
+
const clarity = window.clarity;
|
|
23444
|
+
return typeof clarity === "function" ? clarity : null;
|
|
23445
|
+
}
|
|
23446
|
+
function installClarity(projectId) {
|
|
23447
|
+
if (typeof window === "undefined" || typeof document === "undefined") return null;
|
|
23448
|
+
const scriptId = `${SCRIPT_ID_PREFIX}-${projectId}`;
|
|
23449
|
+
if (!document.getElementById(scriptId)) {
|
|
23450
|
+
((c, l2, a, r2, i) => {
|
|
23451
|
+
c[a] = c[a] || function(...args) {
|
|
23452
|
+
const queued = c[a];
|
|
23453
|
+
(queued.q = queued.q || []).push(args);
|
|
23454
|
+
};
|
|
23455
|
+
const script = l2.createElement(r2);
|
|
23456
|
+
const firstScript = l2.getElementsByTagName(r2)[0];
|
|
23457
|
+
script.id = scriptId;
|
|
23458
|
+
script.async = true;
|
|
23459
|
+
script.src = "https://www.clarity.ms/tag/" + i;
|
|
23460
|
+
firstScript?.parentNode?.insertBefore(script, firstScript);
|
|
23461
|
+
})(window, document, "clarity", "script", projectId);
|
|
23462
|
+
}
|
|
23463
|
+
return getClarity();
|
|
23464
|
+
}
|
|
23465
|
+
function setTag(key, value) {
|
|
23466
|
+
const clarity = getClarity();
|
|
23467
|
+
if (!clarity || value === void 0 || value === null || value === "") return;
|
|
23468
|
+
try {
|
|
23469
|
+
clarity("set", key, String(value).slice(0, 512));
|
|
23470
|
+
} catch {
|
|
23471
|
+
}
|
|
23472
|
+
}
|
|
23473
|
+
function tagSdkClaritySession(input = {}) {
|
|
23474
|
+
const sessionId = getOrCreateSessionId();
|
|
23475
|
+
setTag("ps_session", sessionId);
|
|
23476
|
+
setTag("ps_sdk_session", sessionId);
|
|
23477
|
+
setTag("ps_product_id", input.productId || void 0);
|
|
23478
|
+
setTag("ps_product_title", input.productTitle || void 0);
|
|
23479
|
+
setTag("ps_product_url", input.productUrl || void 0);
|
|
23480
|
+
setTag("ps_sdk_view", input.view || void 0);
|
|
23481
|
+
setTag("ps_tryon_job_id", input.jobId || void 0);
|
|
23482
|
+
setTag("ps_source", input.source || void 0);
|
|
23483
|
+
}
|
|
23484
|
+
function startSdkClarity(input = {}) {
|
|
23485
|
+
if (typeof window === "undefined" || typeof document === "undefined") return false;
|
|
23486
|
+
const projectId = resolveSdkClarityProjectId(input.projectId);
|
|
23487
|
+
{
|
|
23488
|
+
initializedProjectId = initializedProjectId || projectId;
|
|
23489
|
+
installClarity(initializedProjectId);
|
|
23490
|
+
}
|
|
23491
|
+
if (!getClarity()) return false;
|
|
23492
|
+
tagSdkClaritySession(input);
|
|
23493
|
+
return true;
|
|
23494
|
+
}
|
|
23144
23495
|
function CameraIcon$1({ size = 18 }) {
|
|
23145
23496
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
23146
23497
|
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
|
|
@@ -24327,8 +24678,8 @@ function MultiSectionMobile({
|
|
|
24327
24678
|
sizeGuide ? null : null
|
|
24328
24679
|
] });
|
|
24329
24680
|
}
|
|
24330
|
-
const PER_SLIDE =
|
|
24331
|
-
const CYCLE_MS =
|
|
24681
|
+
const PER_SLIDE = 2;
|
|
24682
|
+
const CYCLE_MS = 2500;
|
|
24332
24683
|
function ProductPhotoCarouselCard({
|
|
24333
24684
|
photos,
|
|
24334
24685
|
items,
|
|
@@ -34632,6 +34983,7 @@ function PrimeStyleTryonInner({
|
|
|
34632
34983
|
continueShoppingLabel,
|
|
34633
34984
|
backToProductPageLabel,
|
|
34634
34985
|
sizeGuideData,
|
|
34986
|
+
clarityProjectId,
|
|
34635
34987
|
initialView,
|
|
34636
34988
|
initialBodyProfileStep
|
|
34637
34989
|
}) {
|
|
@@ -35031,7 +35383,7 @@ function PrimeStyleTryonInner({
|
|
|
35031
35383
|
const key = getApiKey();
|
|
35032
35384
|
const url = getApiUrl(apiUrl);
|
|
35033
35385
|
apiRef.current = new ApiClient(key, url);
|
|
35034
|
-
sseRef.current =
|
|
35386
|
+
sseRef.current = null;
|
|
35035
35387
|
} catch {
|
|
35036
35388
|
}
|
|
35037
35389
|
return () => {
|
|
@@ -35040,6 +35392,76 @@ function PrimeStyleTryonInner({
|
|
|
35040
35392
|
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
35041
35393
|
};
|
|
35042
35394
|
}, [apiUrl]);
|
|
35395
|
+
const sdkReplayOpen = view !== "idle";
|
|
35396
|
+
reactExports.useEffect(() => {
|
|
35397
|
+
if (!sdkReplayOpen) return void 0;
|
|
35398
|
+
const client = apiRef.current;
|
|
35399
|
+
if (!client) return void 0;
|
|
35400
|
+
return startSdkReplay({
|
|
35401
|
+
client,
|
|
35402
|
+
productId: effectiveProductId,
|
|
35403
|
+
productTitle: restoredProductTitle || productTitle,
|
|
35404
|
+
productUrl: restoredProductUrl || effectiveProductUrl
|
|
35405
|
+
});
|
|
35406
|
+
}, [sdkReplayOpen, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl]);
|
|
35407
|
+
reactExports.useEffect(() => {
|
|
35408
|
+
if (!sdkReplayOpen) return;
|
|
35409
|
+
startSdkClarity({
|
|
35410
|
+
projectId: clarityProjectId,
|
|
35411
|
+
productId: effectiveProductId,
|
|
35412
|
+
productTitle: restoredProductTitle || productTitle,
|
|
35413
|
+
productUrl: restoredProductUrl || effectiveProductUrl,
|
|
35414
|
+
view,
|
|
35415
|
+
jobId: currentTryOnJobIdRef.current,
|
|
35416
|
+
source: shouldUseShopifyCartAttribution(apiUrl) ? "shopify-sdk" : "sdk"
|
|
35417
|
+
});
|
|
35418
|
+
}, [apiUrl, clarityProjectId, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl, sdkReplayOpen, view]);
|
|
35419
|
+
const reportSdkEvent = reactExports.useCallback((eventType, input = {}) => {
|
|
35420
|
+
if (shouldUseShopifyCartAttribution(apiUrl)) return;
|
|
35421
|
+
const client = apiRef.current;
|
|
35422
|
+
if (!client) return;
|
|
35423
|
+
void client.reportEvent({
|
|
35424
|
+
eventType,
|
|
35425
|
+
productId: effectiveProductId,
|
|
35426
|
+
productTitle: restoredProductTitle || productTitle,
|
|
35427
|
+
productUrl: restoredProductUrl || effectiveProductUrl,
|
|
35428
|
+
jobId: input.jobId ?? currentTryOnJobIdRef.current ?? void 0,
|
|
35429
|
+
recommendedSize: input.recommendedSize ?? sizingResultRef.current?.recommendedSize,
|
|
35430
|
+
metadata: input.metadata
|
|
35431
|
+
}).catch(() => {
|
|
35432
|
+
});
|
|
35433
|
+
}, [apiUrl, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl]);
|
|
35434
|
+
const reportSdkClientError = reactExports.useCallback((input) => {
|
|
35435
|
+
if (shouldUseShopifyCartAttribution(apiUrl)) return;
|
|
35436
|
+
const client = apiRef.current;
|
|
35437
|
+
if (!client) return;
|
|
35438
|
+
void client.reportClientError({
|
|
35439
|
+
...input,
|
|
35440
|
+
productId: effectiveProductId,
|
|
35441
|
+
productTitle: restoredProductTitle || productTitle,
|
|
35442
|
+
productUrl: restoredProductUrl || effectiveProductUrl,
|
|
35443
|
+
jobId: input.jobId ?? currentTryOnJobIdRef.current ?? void 0
|
|
35444
|
+
}).catch(() => {
|
|
35445
|
+
});
|
|
35446
|
+
}, [apiUrl, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl]);
|
|
35447
|
+
const productViewLoggedRef = reactExports.useRef(null);
|
|
35448
|
+
reactExports.useEffect(() => {
|
|
35449
|
+
const key = `${effectiveProductId || ""}|${effectiveProductUrl || ""}`;
|
|
35450
|
+
if (!key.trim() || productViewLoggedRef.current === key) return;
|
|
35451
|
+
productViewLoggedRef.current = key;
|
|
35452
|
+
if (shouldUseShopifyCartAttribution(apiUrl)) {
|
|
35453
|
+
logProductView({ productId: effectiveProductId, productTitle });
|
|
35454
|
+
return;
|
|
35455
|
+
}
|
|
35456
|
+
reportSdkEvent("PRODUCT_VIEW", {
|
|
35457
|
+
metadata: {
|
|
35458
|
+
productUrl: effectiveProductUrl,
|
|
35459
|
+
productFitType: resolvedProductFitType,
|
|
35460
|
+
productCategory,
|
|
35461
|
+
productSubcategory
|
|
35462
|
+
}
|
|
35463
|
+
});
|
|
35464
|
+
}, [apiUrl, effectiveProductId, effectiveProductUrl, productCategory, productSubcategory, productTitle, reportSdkEvent, resolvedProductFitType]);
|
|
35043
35465
|
const pickFireCountRef = reactExports.useRef(0);
|
|
35044
35466
|
const toBackendFetchableImageUrl = reactExports.useCallback((url) => {
|
|
35045
35467
|
const trimmed = String(url || "").trim();
|
|
@@ -35580,10 +36002,11 @@ function PrimeStyleTryonInner({
|
|
|
35580
36002
|
});
|
|
35581
36003
|
const handleOpen = reactExports.useCallback(() => {
|
|
35582
36004
|
console.log("[ps-sdk] handleOpen fired — opening modal");
|
|
36005
|
+
reportSdkEvent("SDK_OPENED", { metadata: { view: "body-profile" } });
|
|
35583
36006
|
setBodyProfileInitialStep(null);
|
|
35584
36007
|
setView("body-profile");
|
|
35585
36008
|
onOpen?.();
|
|
35586
|
-
}, [onOpen]);
|
|
36009
|
+
}, [onOpen, reportSdkEvent]);
|
|
35587
36010
|
const handleClose = reactExports.useCallback(() => {
|
|
35588
36011
|
const tryOnInFlight = tryOnProcessing;
|
|
35589
36012
|
setView("idle");
|
|
@@ -35673,12 +36096,28 @@ function PrimeStyleTryonInner({
|
|
|
35673
36096
|
if (!isValidImageFile(file)) {
|
|
35674
36097
|
setErrorMessage(t2("Please upload a JPEG, PNG, or WebP image."));
|
|
35675
36098
|
setView("error");
|
|
36099
|
+
reportSdkClientError({
|
|
36100
|
+
message: "Invalid image file type",
|
|
36101
|
+
code: "INVALID_FILE",
|
|
36102
|
+
component: "PhotoUpload",
|
|
36103
|
+
view,
|
|
36104
|
+
severity: "low",
|
|
36105
|
+
metadata: { fileType: file.type, fileSize: file.size }
|
|
36106
|
+
});
|
|
35676
36107
|
onError?.({ message: "Invalid file type", code: "INVALID_FILE" });
|
|
35677
36108
|
return;
|
|
35678
36109
|
}
|
|
35679
36110
|
if (file.size > 10 * 1024 * 1024) {
|
|
35680
36111
|
setErrorMessage(t2("Image must be under 10MB."));
|
|
35681
36112
|
setView("error");
|
|
36113
|
+
reportSdkClientError({
|
|
36114
|
+
message: "Image file too large",
|
|
36115
|
+
code: "FILE_TOO_LARGE",
|
|
36116
|
+
component: "PhotoUpload",
|
|
36117
|
+
view,
|
|
36118
|
+
severity: "low",
|
|
36119
|
+
metadata: { fileType: file.type, fileSize: file.size }
|
|
36120
|
+
});
|
|
35682
36121
|
onError?.({ message: "File too large", code: "FILE_TOO_LARGE" });
|
|
35683
36122
|
return;
|
|
35684
36123
|
}
|
|
@@ -35687,13 +36126,23 @@ function PrimeStyleTryonInner({
|
|
|
35687
36126
|
modelImageIdRef.current = null;
|
|
35688
36127
|
const objUrl = URL.createObjectURL(file);
|
|
35689
36128
|
setPreviewUrl(objUrl);
|
|
36129
|
+
reportSdkEvent("PHOTO_UPLOADED", {
|
|
36130
|
+
metadata: { fileType: file.type, fileSize: file.size, view }
|
|
36131
|
+
});
|
|
35690
36132
|
onUpload?.(file);
|
|
35691
36133
|
modelPoseRef.current = null;
|
|
35692
36134
|
detectMeasurementLines(objUrl).then((lines) => {
|
|
35693
36135
|
modelPoseRef.current = lines;
|
|
35694
|
-
}).catch(() => {
|
|
36136
|
+
}).catch((error) => {
|
|
36137
|
+
reportSdkClientError({
|
|
36138
|
+
message: error instanceof Error ? error.message : "Pose detection failed",
|
|
36139
|
+
code: "POSE_DETECTION_FAILED",
|
|
36140
|
+
component: "MediaPipe",
|
|
36141
|
+
view,
|
|
36142
|
+
severity: "low"
|
|
36143
|
+
});
|
|
35695
36144
|
});
|
|
35696
|
-
}, [onUpload, onError]);
|
|
36145
|
+
}, [onUpload, onError, reportSdkClientError, reportSdkEvent, t2, view]);
|
|
35697
36146
|
const handleRemovePreview = reactExports.useCallback(() => {
|
|
35698
36147
|
setSelectedFile(null);
|
|
35699
36148
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
@@ -35762,12 +36211,21 @@ function PrimeStyleTryonInner({
|
|
|
35762
36211
|
setTryOnProcessing(false);
|
|
35763
36212
|
setTryOnStartedAt(null);
|
|
35764
36213
|
const msg = update.error || t2("Try-on generation failed");
|
|
36214
|
+
reportSdkClientError({
|
|
36215
|
+
message: msg,
|
|
36216
|
+
code: "TRYON_GENERATION_FAILED",
|
|
36217
|
+
component: "TryOn",
|
|
36218
|
+
view,
|
|
36219
|
+
severity: "medium",
|
|
36220
|
+
jobId: update.galleryId,
|
|
36221
|
+
metadata: { status: update.status }
|
|
36222
|
+
});
|
|
35765
36223
|
setErrorMessage(msg);
|
|
35766
36224
|
setView("error");
|
|
35767
36225
|
onError?.({ message: msg });
|
|
35768
36226
|
}
|
|
35769
36227
|
}
|
|
35770
|
-
}, [apiUrl, effectiveProductId, productTitle, onComplete, onError, cleanupJob]);
|
|
36228
|
+
}, [apiUrl, effectiveProductId, productTitle, onComplete, onError, cleanupJob, reportSdkClientError, t2, view]);
|
|
35771
36229
|
const dynamicFields = reactExports.useMemo(() => {
|
|
35772
36230
|
if (sizeGuide?.found && sizeGuide.requiredFields && sizeGuide.requiredFields.length > 0) {
|
|
35773
36231
|
return sizeGuide.requiredFields;
|
|
@@ -35781,6 +36239,14 @@ function PrimeStyleTryonInner({
|
|
|
35781
36239
|
const method = methodOverride || sizingMethod;
|
|
35782
36240
|
const baseUrl = getApiUrl(apiUrl);
|
|
35783
36241
|
const key = getApiKey();
|
|
36242
|
+
reportSdkEvent("SIZING_STARTED", {
|
|
36243
|
+
metadata: {
|
|
36244
|
+
method,
|
|
36245
|
+
measurementType,
|
|
36246
|
+
productFitType: resolvedProductFitType,
|
|
36247
|
+
hasSizeGuide: !!sizeGuide?.found
|
|
36248
|
+
}
|
|
36249
|
+
});
|
|
35784
36250
|
if (measurementType === "face" || measurementType === "head") {
|
|
35785
36251
|
const f2 = formRef.current;
|
|
35786
36252
|
const toNum = (v2) => {
|
|
@@ -35839,16 +36305,42 @@ function PrimeStyleTryonInner({
|
|
|
35839
36305
|
const data = await resp.json();
|
|
35840
36306
|
await minVisible;
|
|
35841
36307
|
if (data?.found === false) {
|
|
36308
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36309
|
+
metadata: {
|
|
36310
|
+
reason: data?.reasoning || "NO_MATCH",
|
|
36311
|
+
measurementType,
|
|
36312
|
+
found: false
|
|
36313
|
+
}
|
|
36314
|
+
});
|
|
35842
36315
|
setNoSizeReason(data?.reasoning === "NO_SIZE_CHART" ? "no-chart" : "no-match");
|
|
35843
36316
|
setView("no-chart");
|
|
35844
36317
|
setEstimationDone(true);
|
|
35845
36318
|
return;
|
|
35846
36319
|
}
|
|
35847
36320
|
setSizingResult(data);
|
|
36321
|
+
reportSdkEvent("SIZE_RECOMMENDATION_SHOWN", {
|
|
36322
|
+
recommendedSize: data?.recommendedSize,
|
|
36323
|
+
metadata: {
|
|
36324
|
+
confidence: data?.confidence,
|
|
36325
|
+
measurementType,
|
|
36326
|
+
source: "face-recommend"
|
|
36327
|
+
}
|
|
36328
|
+
});
|
|
35848
36329
|
onComplete?.(data);
|
|
35849
36330
|
} else {
|
|
35850
36331
|
const body = await resp.text().catch(() => "");
|
|
35851
36332
|
console.error("[PS-SDK] face-recommend failed:", resp.status, body);
|
|
36333
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36334
|
+
metadata: { status: resp.status, measurementType, source: "face-recommend" }
|
|
36335
|
+
});
|
|
36336
|
+
reportSdkClientError({
|
|
36337
|
+
message: body || "Face/head sizing request failed",
|
|
36338
|
+
code: "FACE_RECOMMEND_FAILED",
|
|
36339
|
+
component: "Sizing",
|
|
36340
|
+
view,
|
|
36341
|
+
severity: "medium",
|
|
36342
|
+
metadata: { status: resp.status, measurementType }
|
|
36343
|
+
});
|
|
35852
36344
|
await minVisible;
|
|
35853
36345
|
setErrorMessage(t2("Unable to get a size suggestion. Please try again."));
|
|
35854
36346
|
setView("error");
|
|
@@ -35856,6 +36348,18 @@ function PrimeStyleTryonInner({
|
|
|
35856
36348
|
}
|
|
35857
36349
|
} catch (err) {
|
|
35858
36350
|
console.error("[PS-SDK] face-recommend network error:", err);
|
|
36351
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36352
|
+
metadata: { measurementType, source: "face-recommend", network: true }
|
|
36353
|
+
});
|
|
36354
|
+
reportSdkClientError({
|
|
36355
|
+
message: err instanceof Error ? err.message : "Face/head sizing network error",
|
|
36356
|
+
code: "FACE_RECOMMEND_NETWORK_ERROR",
|
|
36357
|
+
stack: err instanceof Error ? err.stack : void 0,
|
|
36358
|
+
component: "Sizing",
|
|
36359
|
+
view,
|
|
36360
|
+
severity: "medium",
|
|
36361
|
+
metadata: { measurementType }
|
|
36362
|
+
});
|
|
35859
36363
|
await minVisible;
|
|
35860
36364
|
setErrorMessage(t2("Unable to connect to sizing service. Please try again."));
|
|
35861
36365
|
setView("error");
|
|
@@ -35916,6 +36420,17 @@ function PrimeStyleTryonInner({
|
|
|
35916
36420
|
const qWeight = parseFloat(formRef.current.weight || "0");
|
|
35917
36421
|
if (!qHeight || !qWeight) {
|
|
35918
36422
|
console.error("[PS-SDK] submitSizing ABORT — qHeight:", qHeight, "qWeight:", qWeight, "formRef:", JSON.stringify(formRef.current));
|
|
36423
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36424
|
+
metadata: { reason: "missing_height_or_weight", method, measurementType }
|
|
36425
|
+
});
|
|
36426
|
+
reportSdkClientError({
|
|
36427
|
+
message: "Sizing submitted without height or weight",
|
|
36428
|
+
code: "SIZING_INPUT_MISSING",
|
|
36429
|
+
component: "Sizing",
|
|
36430
|
+
view,
|
|
36431
|
+
severity: "low",
|
|
36432
|
+
metadata: { method, measurementType, qHeight, qWeight }
|
|
36433
|
+
});
|
|
35919
36434
|
setSizingLoading(false);
|
|
35920
36435
|
return;
|
|
35921
36436
|
}
|
|
@@ -35948,12 +36463,29 @@ function PrimeStyleTryonInner({
|
|
|
35948
36463
|
const data = await res.json();
|
|
35949
36464
|
console.log("[PS-SDK] Sizing recommend RESULT:", JSON.stringify(data));
|
|
35950
36465
|
if (data?.found === false) {
|
|
36466
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36467
|
+
metadata: {
|
|
36468
|
+
reason: data?.reasoning || "NO_MATCH",
|
|
36469
|
+
method,
|
|
36470
|
+
measurementType,
|
|
36471
|
+
found: false
|
|
36472
|
+
}
|
|
36473
|
+
});
|
|
35951
36474
|
setNoSizeReason(data?.reasoning === "NO_SIZE_CHART" ? "no-chart" : "no-match");
|
|
35952
36475
|
setView("no-chart");
|
|
35953
36476
|
setEstimationDone(true);
|
|
35954
36477
|
return;
|
|
35955
36478
|
}
|
|
35956
36479
|
setSizingResult(data);
|
|
36480
|
+
reportSdkEvent("SIZE_RECOMMENDATION_SHOWN", {
|
|
36481
|
+
recommendedSize: data?.recommendedSize,
|
|
36482
|
+
metadata: {
|
|
36483
|
+
confidence: data?.confidence,
|
|
36484
|
+
method,
|
|
36485
|
+
measurementType,
|
|
36486
|
+
found: data?.found
|
|
36487
|
+
}
|
|
36488
|
+
});
|
|
35957
36489
|
onComplete?.(data);
|
|
35958
36490
|
const m2 = payload.measurements || {};
|
|
35959
36491
|
const qe2 = payload.quickEstimate || {};
|
|
@@ -35981,26 +36513,49 @@ function PrimeStyleTryonInner({
|
|
|
35981
36513
|
} else {
|
|
35982
36514
|
const errBody = await res.text().catch(() => "");
|
|
35983
36515
|
console.error("[PS-SDK] Sizing recommend failed:", res.status, errBody);
|
|
36516
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36517
|
+
metadata: { status: res.status, method, measurementType, source: "sizing-recommend" }
|
|
36518
|
+
});
|
|
36519
|
+
reportSdkClientError({
|
|
36520
|
+
message: errBody || "Sizing request failed",
|
|
36521
|
+
code: "SIZING_RECOMMEND_FAILED",
|
|
36522
|
+
component: "Sizing",
|
|
36523
|
+
view,
|
|
36524
|
+
severity: "medium",
|
|
36525
|
+
metadata: { status: res.status, method, measurementType }
|
|
36526
|
+
});
|
|
35984
36527
|
setErrorMessage(t2("Unable to get a size suggestion. Please try again."));
|
|
35985
36528
|
setView("error");
|
|
35986
36529
|
setEstimationDone(true);
|
|
35987
36530
|
}
|
|
35988
36531
|
} catch (err) {
|
|
35989
36532
|
console.error("[PS-SDK] Sizing recommend network error:", err);
|
|
36533
|
+
reportSdkEvent("SIZING_FAILED", {
|
|
36534
|
+
metadata: { method, measurementType, source: "sizing-recommend", network: true }
|
|
36535
|
+
});
|
|
36536
|
+
reportSdkClientError({
|
|
36537
|
+
message: err instanceof Error ? err.message : "Sizing network error",
|
|
36538
|
+
code: "SIZING_RECOMMEND_NETWORK_ERROR",
|
|
36539
|
+
stack: err instanceof Error ? err.stack : void 0,
|
|
36540
|
+
component: "Sizing",
|
|
36541
|
+
view,
|
|
36542
|
+
severity: "medium",
|
|
36543
|
+
metadata: { method, measurementType }
|
|
36544
|
+
});
|
|
35990
36545
|
setErrorMessage(t2("Unable to connect to sizing service. Please try again."));
|
|
35991
36546
|
setView("error");
|
|
35992
36547
|
setEstimationDone(true);
|
|
35993
36548
|
} finally {
|
|
35994
36549
|
setSizingLoading(false);
|
|
35995
36550
|
}
|
|
35996
|
-
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productContext, measurementType, dynamicFields, persistResultToProfile]);
|
|
36551
|
+
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productContext, measurementType, resolvedProductFitType, dynamicFields, persistResultToProfile, reportSdkClientError, reportSdkEvent, t2, view]);
|
|
35997
36552
|
const handleQuickEstimate = reactExports.useCallback(async (height, weight, heightUnit2, weightUnit2, gender, age, bodyType, chestProfile, midsectionProfile, hipProfile, bodyImage) => {
|
|
35998
36553
|
if (!apiRef.current) {
|
|
35999
36554
|
const msg = t2("SDK not configured. Please refresh and try again.");
|
|
36000
36555
|
console.warn("[ps-sdk] handleQuickEstimate BAILED — apiRef is null. API key not loaded.");
|
|
36001
36556
|
setErrorMessage(msg);
|
|
36002
36557
|
setView("error");
|
|
36003
|
-
onError?.({ message: msg, code: "SDK_NOT_CONFIGURED" });
|
|
36558
|
+
onError?.({ message: msg, code: !apiRef.current ? "SDK_NOT_CONFIGURED" : "PHOTO_MISSING" });
|
|
36004
36559
|
return;
|
|
36005
36560
|
}
|
|
36006
36561
|
getApiUrl(apiUrl);
|
|
@@ -36379,6 +36934,13 @@ function PrimeStyleTryonInner({
|
|
|
36379
36934
|
const msg = !apiRef.current ? t2("SDK not configured. Please provide an API key.") : t2("Please upload a photo first.");
|
|
36380
36935
|
setErrorMessage(msg);
|
|
36381
36936
|
setView("error");
|
|
36937
|
+
reportSdkClientError({
|
|
36938
|
+
message: msg,
|
|
36939
|
+
code: !apiRef.current ? "SDK_NOT_CONFIGURED" : "PHOTO_MISSING",
|
|
36940
|
+
component: "TryOn",
|
|
36941
|
+
view,
|
|
36942
|
+
severity: !apiRef.current ? "high" : "low"
|
|
36943
|
+
});
|
|
36382
36944
|
onError?.({ message: msg, code: "SDK_NOT_CONFIGURED" });
|
|
36383
36945
|
return;
|
|
36384
36946
|
}
|
|
@@ -36533,12 +37095,20 @@ function PrimeStyleTryonInner({
|
|
|
36533
37095
|
}
|
|
36534
37096
|
);
|
|
36535
37097
|
currentTryOnJobIdRef.current = response.jobId;
|
|
37098
|
+
tagSdkClaritySession({
|
|
37099
|
+
productId: effectiveProductId,
|
|
37100
|
+
productTitle: restoredProductTitle || productTitle,
|
|
37101
|
+
productUrl: restoredProductUrl || effectiveProductUrl,
|
|
37102
|
+
view,
|
|
37103
|
+
jobId: response.jobId,
|
|
37104
|
+
source: shouldUseShopifyCartAttribution(apiUrl) ? "shopify-sdk" : "sdk"
|
|
37105
|
+
});
|
|
36536
37106
|
if (response.modelImageId) modelImageIdRef.current = response.modelImageId;
|
|
36537
37107
|
onProcessing?.(response.jobId);
|
|
36538
37108
|
const usePollingOnly = shouldUseShopifyCartAttribution(apiUrl);
|
|
36539
|
-
if (!usePollingOnly
|
|
37109
|
+
if (!usePollingOnly) {
|
|
36540
37110
|
sseRef.current?.disconnect();
|
|
36541
|
-
sseRef.current = new SseClient(response.streamUrl);
|
|
37111
|
+
sseRef.current = new SseClient(response.streamUrl || apiRef.current.getStreamUrl(response.jobId));
|
|
36542
37112
|
}
|
|
36543
37113
|
unsubRef.current?.();
|
|
36544
37114
|
unsubRef.current = usePollingOnly ? null : sseRef.current?.onJob(response.jobId, handleVtoUpdate) ?? null;
|
|
@@ -36566,11 +37136,19 @@ function PrimeStyleTryonInner({
|
|
|
36566
37136
|
} catch (err) {
|
|
36567
37137
|
const message = err instanceof Error ? err.message : t2("Failed to start try-on");
|
|
36568
37138
|
const code = err instanceof PrimeStyleError ? err.code : void 0;
|
|
37139
|
+
reportSdkClientError({
|
|
37140
|
+
message,
|
|
37141
|
+
code: code || "TRYON_SUBMIT_FAILED",
|
|
37142
|
+
stack: err instanceof Error ? err.stack : void 0,
|
|
37143
|
+
component: "TryOn",
|
|
37144
|
+
view,
|
|
37145
|
+
severity: "medium"
|
|
37146
|
+
});
|
|
36569
37147
|
setErrorMessage(message);
|
|
36570
37148
|
setView("error");
|
|
36571
37149
|
onError?.({ message, code });
|
|
36572
37150
|
}
|
|
36573
|
-
}, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, garmentDetailImage, productTitle, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate]);
|
|
37151
|
+
}, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, garmentDetailImage, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate, reportSdkClientError, t2, view]);
|
|
36574
37152
|
reactExports.useEffect(() => {
|
|
36575
37153
|
if (view !== "size-result") {
|
|
36576
37154
|
autoTryOnFiredRef.current = false;
|
|
@@ -36662,7 +37240,7 @@ function PrimeStyleTryonInner({
|
|
|
36662
37240
|
}, [sizingResult]);
|
|
36663
37241
|
const handleAddToBag = reactExports.useCallback(async () => {
|
|
36664
37242
|
if (!onAddToBag || !sizingResult) return;
|
|
36665
|
-
|
|
37243
|
+
const payload = {
|
|
36666
37244
|
productId,
|
|
36667
37245
|
productTitle: restoredProductTitle || productTitle,
|
|
36668
37246
|
productUrl: restoredProductUrl || effectiveProductUrl,
|
|
@@ -36671,7 +37249,33 @@ function PrimeStyleTryonInner({
|
|
|
36671
37249
|
resultImageUrl: resultImageUrlRef.current || resultImageUrl,
|
|
36672
37250
|
historyEntryId: currentHistoryEntryIdRef.current ?? void 0,
|
|
36673
37251
|
selectedSizes: buildAddToBagSelectedSizes()
|
|
36674
|
-
}
|
|
37252
|
+
};
|
|
37253
|
+
try {
|
|
37254
|
+
await onAddToBag(payload);
|
|
37255
|
+
reportSdkEvent("SIZE_RECOMMENDATION_ACCEPTED", {
|
|
37256
|
+
recommendedSize: sizingResult.recommendedSize,
|
|
37257
|
+
metadata: { selectedSizes: payload.selectedSizes }
|
|
37258
|
+
});
|
|
37259
|
+
reportSdkEvent("ADD_TO_CART_FROM_TRYON", {
|
|
37260
|
+
recommendedSize: sizingResult.recommendedSize,
|
|
37261
|
+
metadata: {
|
|
37262
|
+
selectedSizes: payload.selectedSizes,
|
|
37263
|
+
historyEntryId: payload.historyEntryId,
|
|
37264
|
+
hasResult: Boolean(payload.resultImageUrl)
|
|
37265
|
+
}
|
|
37266
|
+
});
|
|
37267
|
+
} catch (error) {
|
|
37268
|
+
reportSdkClientError({
|
|
37269
|
+
message: error instanceof Error ? error.message : "Add to bag failed",
|
|
37270
|
+
code: "ADD_TO_BAG_FAILED",
|
|
37271
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
37272
|
+
component: "ResultActions",
|
|
37273
|
+
view,
|
|
37274
|
+
severity: "medium",
|
|
37275
|
+
metadata: { selectedSizes: payload.selectedSizes }
|
|
37276
|
+
});
|
|
37277
|
+
throw error;
|
|
37278
|
+
}
|
|
36675
37279
|
}, [
|
|
36676
37280
|
buildAddToBagSelectedSizes,
|
|
36677
37281
|
effectiveProductUrl,
|
|
@@ -36681,7 +37285,10 @@ function PrimeStyleTryonInner({
|
|
|
36681
37285
|
restoredProductTitle,
|
|
36682
37286
|
restoredProductUrl,
|
|
36683
37287
|
resultImageUrl,
|
|
36684
|
-
|
|
37288
|
+
reportSdkClientError,
|
|
37289
|
+
reportSdkEvent,
|
|
37290
|
+
sizingResult,
|
|
37291
|
+
view
|
|
36685
37292
|
]);
|
|
36686
37293
|
const handleTryOnFeedbackSubmit = reactExports.useCallback(async ({ rating, note }) => {
|
|
36687
37294
|
const profileLoggedIn = Boolean(profileSession);
|
|
@@ -37639,7 +38246,7 @@ function PrimeStyleTryonInner({
|
|
|
37639
38246
|
return null;
|
|
37640
38247
|
}
|
|
37641
38248
|
}
|
|
37642
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { visibility: cssReady ? "visible" : "hidden", ...cssVars, ...style }, suppressHydrationWarning: true, "data-ps-tryon": true, children: [
|
|
38249
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { visibility: cssReady ? "visible" : "hidden", ...cssVars, ...style }, suppressHydrationWarning: true, "data-ps-tryon": true, "data-clarity-unmask": "true", children: [
|
|
37643
38250
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37644
38251
|
"button",
|
|
37645
38252
|
{
|
|
@@ -37653,7 +38260,7 @@ function PrimeStyleTryonInner({
|
|
|
37653
38260
|
}
|
|
37654
38261
|
),
|
|
37655
38262
|
view !== "idle" && resolvedPortalContainer && reactDomExports.createPortal(
|
|
37656
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" || view === "profiles" || view === "no-chart" || view === "photo-guide" || view === "error" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
|
|
38263
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, "data-clarity-unmask": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" || view === "profiles" || view === "no-chart" || view === "photo-guide" || view === "error" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), "data-clarity-unmask": "true", children: [
|
|
37657
38264
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-header ps-tryon-header-minimal", cn.header), children: [
|
|
37658
38265
|
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
37659
38266
|
"a",
|
|
@@ -37811,7 +38418,7 @@ function PrimeStyleTryonInner({
|
|
|
37811
38418
|
resolvedPortalContainer
|
|
37812
38419
|
),
|
|
37813
38420
|
view !== "body-profile" && view !== "processing" && !(view === "size-result" && sizeGuide?.sections && Object.keys(sizeGuide.sections).length > 1) && /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper, { view, stepIndex }),
|
|
37814
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
|
|
38421
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, "data-clarity-unmask": "true", children: [
|
|
37815
38422
|
showBackButton && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-back-btn", onClick: handleBack, children: [
|
|
37816
38423
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
37817
38424
|
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "6", x2: "1", y2: "6" }),
|
|
@@ -37891,8 +38498,20 @@ class PrimeStyleTryonErrorBoundary extends reactExports.Component {
|
|
|
37891
38498
|
}
|
|
37892
38499
|
componentDidCatch(error) {
|
|
37893
38500
|
console.error("[ps-sdk] PrimeStyleTryon render failed:", error);
|
|
38501
|
+
const message = error instanceof Error ? error.message : "PrimeStyleTryon render failed";
|
|
38502
|
+
void new ApiClient(getApiKey(), getApiUrl(this.props.apiUrl)).reportClientError({
|
|
38503
|
+
message,
|
|
38504
|
+
code: "RENDER_ERROR",
|
|
38505
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
38506
|
+
component: "PrimeStyleTryon",
|
|
38507
|
+
productId: this.props.productId || this.props.productImage,
|
|
38508
|
+
productTitle: this.props.productTitle,
|
|
38509
|
+
productUrl: this.props.productUrl,
|
|
38510
|
+
severity: "high"
|
|
38511
|
+
}).catch(() => {
|
|
38512
|
+
});
|
|
37894
38513
|
this.props.onError?.({
|
|
37895
|
-
message
|
|
38514
|
+
message,
|
|
37896
38515
|
code: "RENDER_ERROR"
|
|
37897
38516
|
});
|
|
37898
38517
|
}
|
|
@@ -38447,7 +39066,8 @@ function buildPropsFromDataAttrs(data) {
|
|
|
38447
39066
|
sizingCountry: data.sizingCountry,
|
|
38448
39067
|
showPoweredBy: data.showPoweredBy === "true",
|
|
38449
39068
|
buttonStyles: parseJsonAttr(data.buttonStyles, void 0),
|
|
38450
|
-
modalStyles: parseJsonAttr(data.modalStyles, void 0)
|
|
39069
|
+
modalStyles: parseJsonAttr(data.modalStyles, void 0),
|
|
39070
|
+
clarityProjectId: data.clarityProjectId
|
|
38451
39071
|
};
|
|
38452
39072
|
console.log(`${TAG} built props`, props);
|
|
38453
39073
|
return props;
|