@primestyleai/tryon 5.10.101 → 5.10.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/PrimeStyleTryonInner.d.ts +1 -1
- package/dist/react/index.js +4771 -4836
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/types.d.ts +4 -0
- package/dist/react/views/ProductPhotoCarouselCard.d.ts +12 -0
- package/dist/react/views/SizeResultView.d.ts +5 -19
- package/dist/react/views/TryOnGenerationBadge.d.ts +5 -0
- package/dist/sizing/fit-compute.d.ts +8 -3
- package/dist/storefront/primestyle-tryon.js +600 -758
- package/dist/types.d.ts +5 -0
- package/package.json +1 -1
|
@@ -10078,12 +10078,13 @@ function parseNum(s) {
|
|
|
10078
10078
|
const n2 = parseFloat(s.replace(/[^\d.]/g, ""));
|
|
10079
10079
|
return isNaN(n2) ? 0 : n2;
|
|
10080
10080
|
}
|
|
10081
|
-
function computeFit(userValue, chartRange) {
|
|
10081
|
+
function computeFit(userValue, chartRange, unit) {
|
|
10082
10082
|
const { min: rMin, max: rMax } = parseRange(chartRange);
|
|
10083
10083
|
if (rMin === 0 && rMax === 0) return "good";
|
|
10084
10084
|
const range = rMax - rMin;
|
|
10085
10085
|
const threshold = range > 0 ? range * 0.5 : rMin * 0.05 || 3;
|
|
10086
|
-
|
|
10086
|
+
const perfectTol = unit === "cm" ? 2.54 : unit === "mm" ? 25.4 : 1;
|
|
10087
|
+
if (userValue > rMin - perfectTol && userValue < rMax + perfectTol) return "good";
|
|
10087
10088
|
if (userValue < rMin) {
|
|
10088
10089
|
const diff2 = rMin - userValue;
|
|
10089
10090
|
if (diff2 > threshold * 2) return "too-loose";
|
|
@@ -10107,12 +10108,13 @@ const SKIP_AREAS_FOR_FIT = /* @__PURE__ */ new Set([
|
|
|
10107
10108
|
"altezza",
|
|
10108
10109
|
"estatura"
|
|
10109
10110
|
]);
|
|
10110
|
-
function buildFitInfo(matchDetails, poseLines) {
|
|
10111
|
+
function buildFitInfo(matchDetails, poseLines, unit) {
|
|
10111
10112
|
return matchDetails.filter((m2) => !SKIP_AREAS_FOR_FIT.has(m2.measurement.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim())).map((m2) => {
|
|
10112
10113
|
const userNum = parseNum(m2.userValue);
|
|
10113
|
-
const fit = computeFit(userNum, m2.chartRange);
|
|
10114
|
+
const fit = computeFit(userNum, m2.chartRange, unit);
|
|
10114
10115
|
const info = {
|
|
10115
10116
|
area: m2.measurement,
|
|
10117
|
+
section: m2.section || void 0,
|
|
10116
10118
|
fit,
|
|
10117
10119
|
userValue: userNum || void 0,
|
|
10118
10120
|
garmentRange: m2.chartRange || void 0
|
|
@@ -11328,6 +11330,37 @@ const STYLES$1 = `
|
|
|
11328
11330
|
border: 1px solid rgba(33,84,239,0.25); border-radius: 2vw;
|
|
11329
11331
|
padding: 0.1vw 0.5vw;
|
|
11330
11332
|
}
|
|
11333
|
+
.ps-tryon-sr-card-v2-rec-pill {
|
|
11334
|
+
align-self: flex-start;
|
|
11335
|
+
font-size: 0.55vw; font-weight: 700; color: var(--ps-accent);
|
|
11336
|
+
text-transform: uppercase; letter-spacing: 0.08em;
|
|
11337
|
+
background: rgba(33, 84, 239, 0.10);
|
|
11338
|
+
border: 1px solid rgba(33, 84, 239, 0.18);
|
|
11339
|
+
border-radius: 2vw;
|
|
11340
|
+
padding: 0.18vw 0.6vw;
|
|
11341
|
+
margin-top: 0.3vw;
|
|
11342
|
+
}
|
|
11343
|
+
.ps-tryon-sr-card-v2-rec-pill.is-overridden {
|
|
11344
|
+
color: #b45309;
|
|
11345
|
+
background: rgba(180, 83, 9, 0.10);
|
|
11346
|
+
border-color: rgba(180, 83, 9, 0.25);
|
|
11347
|
+
}
|
|
11348
|
+
.ps-tryon-sr-card-v2-view {
|
|
11349
|
+
align-self: center;
|
|
11350
|
+
margin-top: 0.4vw;
|
|
11351
|
+
font-size: 0.62vw; font-weight: 600;
|
|
11352
|
+
color: var(--ps-accent);
|
|
11353
|
+
text-transform: uppercase; letter-spacing: 0.06em;
|
|
11354
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 0.2vw;
|
|
11355
|
+
transition: gap 0.2s ease;
|
|
11356
|
+
}
|
|
11357
|
+
.ps-tryon-sr-card-v2:hover .ps-tryon-sr-card-v2-view {
|
|
11358
|
+
gap: 0.4vw;
|
|
11359
|
+
}
|
|
11360
|
+
.ps-tryon-sr-card-v2-view > span {
|
|
11361
|
+
font-size: 0.85vw; line-height: 1; color: var(--ps-accent);
|
|
11362
|
+
transform: translateY(-0.05vw);
|
|
11363
|
+
}
|
|
11331
11364
|
.ps-tryon-sr-card-v2-img { display: none; }
|
|
11332
11365
|
.ps-tryon-sr-card-v2-icon {
|
|
11333
11366
|
position: absolute; bottom: 0.35vw; right: 0.45vw;
|
|
@@ -11391,24 +11424,165 @@ const STYLES$1 = `
|
|
|
11391
11424
|
filter: blur(8px) brightness(0.5); transform: scale(1.05);
|
|
11392
11425
|
transition: filter 0.5s ease, transform 0.5s ease;
|
|
11393
11426
|
}
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
background:
|
|
11399
|
-
|
|
11400
|
-
|
|
11401
|
-
|
|
11402
|
-
box-shadow: 0
|
|
11427
|
+
/* ── Try-on generation badge (left-side overlay during VTO) ── */
|
|
11428
|
+
.ps-tryon-badge {
|
|
11429
|
+
position: absolute; bottom: 16px; left: 16px; right: 16px;
|
|
11430
|
+
z-index: 5;
|
|
11431
|
+
background: #ffffff;
|
|
11432
|
+
border-radius: 14px;
|
|
11433
|
+
padding: 14px 18px;
|
|
11434
|
+
max-width: 420px;
|
|
11435
|
+
box-shadow: 0 8px 28px rgba(20, 30, 60, 0.14), 0 2px 6px rgba(20, 30, 60, 0.08);
|
|
11436
|
+
display: flex; flex-direction: column; gap: 10px;
|
|
11437
|
+
font-family: inherit;
|
|
11438
|
+
pointer-events: none;
|
|
11439
|
+
}
|
|
11440
|
+
.ps-tryon-badge-row {
|
|
11441
|
+
display: flex; align-items: center; gap: 12px;
|
|
11442
|
+
}
|
|
11443
|
+
.ps-tryon-badge-spinner {
|
|
11444
|
+
display: inline-flex; flex-shrink: 0;
|
|
11445
|
+
animation: ps-tryon-badge-spin 1s linear infinite;
|
|
11446
|
+
}
|
|
11447
|
+
.ps-tryon-badge-title {
|
|
11448
|
+
flex: 1; min-width: 0;
|
|
11449
|
+
font-size: 15px; font-weight: 600; color: #0f172a;
|
|
11450
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
11451
|
+
}
|
|
11452
|
+
.ps-tryon-badge-pct {
|
|
11453
|
+
flex-shrink: 0;
|
|
11454
|
+
background: linear-gradient(135deg, var(--ps-accent) 0%, var(--ps-accent-hover) 100%);
|
|
11455
|
+
color: #fff; font-size: 12px; font-weight: 700;
|
|
11456
|
+
padding: 4px 11px; border-radius: 999px;
|
|
11457
|
+
letter-spacing: 0.02em;
|
|
11458
|
+
}
|
|
11459
|
+
.ps-tryon-badge-bar {
|
|
11460
|
+
height: 5px;
|
|
11461
|
+
background: #eef2f8;
|
|
11462
|
+
border-radius: 999px; overflow: hidden;
|
|
11463
|
+
}
|
|
11464
|
+
.ps-tryon-badge-bar-fill {
|
|
11465
|
+
height: 100%;
|
|
11466
|
+
background: linear-gradient(90deg, var(--ps-accent) 0%, var(--ps-accent-hover) 100%);
|
|
11467
|
+
border-radius: 999px;
|
|
11468
|
+
transition: width 0.3s ease;
|
|
11469
|
+
}
|
|
11470
|
+
.ps-tryon-badge-foot {
|
|
11471
|
+
display: flex; align-items: center; justify-content: space-between; gap: 10px;
|
|
11472
|
+
font-size: 12px; color: #6b7280;
|
|
11473
|
+
}
|
|
11474
|
+
.ps-tryon-badge-status {
|
|
11475
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
11476
|
+
font-weight: 500;
|
|
11477
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
11478
|
+
}
|
|
11479
|
+
.ps-tryon-badge-status-icon {
|
|
11480
|
+
display: inline-flex; flex-shrink: 0; color: var(--ps-accent);
|
|
11481
|
+
}
|
|
11482
|
+
.ps-tryon-badge-eta {
|
|
11483
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
11484
|
+
font-weight: 500; flex-shrink: 0;
|
|
11485
|
+
}
|
|
11486
|
+
@keyframes ps-tryon-badge-spin {
|
|
11487
|
+
to { transform: rotate(360deg); }
|
|
11488
|
+
}
|
|
11489
|
+
|
|
11490
|
+
/* ── Product photo strip (single-garment, below the size card) ──
|
|
11491
|
+
Three thumbnails per slide, evenly spaced, auto-advances. Lives at
|
|
11492
|
+
the bottom of the right panel as decoration / entertainment. */
|
|
11493
|
+
.ps-tryon-photo-strip {
|
|
11494
|
+
margin-top: 1vw;
|
|
11495
|
+
display: flex; flex-direction: column; gap: 0.6vw;
|
|
11496
|
+
}
|
|
11497
|
+
.ps-tryon-photo-strip-head {
|
|
11498
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
11499
|
+
}
|
|
11500
|
+
.ps-tryon-photo-strip-badge {
|
|
11501
|
+
color: var(--ps-accent);
|
|
11502
|
+
font-size: 0.7vw; font-weight: 600;
|
|
11503
|
+
display: inline-flex; align-items: center; gap: 0.3vw;
|
|
11504
|
+
letter-spacing: 0.04em; text-transform: uppercase;
|
|
11505
|
+
}
|
|
11506
|
+
.ps-tryon-photo-strip-row {
|
|
11507
|
+
display: grid;
|
|
11508
|
+
grid-template-columns: repeat(3, 1fr);
|
|
11509
|
+
gap: 0.6vw;
|
|
11510
|
+
animation: ps-tryon-photo-strip-fade 0.5s ease;
|
|
11511
|
+
}
|
|
11512
|
+
.ps-tryon-photo-strip-cell {
|
|
11513
|
+
position: relative;
|
|
11514
|
+
aspect-ratio: 3 / 4;
|
|
11515
|
+
overflow: hidden;
|
|
11516
|
+
border-radius: 0.5vw;
|
|
11517
|
+
background: #f3f5f9;
|
|
11518
|
+
box-shadow: 0 0.15vw 0.5vw rgba(20, 30, 60, 0.08);
|
|
11519
|
+
transition: transform 0.25s ease;
|
|
11520
|
+
}
|
|
11521
|
+
.ps-tryon-photo-strip-cell:hover {
|
|
11522
|
+
transform: translateY(-0.15vw);
|
|
11523
|
+
}
|
|
11524
|
+
.ps-tryon-photo-strip-cell > img {
|
|
11525
|
+
width: 100%; height: 100%;
|
|
11526
|
+
object-fit: cover;
|
|
11527
|
+
user-select: none;
|
|
11528
|
+
pointer-events: none;
|
|
11529
|
+
}
|
|
11530
|
+
.ps-tryon-photo-strip-dots {
|
|
11531
|
+
display: flex; justify-content: center; align-items: center; gap: 0.3vw;
|
|
11532
|
+
padding-top: 0.2vw;
|
|
11533
|
+
}
|
|
11534
|
+
.ps-tryon-photo-strip-dot {
|
|
11535
|
+
width: 0.3vw; height: 0.3vw; min-width: 4px; min-height: 4px;
|
|
11536
|
+
border-radius: 999px;
|
|
11537
|
+
background: #d6dbe4;
|
|
11538
|
+
transition: background-color 0.3s ease, width 0.3s ease;
|
|
11539
|
+
}
|
|
11540
|
+
.ps-tryon-photo-strip-dot.is-active {
|
|
11541
|
+
background: var(--ps-accent);
|
|
11542
|
+
width: 0.9vw; min-width: 14px;
|
|
11543
|
+
}
|
|
11544
|
+
@keyframes ps-tryon-photo-strip-fade {
|
|
11545
|
+
from { opacity: 0; transform: translateY(0.3vw); }
|
|
11546
|
+
to { opacity: 1; transform: translateY(0); }
|
|
11547
|
+
}
|
|
11548
|
+
|
|
11549
|
+
/* ── No-fit empty state (single-garment, sizing match% < 50%) ── */
|
|
11550
|
+
.ps-tryon-nofit {
|
|
11551
|
+
background: #ffffff;
|
|
11552
|
+
border: 1px solid #eef2f8;
|
|
11553
|
+
border-radius: 1vw;
|
|
11554
|
+
padding: 3vw 2.4vw 2.6vw;
|
|
11555
|
+
text-align: center;
|
|
11556
|
+
display: flex; flex-direction: column; align-items: center;
|
|
11557
|
+
box-shadow: 0 0.4vw 1.2vw rgba(20, 30, 60, 0.05);
|
|
11403
11558
|
}
|
|
11404
|
-
.ps-tryon-
|
|
11405
|
-
|
|
11559
|
+
.ps-tryon-nofit-icon {
|
|
11560
|
+
width: 4.4vw; height: 4.4vw; min-width: 56px; min-height: 56px;
|
|
11561
|
+
border-radius: 50%;
|
|
11562
|
+
background: #fef2f2;
|
|
11563
|
+
color: #dc2626;
|
|
11564
|
+
display: flex; align-items: center; justify-content: center;
|
|
11565
|
+
margin-bottom: 1.2vw;
|
|
11566
|
+
}
|
|
11567
|
+
.ps-tryon-nofit-icon svg { width: 50%; height: 50%; }
|
|
11568
|
+
.ps-tryon-nofit-title {
|
|
11569
|
+
font-size: 1.15vw; font-weight: 700; color: #0f172a;
|
|
11570
|
+
margin: 0 0 0.7vw;
|
|
11571
|
+
line-height: 1.3;
|
|
11572
|
+
letter-spacing: -0.01em;
|
|
11573
|
+
}
|
|
11574
|
+
.ps-tryon-nofit-sub {
|
|
11575
|
+
font-size: 0.78vw; color: #6b7280;
|
|
11576
|
+
margin: 0 0 2vw;
|
|
11577
|
+
max-width: 22vw;
|
|
11578
|
+
line-height: 1.6;
|
|
11579
|
+
}
|
|
11580
|
+
.ps-tryon-nofit-actions {
|
|
11581
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
11582
|
+
width: 100%; gap: 1vw;
|
|
11583
|
+
padding-top: 1.2vw;
|
|
11584
|
+
border-top: 1px solid #f1f4fa;
|
|
11406
11585
|
}
|
|
11407
|
-
.ps-tryon-v2-processing-label .ps-tryon-progress-ring-track { stroke: rgba(255,255,255,0.18); }
|
|
11408
|
-
.ps-tryon-v2-processing-label .ps-tryon-progress-ring-fill { stroke: var(--ps-accent-light); }
|
|
11409
|
-
.ps-tryon-v2-processing-label .ps-tryon-progress-eta { color: #fff; }
|
|
11410
|
-
.ps-tryon-v2-processing-label .ps-tryon-progress-bar-wrap { background: rgba(255,255,255,0.18); }
|
|
11411
|
-
.ps-tryon-v2-processing-label .ps-tryon-progress-pct { color: var(--ps-accent-light); }
|
|
11412
11586
|
|
|
11413
11587
|
/* "I don't know" link */
|
|
11414
11588
|
.ps-tryon-v2-dontknow {
|
|
@@ -18741,140 +18915,6 @@ function MobileBottomTabs({ mode, onSwitchToManual, onSwitchToScan, t: t2 }) {
|
|
|
18741
18915
|
)
|
|
18742
18916
|
] });
|
|
18743
18917
|
}
|
|
18744
|
-
const TARGET_SECONDS = 22;
|
|
18745
|
-
const RING_RADIUS$1 = 38;
|
|
18746
|
-
const RING_CIRC = 2 * Math.PI * RING_RADIUS$1;
|
|
18747
|
-
function EngagingTryOnView({
|
|
18748
|
-
previewUrl,
|
|
18749
|
-
productMaterial,
|
|
18750
|
-
productDescription,
|
|
18751
|
-
onCancel,
|
|
18752
|
-
variant = "split",
|
|
18753
|
-
t: t2
|
|
18754
|
-
}) {
|
|
18755
|
-
const startRef = reactExports.useRef(Date.now());
|
|
18756
|
-
const ringRef = reactExports.useRef(null);
|
|
18757
|
-
const pctRef = reactExports.useRef(null);
|
|
18758
|
-
const statusRef = reactExports.useRef(null);
|
|
18759
|
-
const statuses = [
|
|
18760
|
-
t2("Preparing your image…"),
|
|
18761
|
-
t2("Mapping body landmarks…"),
|
|
18762
|
-
t2("Rendering the garment…"),
|
|
18763
|
-
t2("Refining drape and shadows…"),
|
|
18764
|
-
t2("Almost done — finalizing…")
|
|
18765
|
-
];
|
|
18766
|
-
reactExports.useEffect(() => {
|
|
18767
|
-
startRef.current = Date.now();
|
|
18768
|
-
const id2 = setInterval(() => {
|
|
18769
|
-
const elapsed = (Date.now() - startRef.current) / 1e3;
|
|
18770
|
-
const pct = Math.min(95, elapsed / TARGET_SECONDS * 100);
|
|
18771
|
-
const val = Math.round(pct);
|
|
18772
|
-
if (pctRef.current) pctRef.current.textContent = `${val}%`;
|
|
18773
|
-
if (ringRef.current) ringRef.current.style.strokeDashoffset = String(RING_CIRC * (1 - pct / 100));
|
|
18774
|
-
if (statusRef.current) {
|
|
18775
|
-
const stepIdx = Math.min(statuses.length - 1, Math.floor(elapsed / TARGET_SECONDS * statuses.length));
|
|
18776
|
-
const desired = statuses[stepIdx];
|
|
18777
|
-
if (statusRef.current.textContent !== desired) statusRef.current.textContent = desired;
|
|
18778
|
-
}
|
|
18779
|
-
}, 200);
|
|
18780
|
-
return () => clearInterval(id2);
|
|
18781
|
-
}, []);
|
|
18782
|
-
const aiFacts = [
|
|
18783
|
-
t2("Our model is analyzing 150+ body landmarks for the perfect fit"),
|
|
18784
|
-
t2("Calibrating fabric drape against your body proportions"),
|
|
18785
|
-
t2("Cross-checking fit against millions of garment patterns"),
|
|
18786
|
-
t2("Rendering shadows and highlights to match your photo's lighting")
|
|
18787
|
-
];
|
|
18788
|
-
const styleTips = [
|
|
18789
|
-
t2("Pair this with neutral tones for a balanced look"),
|
|
18790
|
-
t2("Layer with a fitted base for sharper silhouette"),
|
|
18791
|
-
t2("Cuff once for a relaxed everyday feel")
|
|
18792
|
-
];
|
|
18793
|
-
const [factIdx, setFactIdx] = reactExports.useState(0);
|
|
18794
|
-
const [tipIdx, setTipIdx] = reactExports.useState(0);
|
|
18795
|
-
reactExports.useEffect(() => {
|
|
18796
|
-
const f2 = setInterval(() => setFactIdx((i) => (i + 1) % aiFacts.length), 4e3);
|
|
18797
|
-
const s = setInterval(() => setTipIdx((i) => (i + 1) % styleTips.length), 5e3);
|
|
18798
|
-
return () => {
|
|
18799
|
-
clearInterval(f2);
|
|
18800
|
-
clearInterval(s);
|
|
18801
|
-
};
|
|
18802
|
-
}, []);
|
|
18803
|
-
const garmentLine = productMaterial?.trim() || (productDescription?.trim() ? productDescription.trim().slice(0, 90) + (productDescription.trim().length > 90 ? "…" : "") : null) || t2("Crafted with quality materials for everyday comfort");
|
|
18804
|
-
const Panel = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-panel", children: [
|
|
18805
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-head", children: [
|
|
18806
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-processing-v2-title", children: t2("Generating Your Look") }),
|
|
18807
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-processing-v2-sub", children: t2("Our AI is precisely mapping the garment to your unique proportions.") })
|
|
18808
|
-
] }),
|
|
18809
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-ring-wrap", children: [
|
|
18810
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 96 96", width: "120", height: "120", "aria-hidden": "true", children: [
|
|
18811
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "48", cy: "48", r: RING_RADIUS$1, className: "ps-tryon-progress-ring-track" }),
|
|
18812
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
18813
|
-
"circle",
|
|
18814
|
-
{
|
|
18815
|
-
ref: ringRef,
|
|
18816
|
-
cx: "48",
|
|
18817
|
-
cy: "48",
|
|
18818
|
-
r: RING_RADIUS$1,
|
|
18819
|
-
className: "ps-tryon-progress-ring-fill",
|
|
18820
|
-
strokeDasharray: RING_CIRC,
|
|
18821
|
-
strokeDashoffset: RING_CIRC
|
|
18822
|
-
}
|
|
18823
|
-
)
|
|
18824
|
-
] }),
|
|
18825
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-ring-text", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: pctRef, className: "ps-tryon-processing-v2-pct", children: "0%" }) })
|
|
18826
|
-
] }),
|
|
18827
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: statusRef, className: "ps-tryon-processing-v2-status", children: statuses[0] }),
|
|
18828
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-sep" }),
|
|
18829
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
18830
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-section-label", children: t2("WHILE YOU WAIT") }),
|
|
18831
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-cards", children: [
|
|
18832
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card", children: [
|
|
18833
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-icon ps-style", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 18h6M10 22h4M12 2a7 7 0 0 0-4 12.7c1 .9 1 1.8 1 2.3v1h6v-1c0-.5 0-1.4 1-2.3A7 7 0 0 0 12 2z" }) }) }),
|
|
18834
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card-text", children: [
|
|
18835
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-head", children: t2("Style Tip") }),
|
|
18836
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-body", children: styleTips[tipIdx] }, tipIdx)
|
|
18837
|
-
] })
|
|
18838
|
-
] }),
|
|
18839
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card", children: [
|
|
18840
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-icon ps-spotlight", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
18841
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
18842
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
18843
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
18844
|
-
] }) }),
|
|
18845
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card-text", children: [
|
|
18846
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-head", children: t2("Garment Spotlight") }),
|
|
18847
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-body", children: garmentLine })
|
|
18848
|
-
] })
|
|
18849
|
-
] }),
|
|
18850
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card", children: [
|
|
18851
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-icon ps-fact", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 2v6M12 16v6M4.93 4.93l4.24 4.24M14.83 14.83l4.24 4.24M2 12h6M16 12h6M4.93 19.07l4.24-4.24M14.83 9.17l4.24-4.24" }) }) }),
|
|
18852
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-card-text", children: [
|
|
18853
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-head", children: t2("AI Fact") }),
|
|
18854
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-v2-card-body", children: aiFacts[factIdx] }, factIdx)
|
|
18855
|
-
] })
|
|
18856
|
-
] })
|
|
18857
|
-
] })
|
|
18858
|
-
] }),
|
|
18859
|
-
onCancel && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-tryon-processing-v2-cancel", onClick: onCancel, children: t2("Cancel Generation") })
|
|
18860
|
-
] });
|
|
18861
|
-
if (variant === "panel-only") return Panel;
|
|
18862
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2", children: [
|
|
18863
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-image", children: [
|
|
18864
|
-
previewUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18865
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-processing-blur", style: { backgroundImage: `url(${previewUrl})` } }),
|
|
18866
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: previewUrl, alt: t2("Your photo"), className: "ps-tryon-processing-model" })
|
|
18867
|
-
] }),
|
|
18868
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-scan-line" }),
|
|
18869
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-scan-overlay" }),
|
|
18870
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-v2-badge", children: [
|
|
18871
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-processing-v2-badge-dot", "aria-hidden": "true" }),
|
|
18872
|
-
t2("ANALYZING BODY MAP")
|
|
18873
|
-
] })
|
|
18874
|
-
] }),
|
|
18875
|
-
Panel
|
|
18876
|
-
] });
|
|
18877
|
-
}
|
|
18878
18918
|
const SKELETON_CONNECTIONS$1 = [
|
|
18879
18919
|
["leftShoulder", "rightShoulder"],
|
|
18880
18920
|
["leftShoulder", "leftElbow"],
|
|
@@ -18960,30 +19000,6 @@ function MobileScanningView({
|
|
|
18960
19000
|
onSwitchToManual,
|
|
18961
19001
|
t: t2
|
|
18962
19002
|
}) {
|
|
18963
|
-
if (tryOnProcessing) {
|
|
18964
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-root", children: [
|
|
18965
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
18966
|
-
EngagingTryOnView,
|
|
18967
|
-
{
|
|
18968
|
-
previewUrl,
|
|
18969
|
-
productMaterial,
|
|
18970
|
-
productDescription,
|
|
18971
|
-
onCancel: onCancelTryOn,
|
|
18972
|
-
t: t2
|
|
18973
|
-
}
|
|
18974
|
-
),
|
|
18975
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
18976
|
-
MobileBottomTabs,
|
|
18977
|
-
{
|
|
18978
|
-
mode: "scan",
|
|
18979
|
-
onSwitchToManual,
|
|
18980
|
-
onSwitchToScan: () => {
|
|
18981
|
-
},
|
|
18982
|
-
t: t2
|
|
18983
|
-
}
|
|
18984
|
-
) })
|
|
18985
|
-
] });
|
|
18986
|
-
}
|
|
18987
19003
|
const displayImage = previewUrl || productImage || "";
|
|
18988
19004
|
const isPhotoMode = !!previewUrl;
|
|
18989
19005
|
const stages = isPhotoMode ? [
|
|
@@ -19003,11 +19019,18 @@ function MobileScanningView({
|
|
|
19003
19019
|
const img = e.currentTarget;
|
|
19004
19020
|
setDims({ w: img.naturalWidth || img.offsetWidth, h: img.naturalHeight || img.offsetHeight });
|
|
19005
19021
|
};
|
|
19022
|
+
const TOTAL_MS = 6e3;
|
|
19023
|
+
const LAST_HOLD_MS = 1e3;
|
|
19024
|
+
const startRef = reactExports.useRef(Date.now());
|
|
19006
19025
|
const [stageIdx, setStageIdx] = reactExports.useState(0);
|
|
19007
19026
|
reactExports.useEffect(() => {
|
|
19027
|
+
const stepMs = (TOTAL_MS - LAST_HOLD_MS) / Math.max(1, stages.length - 1);
|
|
19008
19028
|
const id2 = setInterval(() => {
|
|
19009
|
-
|
|
19010
|
-
|
|
19029
|
+
const elapsed = Date.now() - startRef.current;
|
|
19030
|
+
const idx = Math.min(stages.length - 1, Math.floor(elapsed / stepMs));
|
|
19031
|
+
setStageIdx((prev) => prev === idx ? prev : idx);
|
|
19032
|
+
if (idx >= stages.length - 1) clearInterval(id2);
|
|
19033
|
+
}, 100);
|
|
19011
19034
|
return () => clearInterval(id2);
|
|
19012
19035
|
}, [stages.length]);
|
|
19013
19036
|
reactExports.useEffect(() => {
|
|
@@ -19242,6 +19265,132 @@ function MultiSectionMobile({
|
|
|
19242
19265
|
sizeGuide ? null : null
|
|
19243
19266
|
] });
|
|
19244
19267
|
}
|
|
19268
|
+
const TARGET_SECONDS = 22;
|
|
19269
|
+
function TryOnGenerationBadge({
|
|
19270
|
+
tryOnStartedAt,
|
|
19271
|
+
t: t2
|
|
19272
|
+
}) {
|
|
19273
|
+
const [, force] = reactExports.useState(0);
|
|
19274
|
+
reactExports.useEffect(() => {
|
|
19275
|
+
if (tryOnStartedAt == null) return;
|
|
19276
|
+
const id2 = setInterval(() => force((v2) => v2 + 1), 200);
|
|
19277
|
+
return () => clearInterval(id2);
|
|
19278
|
+
}, [tryOnStartedAt]);
|
|
19279
|
+
if (tryOnStartedAt == null) return null;
|
|
19280
|
+
const elapsed = (Date.now() - tryOnStartedAt) / 1e3;
|
|
19281
|
+
const pct = Math.min(95, elapsed / TARGET_SECONDS * 100);
|
|
19282
|
+
const pctRounded = Math.round(pct);
|
|
19283
|
+
const remaining = Math.max(0, TARGET_SECONDS - Math.floor(elapsed));
|
|
19284
|
+
const etaText = elapsed >= TARGET_SECONDS ? t2("almost done") : `~${remaining}s ${t2("left")}`;
|
|
19285
|
+
const statuses = [
|
|
19286
|
+
t2("Preparing your image"),
|
|
19287
|
+
t2("Analyzing body proportions"),
|
|
19288
|
+
t2("Mapping garment to body"),
|
|
19289
|
+
t2("Refining drape and shadows"),
|
|
19290
|
+
t2("Almost done")
|
|
19291
|
+
];
|
|
19292
|
+
const stepIdx = Math.min(
|
|
19293
|
+
statuses.length - 1,
|
|
19294
|
+
Math.floor(elapsed / TARGET_SECONDS * statuses.length)
|
|
19295
|
+
);
|
|
19296
|
+
const status = statuses[stepIdx];
|
|
19297
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge", role: "status", "aria-live": "polite", children: [
|
|
19298
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-row", children: [
|
|
19299
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-spinner", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "22", height: "22", children: [
|
|
19300
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("defs", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("linearGradient", { id: "ps-tryon-badge-grad", x1: "0", y1: "0", x2: "1", y2: "1", children: [
|
|
19301
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "0%", stopColor: "#3B82F6" }),
|
|
19302
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("stop", { offset: "100%", stopColor: "#2563EB" })
|
|
19303
|
+
] }) }),
|
|
19304
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "rgba(59,130,246,0.18)", strokeWidth: "2.4" }),
|
|
19305
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19306
|
+
"circle",
|
|
19307
|
+
{
|
|
19308
|
+
cx: "12",
|
|
19309
|
+
cy: "12",
|
|
19310
|
+
r: "9",
|
|
19311
|
+
fill: "none",
|
|
19312
|
+
stroke: "url(#ps-tryon-badge-grad)",
|
|
19313
|
+
strokeWidth: "2.4",
|
|
19314
|
+
strokeLinecap: "round",
|
|
19315
|
+
strokeDasharray: "56.5",
|
|
19316
|
+
strokeDashoffset: "38"
|
|
19317
|
+
}
|
|
19318
|
+
)
|
|
19319
|
+
] }) }),
|
|
19320
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-title", children: t2("Generating your look...") }),
|
|
19321
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-pct", children: [
|
|
19322
|
+
pctRounded,
|
|
19323
|
+
"%"
|
|
19324
|
+
] })
|
|
19325
|
+
] }),
|
|
19326
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-badge-bar-fill", style: { width: `${pctRounded}%` } }) }),
|
|
19327
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-badge-foot", children: [
|
|
19328
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-status", children: [
|
|
19329
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-badge-status-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
19330
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6", y1: "10", x2: "6", y2: "14" }),
|
|
19331
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "10", y1: "6", x2: "10", y2: "18" }),
|
|
19332
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "14", y1: "9", x2: "14", y2: "15" }),
|
|
19333
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "11", x2: "18", y2: "13" })
|
|
19334
|
+
] }) }),
|
|
19335
|
+
status
|
|
19336
|
+
] }),
|
|
19337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-badge-eta", children: [
|
|
19338
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
19339
|
+
"svg",
|
|
19340
|
+
{
|
|
19341
|
+
width: "11",
|
|
19342
|
+
height: "11",
|
|
19343
|
+
viewBox: "0 0 24 24",
|
|
19344
|
+
fill: "none",
|
|
19345
|
+
stroke: "currentColor",
|
|
19346
|
+
strokeWidth: "2",
|
|
19347
|
+
strokeLinecap: "round",
|
|
19348
|
+
strokeLinejoin: "round",
|
|
19349
|
+
"aria-hidden": "true",
|
|
19350
|
+
children: [
|
|
19351
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
19352
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("polyline", { points: "12 6 12 12 16 14" })
|
|
19353
|
+
]
|
|
19354
|
+
}
|
|
19355
|
+
),
|
|
19356
|
+
etaText
|
|
19357
|
+
] })
|
|
19358
|
+
] })
|
|
19359
|
+
] });
|
|
19360
|
+
}
|
|
19361
|
+
const PER_SLIDE = 3;
|
|
19362
|
+
const CYCLE_MS = 4e3;
|
|
19363
|
+
function ProductPhotoCarouselCard({
|
|
19364
|
+
photos,
|
|
19365
|
+
productTitle,
|
|
19366
|
+
t: t2
|
|
19367
|
+
}) {
|
|
19368
|
+
const [groupIdx, setGroupIdx] = reactExports.useState(0);
|
|
19369
|
+
const totalGroups = Math.max(1, Math.ceil(photos.length / PER_SLIDE));
|
|
19370
|
+
reactExports.useEffect(() => {
|
|
19371
|
+
if (totalGroups < 2) return;
|
|
19372
|
+
const id2 = setInterval(() => setGroupIdx((v2) => (v2 + 1) % totalGroups), CYCLE_MS);
|
|
19373
|
+
return () => clearInterval(id2);
|
|
19374
|
+
}, [totalGroups]);
|
|
19375
|
+
if (!photos || photos.length === 0) return null;
|
|
19376
|
+
const start = groupIdx * PER_SLIDE;
|
|
19377
|
+
const slide = photos.slice(start, start + PER_SLIDE);
|
|
19378
|
+
while (slide.length < PER_SLIDE && photos.length >= PER_SLIDE) {
|
|
19379
|
+
slide.push(photos[(start + slide.length) % photos.length]);
|
|
19380
|
+
}
|
|
19381
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-photo-strip", role: "group", "aria-label": t2("Product photos"), children: [
|
|
19382
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-head", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-photo-strip-badge", children: [
|
|
19383
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
19384
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
19385
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
19386
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
19387
|
+
] }),
|
|
19388
|
+
t2("Gallery")
|
|
19389
|
+
] }) }),
|
|
19390
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-row", children: slide.map((src, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-cell", children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src, alt: productTitle || "", draggable: false }) }, `${groupIdx}-${i}`)) }, groupIdx),
|
|
19391
|
+
totalGroups > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-dots", "aria-hidden": "true", children: Array.from({ length: totalGroups }).map((_, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ps-tryon-photo-strip-dot${i === groupIdx ? " is-active" : ""}` }, i)) })
|
|
19392
|
+
] });
|
|
19393
|
+
}
|
|
19245
19394
|
function garmentIconForSection(name) {
|
|
19246
19395
|
const n2 = name.toLowerCase();
|
|
19247
19396
|
if (n2.includes("jacket") || n2.includes("blazer") || n2.includes("coat")) return garmentJacketImg;
|
|
@@ -19265,62 +19414,6 @@ const SKELETON_CONNECTIONS = [
|
|
|
19265
19414
|
["rightHip", "rightKnee"],
|
|
19266
19415
|
["rightKnee", "rightAnkle"]
|
|
19267
19416
|
];
|
|
19268
|
-
const TRYON_TARGET_SECONDS = 22;
|
|
19269
|
-
const TRYON_RING_RADIUS = 27;
|
|
19270
|
-
const TRYON_RING_CIRC = 2 * Math.PI * TRYON_RING_RADIUS;
|
|
19271
|
-
function TryOnProgress({ t: t2, isActive }) {
|
|
19272
|
-
const startRef = reactExports.useRef(null);
|
|
19273
|
-
const ringRef = reactExports.useRef(null);
|
|
19274
|
-
const barRef = reactExports.useRef(null);
|
|
19275
|
-
const etaRef = reactExports.useRef(null);
|
|
19276
|
-
const pctRef = reactExports.useRef(null);
|
|
19277
|
-
reactExports.useEffect(() => {
|
|
19278
|
-
if (!isActive) {
|
|
19279
|
-
startRef.current = null;
|
|
19280
|
-
return;
|
|
19281
|
-
}
|
|
19282
|
-
startRef.current = Date.now();
|
|
19283
|
-
const id2 = setInterval(() => {
|
|
19284
|
-
const start = startRef.current || Date.now();
|
|
19285
|
-
const elapsed = (Date.now() - start) / 1e3;
|
|
19286
|
-
const pct = Math.min(95, elapsed / TRYON_TARGET_SECONDS * 100);
|
|
19287
|
-
const val = Math.round(pct);
|
|
19288
|
-
if (barRef.current) barRef.current.style.width = `${val}%`;
|
|
19289
|
-
if (pctRef.current) pctRef.current.textContent = `${val}%`;
|
|
19290
|
-
if (ringRef.current) {
|
|
19291
|
-
ringRef.current.style.strokeDashoffset = String(TRYON_RING_CIRC * (1 - pct / 100));
|
|
19292
|
-
}
|
|
19293
|
-
if (etaRef.current) {
|
|
19294
|
-
const remaining = Math.max(0, TRYON_TARGET_SECONDS - Math.floor(elapsed));
|
|
19295
|
-
etaRef.current.textContent = elapsed >= TRYON_TARGET_SECONDS ? "•••" : `~${remaining}s`;
|
|
19296
|
-
}
|
|
19297
|
-
}, 200);
|
|
19298
|
-
return () => clearInterval(id2);
|
|
19299
|
-
}, [isActive]);
|
|
19300
|
-
if (!isActive) return null;
|
|
19301
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-wrap", children: [
|
|
19302
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-ring", children: [
|
|
19303
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "64", height: "64", viewBox: "0 0 64 64", "aria-hidden": "true", children: [
|
|
19304
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "32", cy: "32", r: TRYON_RING_RADIUS, className: "ps-tryon-progress-ring-track" }),
|
|
19305
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19306
|
-
"circle",
|
|
19307
|
-
{
|
|
19308
|
-
ref: ringRef,
|
|
19309
|
-
cx: "32",
|
|
19310
|
-
cy: "32",
|
|
19311
|
-
r: TRYON_RING_RADIUS,
|
|
19312
|
-
className: "ps-tryon-progress-ring-fill",
|
|
19313
|
-
strokeDasharray: TRYON_RING_CIRC,
|
|
19314
|
-
strokeDashoffset: TRYON_RING_CIRC
|
|
19315
|
-
}
|
|
19316
|
-
)
|
|
19317
|
-
] }),
|
|
19318
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: etaRef, className: "ps-tryon-progress-eta", children: `~${TRYON_TARGET_SECONDS}s` })
|
|
19319
|
-
] }),
|
|
19320
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: barRef, className: "ps-tryon-progress-bar-fill" }) }),
|
|
19321
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: pctRef, className: "ps-tryon-progress-pct", children: "0%" })
|
|
19322
|
-
] });
|
|
19323
|
-
}
|
|
19324
19417
|
function FaceOverlay({
|
|
19325
19418
|
landmarks,
|
|
19326
19419
|
imgWidth,
|
|
@@ -19447,14 +19540,20 @@ function StageCycler({
|
|
|
19447
19540
|
{ title: t2("MATCHING SIZE"), desc: t2("Comparing your measurements to the size guide.") },
|
|
19448
19541
|
{ title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation.") }
|
|
19449
19542
|
];
|
|
19543
|
+
const TOTAL_MS = 6e3;
|
|
19544
|
+
const LAST_HOLD_MS = 1e3;
|
|
19545
|
+
const startRef = reactExports.useRef(Date.now());
|
|
19450
19546
|
const [idx, setIdx] = reactExports.useState(0);
|
|
19451
19547
|
reactExports.useEffect(() => {
|
|
19452
|
-
|
|
19548
|
+
const stepMs = (TOTAL_MS - LAST_HOLD_MS) / Math.max(1, sizingStages.length - 1);
|
|
19453
19549
|
const id2 = setInterval(() => {
|
|
19454
|
-
|
|
19455
|
-
|
|
19550
|
+
const elapsed = Date.now() - startRef.current;
|
|
19551
|
+
const next = Math.min(sizingStages.length - 1, Math.floor(elapsed / stepMs));
|
|
19552
|
+
setIdx((prev) => prev === next ? prev : next);
|
|
19553
|
+
if (next >= sizingStages.length - 1) clearInterval(id2);
|
|
19554
|
+
}, 100);
|
|
19456
19555
|
return () => clearInterval(id2);
|
|
19457
|
-
}, [
|
|
19556
|
+
}, [sizingStages.length]);
|
|
19458
19557
|
const current = sizingStages[idx] ?? sizingStages[0];
|
|
19459
19558
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage", style: { alignSelf: "center", marginTop: "auto", marginBottom: "auto" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage-slot", children: [
|
|
19460
19559
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
|
|
@@ -19728,19 +19827,11 @@ function SectionDetailView({
|
|
|
19728
19827
|
internationalSizes,
|
|
19729
19828
|
continueLabel,
|
|
19730
19829
|
renderRaw = false,
|
|
19731
|
-
sectionFound
|
|
19732
|
-
onSelectForTryOn,
|
|
19733
|
-
onRegenerateTryOn,
|
|
19734
|
-
pendingOverride,
|
|
19735
|
-
retryLoading,
|
|
19736
|
-
retryStartedAt
|
|
19830
|
+
sectionFound
|
|
19737
19831
|
}) {
|
|
19738
19832
|
const recSize = sectionResult?.recommendedSize || "";
|
|
19739
|
-
const [selectedSize, setSelectedSize] = reactExports.useState(
|
|
19740
|
-
pendingOverride?.selectedSize && pendingOverride.selectedSize !== (sectionResult?.recommendedSize || "") ? pendingOverride.selectedSize : null
|
|
19741
|
-
);
|
|
19833
|
+
const [selectedSize, setSelectedSize] = reactExports.useState(null);
|
|
19742
19834
|
const tryOnElapsedS = useElapsedSeconds(tryOnStartedAt ?? null);
|
|
19743
|
-
const retryElapsedS = useElapsedSeconds(retryStartedAt ?? null);
|
|
19744
19835
|
const unitLblLower = unitLbl.toLowerCase();
|
|
19745
19836
|
const displayUnitId = unitLblLower.includes("mm") ? "mm" : unitLblLower.includes("cm") ? "cm" : "in";
|
|
19746
19837
|
const fromUnit = chartUnit || displayUnitId;
|
|
@@ -19753,9 +19844,7 @@ function SectionDetailView({
|
|
|
19753
19844
|
const countryOptions = internationalSizes ? Object.keys(internationalSizes) : [];
|
|
19754
19845
|
const [selectedCountry, setSelectedCountry] = reactExports.useState(null);
|
|
19755
19846
|
const recLength = lengthEntry?.secResult?.recommendedSize || "";
|
|
19756
|
-
const [selectedLength, setSelectedLength] = reactExports.useState(
|
|
19757
|
-
pendingOverride?.selectedLength && pendingOverride.selectedLength !== recLength ? pendingOverride.selectedLength : null
|
|
19758
|
-
);
|
|
19847
|
+
const [selectedLength, setSelectedLength] = reactExports.useState(null);
|
|
19759
19848
|
const lengthSizes = reactExports.useMemo(() => {
|
|
19760
19849
|
if (!lengthEntry) return [];
|
|
19761
19850
|
const sec = lengthEntry.section;
|
|
@@ -19982,8 +20071,8 @@ function SectionDetailView({
|
|
|
19982
20071
|
const userInColUnit = colIsCm && userIsInches ? +(userNum2 * 2.54).toFixed(1) : !colIsCm && !userIsInches ? +(userNum2 * 2.54).toFixed(1) : userNum2;
|
|
19983
20072
|
const range2 = rMaxRaw - rMinRaw;
|
|
19984
20073
|
const threshold2 = range2 > 0 ? range2 * 0.5 : rMinRaw * 0.05 || 3;
|
|
19985
|
-
const
|
|
19986
|
-
if (userInColUnit
|
|
20074
|
+
const tol = colIsCm ? 2.54 : 1;
|
|
20075
|
+
if (userInColUnit > rMinRaw - tol && userInColUnit < rMaxRaw + tol) fit2 = "good";
|
|
19987
20076
|
else if (userInColUnit < rMinRaw) {
|
|
19988
20077
|
const diff = rMinRaw - userInColUnit;
|
|
19989
20078
|
fit2 = diff > threshold2 * 2 ? "too-long" : diff > threshold2 ? "long" : "a-bit-long";
|
|
@@ -20016,8 +20105,10 @@ function SectionDetailView({
|
|
|
20016
20105
|
const measLower = m2.measurement.toLowerCase();
|
|
20017
20106
|
const isDirectional = /length|inseam|sleeve|hem|rise/.test(measLower);
|
|
20018
20107
|
let fit;
|
|
20019
|
-
const
|
|
20020
|
-
|
|
20108
|
+
const perfectTol = chartUnit === "cm" ? 2.54 : chartUnit === "mm" ? 25.4 : 1;
|
|
20109
|
+
const lowBound = rMin - perfectTol;
|
|
20110
|
+
const highBound = rMax + perfectTol;
|
|
20111
|
+
if (userNum > lowBound && userNum < highBound) {
|
|
20021
20112
|
fit = "good";
|
|
20022
20113
|
} else if (isDirectional) {
|
|
20023
20114
|
const diff = userNum > rMax ? userNum - rMax : rMin - userNum;
|
|
@@ -20064,65 +20155,6 @@ function SectionDetailView({
|
|
|
20064
20155
|
const start = Math.max(0, Math.min(lengthOptions.length - 3, idx - 1));
|
|
20065
20156
|
return lengthOptions.slice(start, start + 3);
|
|
20066
20157
|
})();
|
|
20067
|
-
const autoCommitInitialMount = reactExports.useRef(true);
|
|
20068
|
-
reactExports.useLayoutEffect(() => {
|
|
20069
|
-
if (autoCommitInitialMount.current) {
|
|
20070
|
-
autoCommitInitialMount.current = false;
|
|
20071
|
-
return;
|
|
20072
|
-
}
|
|
20073
|
-
if (!onSelectForTryOn) return;
|
|
20074
|
-
const effSize = displaySize;
|
|
20075
|
-
const effLength = selectedLength || backendLength || "";
|
|
20076
|
-
const hasSizePick = !!selectedSize && selectedSize !== recSize;
|
|
20077
|
-
const hasLengthPick = !!selectedLength && selectedLength !== backendLength;
|
|
20078
|
-
if (!hasSizePick && !hasLengthPick) {
|
|
20079
|
-
onSelectForTryOn(sectionName, null);
|
|
20080
|
-
return;
|
|
20081
|
-
}
|
|
20082
|
-
const mainDetails = sectionResult?.matchDetails || [];
|
|
20083
|
-
const lengthMeasurements = new Set(
|
|
20084
|
-
(lengthEntry?.secResult?.matchDetails || []).map((m2) => m2.measurement.toLowerCase())
|
|
20085
|
-
);
|
|
20086
|
-
const overrideMd = mainDetails.length ? mainDetails.map((m2) => {
|
|
20087
|
-
const measLc = m2.measurement.toLowerCase();
|
|
20088
|
-
if (lengthMeasurements.has(measLc) && lengthEntry) {
|
|
20089
|
-
const sec = lengthEntry.section;
|
|
20090
|
-
const sizeCol = sec.headers.findIndex((h) => /size|length/i.test(h.trim()));
|
|
20091
|
-
const sIdx = sizeCol >= 0 ? sizeCol : 0;
|
|
20092
|
-
const targetCol = sec.headers.findIndex((h) => {
|
|
20093
|
-
const hLc = h.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim();
|
|
20094
|
-
return !!hLc && (hLc === measLc || hLc.includes(measLc) || measLc.includes(hLc));
|
|
20095
|
-
});
|
|
20096
|
-
if (targetCol < 0) return m2;
|
|
20097
|
-
const row = sec.rows.find((r2) => cellValFn(r2, sIdx, sec.headers[sIdx]) === effLength);
|
|
20098
|
-
if (!row) return m2;
|
|
20099
|
-
const cell = cellValFn(row, targetCol, sec.headers[targetCol]);
|
|
20100
|
-
return cell ? { ...m2, chartRange: cell } : m2;
|
|
20101
|
-
}
|
|
20102
|
-
const alt = chartRangeFor(m2.measurement, effSize);
|
|
20103
|
-
if (alt?.range) return { ...m2, chartRange: alt.range };
|
|
20104
|
-
return m2;
|
|
20105
|
-
}) : void 0;
|
|
20106
|
-
const label = effLength ? `${effSize} / ${effLength}` : effSize;
|
|
20107
|
-
console.log(`[ps-sdk:auto-commit] section="${sectionName}" label="${label}"`, {
|
|
20108
|
-
selectedSize,
|
|
20109
|
-
selectedLength,
|
|
20110
|
-
recSize,
|
|
20111
|
-
backendLength,
|
|
20112
|
-
overrideMdPreview: overrideMd?.map((m2) => ({
|
|
20113
|
-
area: m2.measurement,
|
|
20114
|
-
userValue: m2.userValue,
|
|
20115
|
-
chartRange: m2.chartRange
|
|
20116
|
-
}))
|
|
20117
|
-
});
|
|
20118
|
-
onSelectForTryOn(sectionName, {
|
|
20119
|
-
sectionName,
|
|
20120
|
-
selectedSize: effSize,
|
|
20121
|
-
selectedLength: hasLengthPick ? effLength : void 0,
|
|
20122
|
-
displayLabel: label,
|
|
20123
|
-
matchDetails: overrideMd
|
|
20124
|
-
});
|
|
20125
|
-
}, [selectedSize, selectedLength]);
|
|
20126
20158
|
if (isMobileProp) {
|
|
20127
20159
|
const cleanSectionName = sectionName.replace(/\s*[—–-]\s*.*/g, "");
|
|
20128
20160
|
const measurementDesc = (area) => {
|
|
@@ -20606,169 +20638,7 @@ function SectionDetailView({
|
|
|
20606
20638
|
s
|
|
20607
20639
|
);
|
|
20608
20640
|
}) })
|
|
20609
|
-
] })
|
|
20610
|
-
(onRegenerateTryOn || onSelectForTryOn && (!isRecommended || selectedLength && selectedLength !== backendLength)) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: "0.6vw", marginBottom: "0.2vw" }, children: (() => {
|
|
20611
|
-
const effSize = displaySize;
|
|
20612
|
-
const effLength = selectedLength || backendLength || "";
|
|
20613
|
-
const hasLengthPick = !!(selectedLength && selectedLength !== backendLength);
|
|
20614
|
-
const label = effLength ? `${effSize} / ${effLength}` : effSize;
|
|
20615
|
-
const buildOverrideMatchDetails = () => {
|
|
20616
|
-
const mainDetails = sectionResult?.matchDetails || [];
|
|
20617
|
-
if (!mainDetails.length) return void 0;
|
|
20618
|
-
const lengthMeasurements = new Set(
|
|
20619
|
-
(lengthEntry?.secResult?.matchDetails || []).map((m2) => m2.measurement.toLowerCase())
|
|
20620
|
-
);
|
|
20621
|
-
const out = mainDetails.map((m2) => {
|
|
20622
|
-
const measLc = m2.measurement.toLowerCase();
|
|
20623
|
-
if (lengthMeasurements.has(measLc) && lengthEntry) {
|
|
20624
|
-
const numericPick = effLength && !Number.isNaN(parseFloat(effLength)) ? effLength : null;
|
|
20625
|
-
if (numericPick) {
|
|
20626
|
-
return { ...m2, chartRange: numericPick };
|
|
20627
|
-
}
|
|
20628
|
-
const sec = lengthEntry.section;
|
|
20629
|
-
const sizeCol = sec.headers.findIndex((h) => /size|length/i.test(h.trim()));
|
|
20630
|
-
const sIdx = sizeCol >= 0 ? sizeCol : 0;
|
|
20631
|
-
const targetCol = sec.headers.findIndex((h) => {
|
|
20632
|
-
const hLc = h.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim();
|
|
20633
|
-
return !!hLc && (hLc === measLc || hLc.includes(measLc) || measLc.includes(hLc));
|
|
20634
|
-
});
|
|
20635
|
-
if (targetCol < 0) return m2;
|
|
20636
|
-
const row = sec.rows.find((r2) => cellValFn(r2, sIdx, sec.headers[sIdx]) === effLength);
|
|
20637
|
-
if (!row) return m2;
|
|
20638
|
-
const cell = cellValFn(row, targetCol, sec.headers[targetCol]);
|
|
20639
|
-
return cell ? { ...m2, chartRange: cell } : m2;
|
|
20640
|
-
}
|
|
20641
|
-
const alt = chartRangeFor(m2.measurement, effSize);
|
|
20642
|
-
if (alt?.range) return { ...m2, chartRange: alt.range };
|
|
20643
|
-
return m2;
|
|
20644
|
-
});
|
|
20645
|
-
if (effLength && Number.isNaN(parseFloat(effLength))) {
|
|
20646
|
-
out.push({
|
|
20647
|
-
measurement: "Length",
|
|
20648
|
-
userValue: "",
|
|
20649
|
-
chartRange: effLength,
|
|
20650
|
-
fit: "good"
|
|
20651
|
-
});
|
|
20652
|
-
}
|
|
20653
|
-
return out;
|
|
20654
|
-
};
|
|
20655
|
-
const isStored = pendingOverride?.selectedSize === effSize;
|
|
20656
|
-
if (onRegenerateTryOn) {
|
|
20657
|
-
const isRegenerating = !!retryLoading;
|
|
20658
|
-
const TARGET_S = 22;
|
|
20659
|
-
const countdownS = isRegenerating ? Math.max(0, TARGET_S - retryElapsedS) : TARGET_S;
|
|
20660
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
20661
|
-
"button",
|
|
20662
|
-
{
|
|
20663
|
-
type: "button",
|
|
20664
|
-
"data-ps-regen": "1",
|
|
20665
|
-
disabled: isRegenerating,
|
|
20666
|
-
onClick: () => {
|
|
20667
|
-
const md2 = buildOverrideMatchDetails();
|
|
20668
|
-
onRegenerateTryOn({
|
|
20669
|
-
sectionName,
|
|
20670
|
-
selectedSize: effSize,
|
|
20671
|
-
selectedLength: hasLengthPick ? effLength : void 0,
|
|
20672
|
-
displayLabel: label,
|
|
20673
|
-
matchDetails: md2
|
|
20674
|
-
});
|
|
20675
|
-
},
|
|
20676
|
-
style: {
|
|
20677
|
-
width: "100%",
|
|
20678
|
-
padding: "0.55vw 0.8vw",
|
|
20679
|
-
borderRadius: "0.45vw",
|
|
20680
|
-
fontSize: "0.7vw",
|
|
20681
|
-
fontWeight: 700,
|
|
20682
|
-
background: "var(--ps-accent)",
|
|
20683
|
-
color: "#FFFFFF",
|
|
20684
|
-
border: "1.5px solid var(--ps-accent)",
|
|
20685
|
-
cursor: isRegenerating ? "progress" : "pointer",
|
|
20686
|
-
fontFamily: "inherit",
|
|
20687
|
-
display: "flex",
|
|
20688
|
-
alignItems: "center",
|
|
20689
|
-
justifyContent: "center",
|
|
20690
|
-
gap: "0.4vw",
|
|
20691
|
-
position: "relative",
|
|
20692
|
-
overflow: "hidden"
|
|
20693
|
-
},
|
|
20694
|
-
children: [
|
|
20695
|
-
isRegenerating && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20696
|
-
"div",
|
|
20697
|
-
{
|
|
20698
|
-
className: "ps-tryon-regen-fill",
|
|
20699
|
-
"aria-hidden": "true"
|
|
20700
|
-
},
|
|
20701
|
-
retryStartedAt ?? "regen"
|
|
20702
|
-
),
|
|
20703
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { position: "relative", zIndex: 1 }, children: isRegenerating ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
20704
|
-
t2("Generating new try-on…"),
|
|
20705
|
-
" ",
|
|
20706
|
-
countdownS,
|
|
20707
|
-
"s"
|
|
20708
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
20709
|
-
t2("Try It On"),
|
|
20710
|
-
" ",
|
|
20711
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontSize: "0.65vw", opacity: 0.9 }, children: [
|
|
20712
|
-
"(",
|
|
20713
|
-
label,
|
|
20714
|
-
")"
|
|
20715
|
-
] })
|
|
20716
|
-
] }) })
|
|
20717
|
-
]
|
|
20718
|
-
}
|
|
20719
|
-
);
|
|
20720
|
-
}
|
|
20721
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20722
|
-
"button",
|
|
20723
|
-
{
|
|
20724
|
-
type: "button",
|
|
20725
|
-
onClick: () => {
|
|
20726
|
-
if (!onSelectForTryOn) return;
|
|
20727
|
-
onSelectForTryOn(sectionName, isStored ? null : {
|
|
20728
|
-
sectionName,
|
|
20729
|
-
selectedSize: effSize,
|
|
20730
|
-
selectedLength: hasLengthPick ? effLength : void 0,
|
|
20731
|
-
displayLabel: label,
|
|
20732
|
-
matchDetails: buildOverrideMatchDetails()
|
|
20733
|
-
});
|
|
20734
|
-
},
|
|
20735
|
-
style: {
|
|
20736
|
-
width: "100%",
|
|
20737
|
-
padding: "0.55vw 0.8vw",
|
|
20738
|
-
borderRadius: "0.45vw",
|
|
20739
|
-
fontSize: "0.7vw",
|
|
20740
|
-
fontWeight: 700,
|
|
20741
|
-
background: isStored ? "var(--ps-accent)" : "transparent",
|
|
20742
|
-
color: isStored ? "#FFFFFF" : "var(--ps-accent)",
|
|
20743
|
-
border: `1.5px ${isStored ? "solid" : "dashed"} var(--ps-accent)`,
|
|
20744
|
-
cursor: "pointer",
|
|
20745
|
-
fontFamily: "inherit",
|
|
20746
|
-
display: "flex",
|
|
20747
|
-
alignItems: "center",
|
|
20748
|
-
justifyContent: "center",
|
|
20749
|
-
gap: "0.4vw",
|
|
20750
|
-
transition: "background 0.15s, color 0.15s"
|
|
20751
|
-
},
|
|
20752
|
-
children: isStored ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
20753
|
-
t2("Will use this on Try On"),
|
|
20754
|
-
" ",
|
|
20755
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontSize: "0.65vw", opacity: 0.9 }, children: [
|
|
20756
|
-
"(",
|
|
20757
|
-
label,
|
|
20758
|
-
") ✓"
|
|
20759
|
-
] })
|
|
20760
|
-
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
20761
|
-
t2("Use this for Try On"),
|
|
20762
|
-
" ",
|
|
20763
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontSize: "0.65vw", opacity: 0.75 }, children: [
|
|
20764
|
-
"(",
|
|
20765
|
-
label,
|
|
20766
|
-
")"
|
|
20767
|
-
] })
|
|
20768
|
-
] })
|
|
20769
|
-
}
|
|
20770
|
-
);
|
|
20771
|
-
})() })
|
|
20641
|
+
] })
|
|
20772
20642
|
] }) }),
|
|
20773
20643
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", paddingTop: "0.6vw", borderTop: "1px solid rgba(0,0,0,0.06)", flexShrink: 0 }, children: [
|
|
20774
20644
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-bp-back-btn", onClick: onBack, type: "button", style: { fontSize: "0.7vw" }, children: [
|
|
@@ -20844,15 +20714,13 @@ function SizeResultView({
|
|
|
20844
20714
|
sizeGuide,
|
|
20845
20715
|
resultImageUrl,
|
|
20846
20716
|
productImage,
|
|
20717
|
+
productImages,
|
|
20847
20718
|
productTitle,
|
|
20848
20719
|
productMaterial,
|
|
20849
20720
|
productDescription,
|
|
20850
20721
|
sizingUnit,
|
|
20851
20722
|
setView,
|
|
20852
20723
|
handleDownload,
|
|
20853
|
-
onRetryWithFit,
|
|
20854
|
-
retryLoading,
|
|
20855
|
-
retryStartedAt,
|
|
20856
20724
|
selectedFile,
|
|
20857
20725
|
previewUrl,
|
|
20858
20726
|
handleFileSelect,
|
|
@@ -20871,7 +20739,6 @@ function SizeResultView({
|
|
|
20871
20739
|
userHeightCm,
|
|
20872
20740
|
pendingCustomSizes: pendingCustomSizesProp,
|
|
20873
20741
|
onPendingCustomSizeChange,
|
|
20874
|
-
onRegenerateTryOn,
|
|
20875
20742
|
t: t2
|
|
20876
20743
|
}) {
|
|
20877
20744
|
const resultUnitRaw = (sizingResult?.unit || sizingUnit || "").toString().toLowerCase();
|
|
@@ -20977,9 +20844,6 @@ function SizeResultView({
|
|
|
20977
20844
|
const [poseReady, setPoseReady] = reactExports.useState(false);
|
|
20978
20845
|
const [imgDims, setImgDims] = reactExports.useState({ w: 800, h: 1200 });
|
|
20979
20846
|
const pendingCustomSizes = pendingCustomSizesProp ?? {};
|
|
20980
|
-
const setPendingCustomSize = (sectionName, override) => {
|
|
20981
|
-
onPendingCustomSizeChange?.(sectionName, override);
|
|
20982
|
-
};
|
|
20983
20847
|
const handleImgLoad = reactExports.useCallback((e) => {
|
|
20984
20848
|
const el2 = e.currentTarget;
|
|
20985
20849
|
if (el2.naturalWidth && el2.naturalHeight) {
|
|
@@ -21148,7 +21012,7 @@ function SizeResultView({
|
|
|
21148
21012
|
const prettyLength = lengthRec.replace(/\s+/g, " ").trim();
|
|
21149
21013
|
return `${baseSize} / ${prettyLength}`;
|
|
21150
21014
|
}, [lengthEntries, allSectionEntries]);
|
|
21151
|
-
|
|
21015
|
+
reactExports.useMemo(() => {
|
|
21152
21016
|
const cm = userHeightCm || 0;
|
|
21153
21017
|
if (!cm) return "";
|
|
21154
21018
|
if (unitLbl === "in") {
|
|
@@ -21160,8 +21024,8 @@ function SizeResultView({
|
|
|
21160
21024
|
return `${Math.round(cm)} cm`;
|
|
21161
21025
|
}, [userHeightCm, unitLbl]);
|
|
21162
21026
|
const hasPhoto = !!previewUrl;
|
|
21163
|
-
const isSnapProcessing = hasPhoto &&
|
|
21164
|
-
const isSizingOnly = !hasPhoto && sizingLoading
|
|
21027
|
+
const isSnapProcessing = hasPhoto && sizingLoading;
|
|
21028
|
+
const isSizingOnly = !hasPhoto && sizingLoading;
|
|
21165
21029
|
const sizingDone = !!sizingResult;
|
|
21166
21030
|
const tryOnDone = !!resultImageUrl && !tryOnProcessing;
|
|
21167
21031
|
const allDone = hasPhoto ? sizingDone && tryOnDone : sizingDone;
|
|
@@ -21228,20 +21092,12 @@ function SizeResultView({
|
|
|
21228
21092
|
onLoad: handleImgLoad
|
|
21229
21093
|
}
|
|
21230
21094
|
),
|
|
21231
|
-
|
|
21095
|
+
measurementType === "face" || measurementType === "head" ? faceLandmarks && /* @__PURE__ */ jsxRuntimeExports.jsx(FaceOverlay, { landmarks: faceLandmarks, imgWidth: imgDims.w, imgHeight: imgDims.h }) : bodyLandmarks && /* @__PURE__ */ jsxRuntimeExports.jsx(SkeletonOverlay, { landmarks: bodyLandmarks, imgWidth: imgDims.w, imgHeight: imgDims.h })
|
|
21232
21096
|
] }),
|
|
21233
21097
|
(() => {
|
|
21234
21098
|
const isFaceCategory = measurementType === "face" || measurementType === "head";
|
|
21235
21099
|
isFaceCategory ? measurementType === "head" ? t2("Detecting head") : t2("Detecting face") : t2("Detecting body pose");
|
|
21236
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-right-col", style: { display: "flex", alignItems:
|
|
21237
|
-
EngagingTryOnView,
|
|
21238
|
-
{
|
|
21239
|
-
productMaterial,
|
|
21240
|
-
productDescription,
|
|
21241
|
-
variant: "panel-only",
|
|
21242
|
-
t: t2
|
|
21243
|
-
}
|
|
21244
|
-
) : /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21100
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-right-col", style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21245
21101
|
StageCycler,
|
|
21246
21102
|
{
|
|
21247
21103
|
category: isFaceCategory ? measurementType : "body",
|
|
@@ -21279,11 +21135,6 @@ function SizeResultView({
|
|
|
21279
21135
|
})(),
|
|
21280
21136
|
onBack: () => setActiveSection(null),
|
|
21281
21137
|
internationalSizes: entry.secResult?.internationalSizes,
|
|
21282
|
-
onSelectForTryOn: setPendingCustomSize,
|
|
21283
|
-
onRegenerateTryOn: isAccessory ? void 0 : resultImageUrl && onRegenerateTryOn ? onRegenerateTryOn : void 0,
|
|
21284
|
-
retryLoading,
|
|
21285
|
-
retryStartedAt,
|
|
21286
|
-
pendingOverride: pendingCustomSizes[entry.name] ?? null,
|
|
21287
21138
|
productImage: resultImageUrl || productImage,
|
|
21288
21139
|
productTitle,
|
|
21289
21140
|
isMobile: true,
|
|
@@ -21321,10 +21172,7 @@ function SizeResultView({
|
|
|
21321
21172
|
] });
|
|
21322
21173
|
}
|
|
21323
21174
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2", children: [
|
|
21324
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
21325
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: resultImageUrl || productImage, alt: productTitle, className: "ps-tryon-v2-bg-img" }),
|
|
21326
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RegenScanOverlay, { active: !!retryLoading && !!resultImageUrl })
|
|
21327
|
-
] }),
|
|
21175
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-bg", style: { position: "relative" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: resultImageUrl || productImage, alt: productTitle, className: "ps-tryon-v2-bg-img" }) }),
|
|
21328
21176
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-panel", children: [
|
|
21329
21177
|
mismatchNotice,
|
|
21330
21178
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -21346,11 +21194,6 @@ function SizeResultView({
|
|
|
21346
21194
|
})(),
|
|
21347
21195
|
onBack: () => setActiveSection(null),
|
|
21348
21196
|
internationalSizes: entry.secResult?.internationalSizes,
|
|
21349
|
-
onSelectForTryOn: setPendingCustomSize,
|
|
21350
|
-
onRegenerateTryOn: isAccessory ? void 0 : resultImageUrl && onRegenerateTryOn ? onRegenerateTryOn : void 0,
|
|
21351
|
-
retryLoading,
|
|
21352
|
-
retryStartedAt,
|
|
21353
|
-
pendingOverride: pendingCustomSizes[entry.name] ?? null,
|
|
21354
21197
|
t: t2
|
|
21355
21198
|
}
|
|
21356
21199
|
)
|
|
@@ -21420,11 +21263,8 @@ function SizeResultView({
|
|
|
21420
21263
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2", children: [
|
|
21421
21264
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-bg", style: { position: "relative" }, children: [
|
|
21422
21265
|
/* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: tryOnProcessing && previewUrl ? previewUrl : resultImageUrl || productImage, alt: productTitle, className: "ps-tryon-v2-bg-img", onLoad: handleImgLoad }),
|
|
21423
|
-
tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.
|
|
21424
|
-
|
|
21425
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(TryOnProgress, { t: t2, isActive: true })
|
|
21426
|
-
] }),
|
|
21427
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RegenScanOverlay, { active: !!retryLoading && !!resultImageUrl && !tryOnProcessing || !!tryOnProcessing }),
|
|
21266
|
+
tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnGenerationBadge, { tryOnStartedAt: tryOnStartedAt ?? null, t: t2 }),
|
|
21267
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RegenScanOverlay, { active: !!tryOnProcessing }),
|
|
21428
21268
|
resultImageUrl && !tryOnProcessing && poseReady && poseLines && /* @__PURE__ */ jsxRuntimeExports.jsx(MeasurementOverlay, { lines: poseLines, fitRows: (() => {
|
|
21429
21269
|
const all = [...sizingResult?.matchDetails || []];
|
|
21430
21270
|
if (sizingResult?.sections) {
|
|
@@ -21490,11 +21330,15 @@ function SizeResultView({
|
|
|
21490
21330
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21491
21331
|
"span",
|
|
21492
21332
|
{
|
|
21493
|
-
className:
|
|
21494
|
-
|
|
21495
|
-
children: isOverridden ? t2("your selection · not recommended") : heightLineLabel ? `${t2("recommended")} · ${heightLineLabel}` : t2("recommended")
|
|
21333
|
+
className: `ps-tryon-sr-card-v2-rec-pill${isOverridden ? " is-overridden" : ""}`,
|
|
21334
|
+
children: isOverridden ? t2("YOUR SELECTION") : t2("RECOMMENDED")
|
|
21496
21335
|
}
|
|
21497
|
-
)
|
|
21336
|
+
),
|
|
21337
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-sr-card-v2-view", children: [
|
|
21338
|
+
t2("VIEW DETAILS"),
|
|
21339
|
+
" ",
|
|
21340
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "›" })
|
|
21341
|
+
] })
|
|
21498
21342
|
] }),
|
|
21499
21343
|
sectionImg && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: sectionImg, alt: name, className: "ps-tryon-sr-card-v2-img" })
|
|
21500
21344
|
] }, name);
|
|
@@ -21585,11 +21429,6 @@ function SizeResultView({
|
|
|
21585
21429
|
},
|
|
21586
21430
|
backLabel: t2("Back"),
|
|
21587
21431
|
internationalSizes: sizingResult?.internationalSizes,
|
|
21588
|
-
onSelectForTryOn: setPendingCustomSize,
|
|
21589
|
-
onRegenerateTryOn: isAccessory ? void 0 : resultImageUrl && onRegenerateTryOn ? onRegenerateTryOn : void 0,
|
|
21590
|
-
retryLoading,
|
|
21591
|
-
retryStartedAt,
|
|
21592
|
-
pendingOverride: pendingCustomSizes[sectionName] ?? null,
|
|
21593
21432
|
onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
|
|
21594
21433
|
continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
|
|
21595
21434
|
tryOnProcessing,
|
|
@@ -21619,50 +21458,158 @@ function SizeResultView({
|
|
|
21619
21458
|
}
|
|
21620
21459
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2", children: [
|
|
21621
21460
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-bg", style: { position: "relative" }, children: [
|
|
21622
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21623
|
-
|
|
21461
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21462
|
+
"img",
|
|
21463
|
+
{
|
|
21464
|
+
src: tryOnProcessing && previewUrl ? previewUrl : resultImageUrl || productImage,
|
|
21465
|
+
alt: productTitle,
|
|
21466
|
+
className: "ps-tryon-v2-bg-img",
|
|
21467
|
+
onLoad: handleImgLoad
|
|
21468
|
+
}
|
|
21469
|
+
),
|
|
21470
|
+
tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnGenerationBadge, { tryOnStartedAt: tryOnStartedAt ?? null, t: t2 }),
|
|
21471
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(RegenScanOverlay, { active: !!tryOnProcessing }),
|
|
21472
|
+
resultImageUrl && !tryOnProcessing && poseReady && poseLines && /* @__PURE__ */ jsxRuntimeExports.jsx(MeasurementOverlay, { lines: poseLines, fitRows: (sizingResult?.matchDetails || []).map((m2) => ({ area: m2.measurement, userNum: parseFloat(m2.userValue) || 0, chartLabel: m2.chartRange || "", fit: m2.fit })), show: showLines, imgWidth: imgDims.w, imgHeight: imgDims.h }),
|
|
21624
21473
|
resultImageUrl && !tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { position: "absolute", bottom: "0.5vw", left: "0.5vw", zIndex: 3, display: "flex", flexDirection: "column", gap: "0.3vw" }, children: [
|
|
21625
21474
|
!isAccessory && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ps-tryon-sr-glass-btn", onClick: () => setShowLines(!showLines), children: showLines ? t2("Hide Fit") : t2("Show Fit") }),
|
|
21626
21475
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ps-tryon-sr-glass-btn", onClick: handleDownload, children: t2("Download") })
|
|
21627
|
-
] })
|
|
21628
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RegenScanOverlay, { active: !!retryLoading && !!resultImageUrl && !tryOnProcessing })
|
|
21476
|
+
] })
|
|
21629
21477
|
] }),
|
|
21630
21478
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-panel", children: [
|
|
21631
21479
|
mismatchNotice,
|
|
21632
|
-
|
|
21633
|
-
|
|
21634
|
-
|
|
21635
|
-
|
|
21636
|
-
|
|
21637
|
-
|
|
21638
|
-
|
|
21639
|
-
|
|
21640
|
-
|
|
21641
|
-
|
|
21642
|
-
|
|
21643
|
-
|
|
21644
|
-
|
|
21645
|
-
|
|
21646
|
-
|
|
21647
|
-
|
|
21480
|
+
activeSection === sectionName ? (
|
|
21481
|
+
/* DETAIL VIEW — full size table, same as multi-garment */
|
|
21482
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21483
|
+
SectionDetailView,
|
|
21484
|
+
{
|
|
21485
|
+
sectionName,
|
|
21486
|
+
section: singleSection,
|
|
21487
|
+
sectionResult: singleResult,
|
|
21488
|
+
sectionFound: sizingResult?.found,
|
|
21489
|
+
userMeasurements: singleUserMeasurements,
|
|
21490
|
+
unitLbl,
|
|
21491
|
+
chartUnit: resultUnit,
|
|
21492
|
+
lengthEntry: null,
|
|
21493
|
+
onBack: () => setActiveSection(null),
|
|
21494
|
+
backLabel: t2("Back"),
|
|
21495
|
+
internationalSizes: sizingResult?.internationalSizes,
|
|
21496
|
+
onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
|
|
21497
|
+
continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
|
|
21498
|
+
tryOnProcessing,
|
|
21499
|
+
tryOnStartedAt,
|
|
21500
|
+
t: t2,
|
|
21501
|
+
renderRaw: isAccessory
|
|
21502
|
+
}
|
|
21503
|
+
)
|
|
21504
|
+
) : sizingResult?.found === false ? (
|
|
21505
|
+
/* NO-FIT EMPTY STATE — match% < 50% or backend reports
|
|
21506
|
+
no valid size. Skip the card + gallery + try-on
|
|
21507
|
+
entirely so the user gets immediate feedback that
|
|
21508
|
+
this product doesn't carry their size. */
|
|
21509
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-nofit", children: [
|
|
21510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-nofit-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "36", height: "36", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
21511
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
21512
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
|
|
21513
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
|
|
21514
|
+
] }) }),
|
|
21515
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-nofit-title", children: t2("No size matches your measurements") }),
|
|
21516
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-nofit-sub", children: t2("This product's size chart doesn't carry a fit close enough to your body. Try another product or update your profile.") }),
|
|
21517
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-nofit-actions", children: [
|
|
21518
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21519
|
+
"button",
|
|
21520
|
+
{
|
|
21521
|
+
className: "ps-bp-back-btn",
|
|
21522
|
+
onClick: () => {
|
|
21523
|
+
if (resultImageUrl) onResetTryOn?.();
|
|
21524
|
+
else setView("body-profile");
|
|
21525
|
+
},
|
|
21526
|
+
type: "button",
|
|
21527
|
+
children: [
|
|
21528
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
|
|
21529
|
+
" ",
|
|
21530
|
+
t2("Back")
|
|
21531
|
+
]
|
|
21532
|
+
}
|
|
21533
|
+
),
|
|
21534
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-v2-cta", style: { marginTop: 0 }, onClick: onClose, type: "button", children: [
|
|
21535
|
+
t2("Continue Shopping"),
|
|
21536
|
+
" →"
|
|
21537
|
+
] })
|
|
21538
|
+
] })
|
|
21539
|
+
] })
|
|
21540
|
+
) : (
|
|
21541
|
+
/* CARD VIEW — clickable summary card + gallery strip */
|
|
21542
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
21543
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-v2-title", children: t2("Your Perfect Fit") }),
|
|
21544
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-v2-subtitle", children: t2("Tap the card for detailed breakdown") }),
|
|
21545
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-sep" }),
|
|
21546
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-cards-v2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21547
|
+
"button",
|
|
21548
|
+
{
|
|
21549
|
+
className: `ps-tryon-sr-card-v2 ps-full${pendingCustomSizes[sectionName] ? " ps-overridden" : ""}`,
|
|
21550
|
+
onClick: () => setActiveSection(sectionName),
|
|
21551
|
+
type: "button",
|
|
21552
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-card-v2-text", children: [
|
|
21553
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-label", children: sectionName }),
|
|
21554
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-value", children: pendingCustomSizes[sectionName]?.displayLabel || singleResult.recommendedSize || "—" }),
|
|
21555
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
21556
|
+
"span",
|
|
21557
|
+
{
|
|
21558
|
+
className: `ps-tryon-sr-card-v2-rec-pill${pendingCustomSizes[sectionName] ? " is-overridden" : ""}`,
|
|
21559
|
+
children: pendingCustomSizes[sectionName] ? t2("YOUR SELECTION") : t2("RECOMMENDED")
|
|
21560
|
+
}
|
|
21561
|
+
),
|
|
21562
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-sr-card-v2-view", children: [
|
|
21563
|
+
t2("VIEW DETAILS"),
|
|
21564
|
+
" ",
|
|
21565
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "›" })
|
|
21566
|
+
] })
|
|
21567
|
+
] })
|
|
21648
21568
|
}
|
|
21649
|
-
},
|
|
21650
|
-
|
|
21651
|
-
|
|
21652
|
-
|
|
21653
|
-
|
|
21654
|
-
|
|
21655
|
-
|
|
21656
|
-
|
|
21657
|
-
|
|
21658
|
-
|
|
21659
|
-
|
|
21660
|
-
|
|
21661
|
-
|
|
21662
|
-
|
|
21663
|
-
|
|
21569
|
+
) }),
|
|
21570
|
+
productImages && productImages.length >= 2 && /* @__PURE__ */ jsxRuntimeExports.jsx(ProductPhotoCarouselCard, { photos: productImages, productTitle, t: t2 }),
|
|
21571
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: "0.5vw", gap: "0.5vw" }, children: [
|
|
21572
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21573
|
+
"button",
|
|
21574
|
+
{
|
|
21575
|
+
className: "ps-bp-back-btn",
|
|
21576
|
+
onClick: () => {
|
|
21577
|
+
if (resultImageUrl) onResetTryOn?.();
|
|
21578
|
+
else setView("body-profile");
|
|
21579
|
+
},
|
|
21580
|
+
type: "button",
|
|
21581
|
+
children: [
|
|
21582
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
|
|
21583
|
+
" ",
|
|
21584
|
+
t2("Back")
|
|
21585
|
+
]
|
|
21586
|
+
}
|
|
21587
|
+
),
|
|
21588
|
+
resultImageUrl && !tryOnProcessing ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-v2-cta", style: { marginTop: 0 }, onClick: onClose, children: [
|
|
21589
|
+
t2("Continue Shopping"),
|
|
21590
|
+
" →"
|
|
21591
|
+
] }) : vtoExcluded ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-v2-cta", style: { marginTop: 0 }, onClick: onClose, children: [
|
|
21592
|
+
t2("Continue Shopping"),
|
|
21593
|
+
" →"
|
|
21594
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
21595
|
+
"button",
|
|
21596
|
+
{
|
|
21597
|
+
className: "ps-tryon-v2-cta",
|
|
21598
|
+
style: { marginTop: 0 },
|
|
21599
|
+
disabled: tryOnProcessing,
|
|
21600
|
+
onClick: handleSingleTryOn,
|
|
21601
|
+
type: "button",
|
|
21602
|
+
children: [
|
|
21603
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(CameraIcon$1, { size: 14 }),
|
|
21604
|
+
" ",
|
|
21605
|
+
tryOnProcessing ? t2("Processing...") : t2("Try It On")
|
|
21606
|
+
]
|
|
21607
|
+
}
|
|
21608
|
+
)
|
|
21609
|
+
] })
|
|
21610
|
+
] })
|
|
21664
21611
|
)
|
|
21665
|
-
] },
|
|
21612
|
+
] }, `panel-single-${activeSection ? "detail" : "card"}`)
|
|
21666
21613
|
] });
|
|
21667
21614
|
})()
|
|
21668
21615
|
),
|
|
@@ -27703,6 +27650,19 @@ function detectMeasurementType(title) {
|
|
|
27703
27650
|
if (/\b(sunglass|sunglasses|eyewear|eyeglasses|glasses|spectacles|optical|goggles|frames|aviator|wayfarer|lens)\b/.test(t2)) return "face";
|
|
27704
27651
|
return "body";
|
|
27705
27652
|
}
|
|
27653
|
+
function computeMatchScore(recData) {
|
|
27654
|
+
if (!recData) return null;
|
|
27655
|
+
const all = [];
|
|
27656
|
+
for (const m2 of recData.matchDetails ?? []) all.push(m2);
|
|
27657
|
+
if (recData.sections) {
|
|
27658
|
+
for (const sec of Object.values(recData.sections)) {
|
|
27659
|
+
for (const m2 of sec?.matchDetails ?? []) all.push(m2);
|
|
27660
|
+
}
|
|
27661
|
+
}
|
|
27662
|
+
if (all.length === 0) return null;
|
|
27663
|
+
const good = all.filter((r2) => r2.fit === "good" || r2.fit === "a-bit-tight" || r2.fit === "a-bit-loose").length;
|
|
27664
|
+
return Math.round(good / all.length * 100);
|
|
27665
|
+
}
|
|
27706
27666
|
function measurementTypeToVtoCategory(type) {
|
|
27707
27667
|
if (type === "face") return "sunglasses";
|
|
27708
27668
|
if (type === "head") return "hat";
|
|
@@ -27711,6 +27671,7 @@ function measurementTypeToVtoCategory(type) {
|
|
|
27711
27671
|
}
|
|
27712
27672
|
function PrimeStyleTryonInner({
|
|
27713
27673
|
productImage,
|
|
27674
|
+
productImages,
|
|
27714
27675
|
productTitle = "Product",
|
|
27715
27676
|
productId,
|
|
27716
27677
|
productDescription,
|
|
@@ -27751,9 +27712,7 @@ function PrimeStyleTryonInner({
|
|
|
27751
27712
|
const [resultImageUrl, setResultImageUrl] = reactExports.useState(null);
|
|
27752
27713
|
const [errorMessage, setErrorMessage] = reactExports.useState(null);
|
|
27753
27714
|
const [dragOver, setDragOver] = reactExports.useState(false);
|
|
27754
|
-
const [retryLoading, setRetryLoading] = reactExports.useState(false);
|
|
27755
27715
|
const [tryOnStartedAt, setTryOnStartedAt] = reactExports.useState(null);
|
|
27756
|
-
const [retryStartedAt, setRetryStartedAt] = reactExports.useState(null);
|
|
27757
27716
|
const [activeSection, setActiveSection] = reactExports.useState(null);
|
|
27758
27717
|
const [pendingCustomSizes, setPendingCustomSizes] = reactExports.useState({});
|
|
27759
27718
|
const pendingCustomSizesRef = reactExports.useRef({});
|
|
@@ -27763,7 +27722,7 @@ function PrimeStyleTryonInner({
|
|
|
27763
27722
|
const sizingResultRef = reactExports.useRef(null);
|
|
27764
27723
|
const sizeGuideRef = reactExports.useRef(null);
|
|
27765
27724
|
const resultImageUrlRef = reactExports.useRef(null);
|
|
27766
|
-
|
|
27725
|
+
reactExports.useCallback((sectionName, override) => {
|
|
27767
27726
|
setPendingCustomSizes((prev) => {
|
|
27768
27727
|
const next = { ...prev };
|
|
27769
27728
|
if (override === null) delete next[sectionName];
|
|
@@ -27785,6 +27744,7 @@ function PrimeStyleTryonInner({
|
|
|
27785
27744
|
const [estimationDone, setEstimationDone] = reactExports.useState(false);
|
|
27786
27745
|
const [tryOnProcessing, setTryOnProcessing] = reactExports.useState(false);
|
|
27787
27746
|
const [sizeGuide, setSizeGuide] = reactExports.useState(null);
|
|
27747
|
+
const noFitFoundRef = reactExports.useRef(false);
|
|
27788
27748
|
reactExports.useEffect(() => {
|
|
27789
27749
|
sizingResultRef.current = sizingResult;
|
|
27790
27750
|
}, [sizingResult]);
|
|
@@ -27843,6 +27803,7 @@ function PrimeStyleTryonInner({
|
|
|
27843
27803
|
const [faceLandmarks, setFaceLandmarks] = reactExports.useState(null);
|
|
27844
27804
|
const selectedFileRef = reactExports.useRef(null);
|
|
27845
27805
|
const modelImageIdRef = reactExports.useRef(null);
|
|
27806
|
+
const autoTryOnFiredRef = reactExports.useRef(false);
|
|
27846
27807
|
reactExports.useEffect(() => {
|
|
27847
27808
|
try {
|
|
27848
27809
|
const key = getApiKey();
|
|
@@ -28250,6 +28211,15 @@ function PrimeStyleTryonInner({
|
|
|
28250
28211
|
unsubRef.current = null;
|
|
28251
28212
|
}, []);
|
|
28252
28213
|
const handleVtoUpdate = reactExports.useCallback((update) => {
|
|
28214
|
+
if (noFitFoundRef.current) {
|
|
28215
|
+
if (update.status === "completed" || update.status === "failed") {
|
|
28216
|
+
completedRef.current = true;
|
|
28217
|
+
cleanupJob();
|
|
28218
|
+
setTryOnProcessing(false);
|
|
28219
|
+
setTryOnStartedAt(null);
|
|
28220
|
+
}
|
|
28221
|
+
return;
|
|
28222
|
+
}
|
|
28253
28223
|
if (update.status === "completed" && update.imageUrl) {
|
|
28254
28224
|
setResultImageUrl((prev) => {
|
|
28255
28225
|
if (!prev || prev.startsWith("data:")) return update.imageUrl;
|
|
@@ -28432,11 +28402,15 @@ function PrimeStyleTryonInner({
|
|
|
28432
28402
|
}
|
|
28433
28403
|
setEstimationDone(false);
|
|
28434
28404
|
try {
|
|
28405
|
+
const tReq = Date.now();
|
|
28406
|
+
const payloadBytes = JSON.stringify(payload).length;
|
|
28407
|
+
console.log(`[ps-sdk:T] ▶ POST /sizing/recommend (quick) payload=${Math.round(payloadBytes / 1024)}KB bodyImage=${!!payload.bodyImage}`);
|
|
28435
28408
|
const res = await fetch(`${baseUrl}/api/v1/sizing/recommend`, {
|
|
28436
28409
|
method: "POST",
|
|
28437
28410
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
28438
28411
|
body: JSON.stringify(payload)
|
|
28439
28412
|
});
|
|
28413
|
+
console.log(`[ps-sdk:T] ◀ /sizing/recommend (quick) status=${res.status} roundTrip=${Date.now() - tReq}ms`);
|
|
28440
28414
|
if (res.ok) {
|
|
28441
28415
|
const data = await res.json();
|
|
28442
28416
|
console.log("[PS-SDK] Sizing recommend RESULT:", JSON.stringify(data));
|
|
@@ -28572,6 +28546,8 @@ function PrimeStyleTryonInner({
|
|
|
28572
28546
|
const objUrl = data.photoFile ? URL.createObjectURL(data.photoFile) : data.photoBase64.startsWith("data:") ? data.photoBase64 : `data:image/jpeg;base64,${data.photoBase64}`;
|
|
28573
28547
|
setPreviewUrl(objUrl);
|
|
28574
28548
|
completedRef.current = false;
|
|
28549
|
+
modelImageIdRef.current = null;
|
|
28550
|
+
noFitFoundRef.current = false;
|
|
28575
28551
|
setTryOnProcessing(false);
|
|
28576
28552
|
setTryOnStartedAt(null);
|
|
28577
28553
|
setSizingResult(null);
|
|
@@ -28582,12 +28558,12 @@ function PrimeStyleTryonInner({
|
|
|
28582
28558
|
const measurementType = detectMeasurementType(productTitle);
|
|
28583
28559
|
if (measurementType === "face" || measurementType === "head") {
|
|
28584
28560
|
setFaceLandmarks(null);
|
|
28585
|
-
const
|
|
28561
|
+
const minVisible2 = new Promise((r2) => setTimeout(r2, 4500));
|
|
28586
28562
|
try {
|
|
28587
28563
|
const faceResult = await detectFaceMeasurements(objUrl);
|
|
28588
28564
|
if (!faceResult) {
|
|
28589
28565
|
console.warn("[ps-sdk] face detection returned no result — likely a full-body photo for a face/head product");
|
|
28590
|
-
await
|
|
28566
|
+
await minVisible2;
|
|
28591
28567
|
const msg = measurementType === "head" ? t2("We couldn't detect your head clearly. Please upload a close-up photo that shows your full head and ears.") : t2("We couldn't detect your face clearly. Please upload a close-up selfie that shows both eyes.");
|
|
28592
28568
|
setErrorMessage(msg);
|
|
28593
28569
|
setView("error");
|
|
@@ -28615,7 +28591,7 @@ function PrimeStyleTryonInner({
|
|
|
28615
28591
|
});
|
|
28616
28592
|
if (recRes.ok) {
|
|
28617
28593
|
const recData = await recRes.json();
|
|
28618
|
-
await
|
|
28594
|
+
await minVisible2;
|
|
28619
28595
|
setSizingResult(recData);
|
|
28620
28596
|
onComplete?.(recData);
|
|
28621
28597
|
persistResultToProfile(
|
|
@@ -28632,12 +28608,12 @@ function PrimeStyleTryonInner({
|
|
|
28632
28608
|
{ skipBodyEstimate: true }
|
|
28633
28609
|
);
|
|
28634
28610
|
} else {
|
|
28635
|
-
await
|
|
28611
|
+
await minVisible2;
|
|
28636
28612
|
setEstimationDone(true);
|
|
28637
28613
|
}
|
|
28638
28614
|
} catch (err) {
|
|
28639
28615
|
console.error("[ps-sdk] face-recommend failed:", err);
|
|
28640
|
-
await
|
|
28616
|
+
await minVisible2;
|
|
28641
28617
|
setEstimationDone(true);
|
|
28642
28618
|
}
|
|
28643
28619
|
setSizingLoading(false);
|
|
@@ -28707,12 +28683,17 @@ function PrimeStyleTryonInner({
|
|
|
28707
28683
|
const jointCount = lmObj ? Object.keys(lmObj).filter((k2) => k2 !== "imageWidth" && k2 !== "imageHeight" && lmObj[k2]).length : 0;
|
|
28708
28684
|
console.log(`[ps-sdk:debug] payload → bodyLandmarks=${!!lmObj}(${jointCount} joints)`);
|
|
28709
28685
|
}
|
|
28686
|
+
const minVisible = new Promise((r2) => setTimeout(r2, 6e3));
|
|
28710
28687
|
try {
|
|
28688
|
+
const tReq = Date.now();
|
|
28689
|
+
const payloadBytes = JSON.stringify(payload).length;
|
|
28690
|
+
console.log(`[ps-sdk:T] ▶ POST /sizing/recommend payload=${Math.round(payloadBytes / 1024)}KB bodyImage=${!!payload.bodyImage} landmarks=${!!payload.bodyLandmarks}`);
|
|
28711
28691
|
const recRes = await fetch(`${baseUrl}/api/v1/sizing/recommend`, {
|
|
28712
28692
|
method: "POST",
|
|
28713
28693
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
28714
28694
|
body: JSON.stringify(payload)
|
|
28715
28695
|
});
|
|
28696
|
+
console.log(`[ps-sdk:T] ◀ /sizing/recommend status=${recRes.status} roundTrip=${Date.now() - tReq}ms`);
|
|
28716
28697
|
if (recRes.ok) {
|
|
28717
28698
|
const recData = await recRes.json();
|
|
28718
28699
|
if (recData?.found === false && recData?.reasoning === "NO_SIZE_CHART") {
|
|
@@ -28721,26 +28702,38 @@ function PrimeStyleTryonInner({
|
|
|
28721
28702
|
setSizingLoading(false);
|
|
28722
28703
|
return;
|
|
28723
28704
|
}
|
|
28724
|
-
|
|
28725
|
-
|
|
28726
|
-
|
|
28727
|
-
{
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
|
|
28734
|
-
|
|
28735
|
-
|
|
28736
|
-
|
|
28737
|
-
|
|
28705
|
+
const matchScore = computeMatchScore(recData);
|
|
28706
|
+
const isLowFit = recData?.found === false || matchScore != null && matchScore < 50;
|
|
28707
|
+
if (isLowFit) {
|
|
28708
|
+
console.log(`[ps-sdk:gate] LOW FIT (match=${matchScore ?? "?"}%, found=${recData?.found}) — suppressing try-on`);
|
|
28709
|
+
noFitFoundRef.current = true;
|
|
28710
|
+
setTryOnProcessing(false);
|
|
28711
|
+
setTryOnStartedAt(null);
|
|
28712
|
+
setSizingResult({ ...recData, found: false });
|
|
28713
|
+
onComplete?.({ ...recData, found: false });
|
|
28714
|
+
} else {
|
|
28715
|
+
setSizingResult(recData);
|
|
28716
|
+
onComplete?.(recData);
|
|
28717
|
+
persistResultToProfile(
|
|
28718
|
+
{
|
|
28719
|
+
gender: data.gender,
|
|
28720
|
+
height: data.height,
|
|
28721
|
+
weight: data.weight,
|
|
28722
|
+
heightUnit: data.heightUnit,
|
|
28723
|
+
weightUnit: data.weightUnit,
|
|
28724
|
+
age: data.age,
|
|
28725
|
+
bodyImage: data.photoBase64
|
|
28726
|
+
},
|
|
28727
|
+
recData
|
|
28728
|
+
);
|
|
28729
|
+
}
|
|
28738
28730
|
} else {
|
|
28739
28731
|
setEstimationDone(true);
|
|
28740
28732
|
}
|
|
28741
28733
|
} catch {
|
|
28742
28734
|
setEstimationDone(true);
|
|
28743
28735
|
}
|
|
28736
|
+
await minVisible;
|
|
28744
28737
|
setSizingLoading(false);
|
|
28745
28738
|
}, [apiUrl, productImage, productTitle, sizingUnit, weightUnit, sizingCountry, sizeGuide, dynamicFields, persistResultToProfile]);
|
|
28746
28739
|
snapSubmitRef.current = handleSnapSubmit;
|
|
@@ -28764,9 +28757,9 @@ function PrimeStyleTryonInner({
|
|
|
28764
28757
|
const isApparel = vtoCategory === "apparel";
|
|
28765
28758
|
const previewObjUrl = (overrideFile ? null : previewUrl) || URL.createObjectURL(file);
|
|
28766
28759
|
if (overrideFile || !previewUrl) setPreviewUrl(previewObjUrl);
|
|
28767
|
-
modelPoseRef.current
|
|
28768
|
-
|
|
28769
|
-
|
|
28760
|
+
if (isApparel && (!modelPoseRef.current || !bodyLandmarks)) {
|
|
28761
|
+
modelPoseRef.current = null;
|
|
28762
|
+
setBodyLandmarks(null);
|
|
28770
28763
|
detectMeasurementLines(previewObjUrl).then((lines) => {
|
|
28771
28764
|
modelPoseRef.current = lines;
|
|
28772
28765
|
}).catch(() => {
|
|
@@ -28817,20 +28810,20 @@ function PrimeStyleTryonInner({
|
|
|
28817
28810
|
console.log("[ps-sdk:flatten] sizingResult keys:", Object.keys(sizingResult || {}));
|
|
28818
28811
|
console.log("[ps-sdk:flatten] root matchDetails:", (sizingResult?.matchDetails || []).map((m2) => m2.measurement));
|
|
28819
28812
|
console.log("[ps-sdk:flatten] sections:", sizingResult?.sections ? Object.keys(sizingResult.sections) : "none");
|
|
28820
|
-
const push = (md2, src) => {
|
|
28813
|
+
const push = (md2, src, section) => {
|
|
28821
28814
|
if (!md2) return;
|
|
28822
28815
|
console.log(`[ps-sdk:flatten] ${src} →`, md2.map((m2) => m2.measurement));
|
|
28823
28816
|
for (const m2 of md2) {
|
|
28824
28817
|
const k2 = m2.measurement.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim();
|
|
28825
28818
|
if (seen.has(k2)) continue;
|
|
28826
28819
|
seen.add(k2);
|
|
28827
|
-
out.push(m2);
|
|
28820
|
+
out.push({ ...m2, section });
|
|
28828
28821
|
}
|
|
28829
28822
|
};
|
|
28830
|
-
push(sizingResult?.matchDetails, "root");
|
|
28823
|
+
push(sizingResult?.matchDetails, "root", void 0);
|
|
28831
28824
|
if (sizingResult?.sections) {
|
|
28832
28825
|
for (const [secName, sec] of Object.entries(sizingResult.sections)) {
|
|
28833
|
-
push(sec?.matchDetails, `section:${secName}
|
|
28826
|
+
push(sec?.matchDetails, `section:${secName}`, secName);
|
|
28834
28827
|
}
|
|
28835
28828
|
}
|
|
28836
28829
|
console.log("[ps-sdk:flatten] final unique:", out.map((m2) => m2.measurement));
|
|
@@ -28839,7 +28832,9 @@ function PrimeStyleTryonInner({
|
|
|
28839
28832
|
const effectiveMatchDetails = override?.matchDetails && override.matchDetails.length ? override.matchDetails : flattenAllMatchDetails();
|
|
28840
28833
|
let fitInfo;
|
|
28841
28834
|
if (isApparel && effectiveMatchDetails.length) {
|
|
28842
|
-
|
|
28835
|
+
const unitRaw = (sizingResult?.unit || sizingUnit || "in").toString().toLowerCase();
|
|
28836
|
+
const unit = unitRaw === "cm" ? "cm" : unitRaw === "mm" ? "mm" : "in";
|
|
28837
|
+
fitInfo = buildFitInfo(effectiveMatchDetails, modelPoseRef.current, unit);
|
|
28843
28838
|
}
|
|
28844
28839
|
console.log("[ps-sdk:tryon] fitInfo built", { count: fitInfo?.length || 0, areas: fitInfo?.map((f2) => `${f2.area}(${f2.fit})`) });
|
|
28845
28840
|
const response = await apiRef.current.submitTryOn(
|
|
@@ -28888,167 +28883,19 @@ function PrimeStyleTryonInner({
|
|
|
28888
28883
|
onError?.({ message, code });
|
|
28889
28884
|
}
|
|
28890
28885
|
}, [selectedFile, productImage, productTitle, sizingResult, onProcessing, onError, handleVtoUpdate]);
|
|
28891
|
-
|
|
28892
|
-
|
|
28893
|
-
|
|
28894
|
-
console.warn("[ps-sdk:retry] skipping — no file/api/sse", {
|
|
28895
|
-
hasFile: !!file,
|
|
28896
|
-
hasApi: !!apiRef.current,
|
|
28897
|
-
hasSse: !!sseRef.current
|
|
28898
|
-
});
|
|
28899
|
-
return;
|
|
28900
|
-
}
|
|
28901
|
-
console.log("[ps-sdk:retry] starting", { fitInfoCount: fitInfo.length, selectedSizeOverride, fitInfo });
|
|
28902
|
-
setRetryLoading(true);
|
|
28903
|
-
setRetryStartedAt(Date.now());
|
|
28904
|
-
const vtoCategory = measurementTypeToVtoCategory(detectMeasurementType(productTitle));
|
|
28905
|
-
const isApparel = vtoCategory === "apparel";
|
|
28906
|
-
if (isApparel && modelPoseRef.current) {
|
|
28907
|
-
const AREA_MAP = {
|
|
28908
|
-
chest: "chest",
|
|
28909
|
-
bust: "chest",
|
|
28910
|
-
waist: "waist",
|
|
28911
|
-
hips: "hips",
|
|
28912
|
-
hip: "hips"
|
|
28913
|
-
};
|
|
28914
|
-
for (const area of fitInfo) {
|
|
28915
|
-
const key = AREA_MAP[area.area.toLowerCase()];
|
|
28916
|
-
if (key && modelPoseRef.current[key]) {
|
|
28917
|
-
const line = modelPoseRef.current[key];
|
|
28918
|
-
area.y = Math.round(line.y * 1e3) / 1e3;
|
|
28919
|
-
area.x1 = Math.round(line.x1 * 1e3) / 1e3;
|
|
28920
|
-
area.x2 = Math.round(line.x2 * 1e3) / 1e3;
|
|
28921
|
-
}
|
|
28922
|
-
}
|
|
28923
|
-
}
|
|
28924
|
-
try {
|
|
28925
|
-
completedRef.current = false;
|
|
28926
|
-
unsubRef.current?.();
|
|
28927
|
-
if (pollingRef.current) {
|
|
28928
|
-
clearInterval(pollingRef.current);
|
|
28929
|
-
pollingRef.current = null;
|
|
28930
|
-
}
|
|
28931
|
-
const useExistingResult = false;
|
|
28932
|
-
const modelImage = await compressImage(file, { maxDimension: 1024, quality: 0.85 });
|
|
28933
|
-
console.log("[ps-sdk:retry] modelImage source", {
|
|
28934
|
-
useExistingResult,
|
|
28935
|
-
bytes: modelImage.length,
|
|
28936
|
-
isPng: modelImage.startsWith("data:image/png")
|
|
28937
|
-
});
|
|
28938
|
-
const outboundFitInfo = isApparel ? fitInfo : void 0;
|
|
28939
|
-
const response = await apiRef.current.submitTryOn(
|
|
28940
|
-
modelImage,
|
|
28941
|
-
productImage,
|
|
28942
|
-
outboundFitInfo,
|
|
28943
|
-
vtoCategory ?? "apparel",
|
|
28944
|
-
{
|
|
28945
|
-
editFromPrevious: useExistingResult,
|
|
28946
|
-
productId: effectiveProductId,
|
|
28947
|
-
productTitle,
|
|
28948
|
-
productDescription,
|
|
28949
|
-
productMaterial,
|
|
28950
|
-
silhouetteContext: buildSilhouetteContext(sizingResultRef.current, sizeGuideRef.current, selectedSizeOverride),
|
|
28951
|
-
modelImageId: modelImageIdRef.current ?? void 0
|
|
28952
|
-
}
|
|
28953
|
-
);
|
|
28954
|
-
if (response.modelImageId) modelImageIdRef.current = response.modelImageId;
|
|
28955
|
-
unsubRef.current = sseRef.current.onJob(response.jobId, (update) => {
|
|
28956
|
-
if (update.status === "completed" && update.imageUrl) {
|
|
28957
|
-
setResultImageUrl(update.imageUrl);
|
|
28958
|
-
setRetryLoading(false);
|
|
28959
|
-
setRetryStartedAt(null);
|
|
28960
|
-
completedRef.current = true;
|
|
28961
|
-
unsubRef.current?.();
|
|
28962
|
-
unsubRef.current = null;
|
|
28963
|
-
if (pollingRef.current) {
|
|
28964
|
-
clearInterval(pollingRef.current);
|
|
28965
|
-
pollingRef.current = null;
|
|
28966
|
-
}
|
|
28967
|
-
} else if (update.status === "failed") {
|
|
28968
|
-
setRetryLoading(false);
|
|
28969
|
-
setRetryStartedAt(null);
|
|
28970
|
-
completedRef.current = true;
|
|
28971
|
-
unsubRef.current?.();
|
|
28972
|
-
unsubRef.current = null;
|
|
28973
|
-
if (pollingRef.current) {
|
|
28974
|
-
clearInterval(pollingRef.current);
|
|
28975
|
-
pollingRef.current = null;
|
|
28976
|
-
}
|
|
28977
|
-
}
|
|
28978
|
-
});
|
|
28979
|
-
let attempts = 0;
|
|
28980
|
-
pollingRef.current = setInterval(async () => {
|
|
28981
|
-
if (completedRef.current) {
|
|
28982
|
-
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
28983
|
-
pollingRef.current = null;
|
|
28984
|
-
return;
|
|
28985
|
-
}
|
|
28986
|
-
attempts++;
|
|
28987
|
-
if (attempts > 60) {
|
|
28988
|
-
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
28989
|
-
pollingRef.current = null;
|
|
28990
|
-
setRetryLoading(false);
|
|
28991
|
-
setRetryStartedAt(null);
|
|
28992
|
-
return;
|
|
28993
|
-
}
|
|
28994
|
-
try {
|
|
28995
|
-
const status = await apiRef.current.getStatus(response.jobId);
|
|
28996
|
-
if (status.status === "completed" && status.imageUrl) {
|
|
28997
|
-
if (!completedRef.current) {
|
|
28998
|
-
completedRef.current = true;
|
|
28999
|
-
setResultImageUrl(status.imageUrl);
|
|
29000
|
-
setRetryLoading(false);
|
|
29001
|
-
setRetryStartedAt(null);
|
|
29002
|
-
unsubRef.current?.();
|
|
29003
|
-
unsubRef.current = null;
|
|
29004
|
-
}
|
|
29005
|
-
if (pollingRef.current) {
|
|
29006
|
-
clearInterval(pollingRef.current);
|
|
29007
|
-
pollingRef.current = null;
|
|
29008
|
-
}
|
|
29009
|
-
} else if (status.status === "failed") {
|
|
29010
|
-
completedRef.current = true;
|
|
29011
|
-
setRetryLoading(false);
|
|
29012
|
-
setRetryStartedAt(null);
|
|
29013
|
-
if (pollingRef.current) {
|
|
29014
|
-
clearInterval(pollingRef.current);
|
|
29015
|
-
pollingRef.current = null;
|
|
29016
|
-
}
|
|
29017
|
-
}
|
|
29018
|
-
} catch {
|
|
29019
|
-
}
|
|
29020
|
-
}, 3e3);
|
|
29021
|
-
} catch {
|
|
29022
|
-
setRetryLoading(false);
|
|
29023
|
-
setRetryStartedAt(null);
|
|
29024
|
-
}
|
|
29025
|
-
}, [selectedFile, productImage, productTitle]);
|
|
29026
|
-
const handleRegenerateTryOn = reactExports.useCallback((override) => {
|
|
29027
|
-
console.log("[ps-sdk:regen] fired", { sectionName: override.sectionName, override, hasFile: !!selectedFile, hasRefFile: !!selectedFileRef.current });
|
|
29028
|
-
setPendingCustomSizeBySection(override.sectionName, override);
|
|
29029
|
-
const map = { ...pendingCustomSizesRef.current, [override.sectionName]: override };
|
|
29030
|
-
const seen = /* @__PURE__ */ new Set();
|
|
29031
|
-
const merged = [];
|
|
29032
|
-
for (const key of Object.keys(map)) {
|
|
29033
|
-
for (const m2 of map[key].matchDetails || []) {
|
|
29034
|
-
const k2 = m2.measurement.toLowerCase().trim();
|
|
29035
|
-
if (seen.has(k2)) continue;
|
|
29036
|
-
seen.add(k2);
|
|
29037
|
-
merged.push(m2);
|
|
29038
|
-
}
|
|
29039
|
-
}
|
|
29040
|
-
if (!merged.length) {
|
|
29041
|
-
console.warn("[ps-sdk:regen] no matchDetails across any section — cannot rebuild fitInfo");
|
|
28886
|
+
reactExports.useEffect(() => {
|
|
28887
|
+
if (!sizingResult) {
|
|
28888
|
+
autoTryOnFiredRef.current = false;
|
|
29042
28889
|
return;
|
|
29043
28890
|
}
|
|
29044
|
-
|
|
29045
|
-
|
|
29046
|
-
|
|
29047
|
-
|
|
29048
|
-
|
|
29049
|
-
|
|
29050
|
-
|
|
29051
|
-
}, [
|
|
28891
|
+
if (sizingResult.found === false) return;
|
|
28892
|
+
if (noFitFoundRef.current) return;
|
|
28893
|
+
if (autoTryOnFiredRef.current) return;
|
|
28894
|
+
if (tryOnProcessing || resultImageUrl) return;
|
|
28895
|
+
if (!selectedFile && !selectedFileRef.current) return;
|
|
28896
|
+
autoTryOnFiredRef.current = true;
|
|
28897
|
+
handleTryOnSubmit();
|
|
28898
|
+
}, [sizingResult, tryOnProcessing, resultImageUrl, selectedFile, handleTryOnSubmit]);
|
|
29052
28899
|
const handleDownload = reactExports.useCallback(() => {
|
|
29053
28900
|
if (!resultImageUrl) return;
|
|
29054
28901
|
if (resultImageUrl.startsWith("data:")) {
|
|
@@ -29490,15 +29337,13 @@ function PrimeStyleTryonInner({
|
|
|
29490
29337
|
sizeGuide,
|
|
29491
29338
|
resultImageUrl,
|
|
29492
29339
|
productImage,
|
|
29340
|
+
productImages,
|
|
29493
29341
|
productTitle,
|
|
29494
29342
|
productMaterial,
|
|
29495
29343
|
productDescription,
|
|
29496
29344
|
sizingUnit,
|
|
29497
29345
|
setView,
|
|
29498
29346
|
handleDownload,
|
|
29499
|
-
onRetryWithFit: handleRetryWithFit,
|
|
29500
|
-
retryLoading,
|
|
29501
|
-
retryStartedAt,
|
|
29502
29347
|
selectedFile,
|
|
29503
29348
|
previewUrl,
|
|
29504
29349
|
handleFileSelect,
|
|
@@ -29511,9 +29356,6 @@ function PrimeStyleTryonInner({
|
|
|
29511
29356
|
measurementType: detectMeasurementType(productTitle),
|
|
29512
29357
|
activeSection,
|
|
29513
29358
|
setActiveSection,
|
|
29514
|
-
pendingCustomSizes,
|
|
29515
|
-
onPendingCustomSizeChange: setPendingCustomSizeBySection,
|
|
29516
|
-
onRegenerateTryOn: handleRegenerateTryOn,
|
|
29517
29359
|
onResetTryOn: () => {
|
|
29518
29360
|
setSelectedFile(null);
|
|
29519
29361
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|