@primestyleai/tryon 5.9.0 → 5.10.0

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.
@@ -10080,7 +10080,8 @@ async function recommendForProduct(input) {
10080
10080
  sections: sectionsMap,
10081
10081
  profileId: profile.id,
10082
10082
  fromCache: false,
10083
- raw: result
10083
+ raw: result,
10084
+ found: result.found
10084
10085
  };
10085
10086
  }
10086
10087
  async function estimateFullMeasurements(args) {
@@ -10139,6 +10140,12 @@ async function estimateFullMeasurements(args) {
10139
10140
  function isImperial(locale) {
10140
10141
  return ["US", "UK", "AU"].includes(locale);
10141
10142
  }
10143
+ function getUnitLabel(unit) {
10144
+ if (unit === "in" || unit === "inches" || unit === "lbs") return "Imperial";
10145
+ if (unit === "cm" || unit === "kg") return "Metric";
10146
+ if (unit === "mm") return "mm";
10147
+ return "";
10148
+ }
10142
10149
  function cx(base, override) {
10143
10150
  return override ? `${base} ${override}` : base;
10144
10151
  }
@@ -10913,12 +10920,22 @@ const STYLES$1 = `
10913
10920
  }
10914
10921
  .ps-tryon-v2-processing-label {
10915
10922
  position: absolute; bottom: 1vw; left: 50%; transform: translateX(-50%);
10916
- z-index: 5; font-size: 0.65vw; font-weight: 500;
10917
- color: var(--ps-accent); letter-spacing: 0.06em;
10918
- background: rgba(0,0,0,0.6); backdrop-filter: blur(8px);
10919
- padding: 0.25vw 0.8vw; border-radius: 2vw;
10923
+ z-index: 5; font-size: 0.7vw; font-weight: 600;
10924
+ color: #fff; letter-spacing: 0.05em;
10925
+ background: rgba(0,0,0,0.72); backdrop-filter: blur(10px);
10926
+ padding: 0.6vw 0.9vw; border-radius: 0.6vw;
10927
+ display: flex; flex-direction: column; align-items: center; gap: 0.5vw;
10928
+ min-width: 14vw;
10929
+ box-shadow: 0 0.4vw 1.5vw rgba(0,0,0,0.35);
10930
+ }
10931
+ .ps-tryon-v2-processing-label > span:first-child {
10920
10932
  animation: ps-loading-pulse 2s ease-in-out infinite;
10921
10933
  }
10934
+ .ps-tryon-v2-processing-label .ps-tryon-progress-ring-track { stroke: rgba(255,255,255,0.18); }
10935
+ .ps-tryon-v2-processing-label .ps-tryon-progress-ring-fill { stroke: var(--ps-accent-light); }
10936
+ .ps-tryon-v2-processing-label .ps-tryon-progress-eta { color: #fff; }
10937
+ .ps-tryon-v2-processing-label .ps-tryon-progress-bar-wrap { background: rgba(255,255,255,0.18); }
10938
+ .ps-tryon-v2-processing-label .ps-tryon-progress-pct { color: var(--ps-accent-light); }
10922
10939
 
10923
10940
  /* "I don't know" link */
10924
10941
  .ps-tryon-v2-dontknow {
@@ -11511,6 +11528,26 @@ const STYLES$1 = `
11511
11528
  .ps-tryon-progress-section {
11512
11529
  display: flex; align-items: center; gap: 0.63vw; width: 100%; max-width: 18vw; margin-bottom: 0.83vw;
11513
11530
  }
11531
+ /* Shared progress layout used inside StageCycler (desktop) and
11532
+ MobileScanningView — row of ring + bar + percent, same tokens. */
11533
+ .ps-tryon-progress-wrap {
11534
+ display: flex; align-items: center; gap: 12px;
11535
+ width: 100%; max-width: 360px; margin-top: 18px;
11536
+ }
11537
+ .ps-tryon-progress-wrap .ps-tryon-progress-bar-wrap {
11538
+ flex: 1; height: 6px; border-radius: 4px; overflow: hidden;
11539
+ position: relative; background: var(--ps-border-color);
11540
+ }
11541
+ .ps-tryon-progress-wrap .ps-tryon-progress-bar-fill {
11542
+ height: 100%; width: 0%;
11543
+ background: linear-gradient(90deg, var(--ps-accent), var(--ps-accent-light));
11544
+ border-radius: 4px; transition: width 0.3s ease;
11545
+ }
11546
+ .ps-tryon-progress-wrap .ps-tryon-progress-pct {
11547
+ font-size: 13px; font-weight: 700; color: var(--ps-accent);
11548
+ min-width: 36px; text-align: right;
11549
+ font-variant-numeric: tabular-nums;
11550
+ }
11514
11551
  .ps-tryon-progress-bar-wrap {
11515
11552
  flex: 1; height: 0.31vw; background: var(--ps-border-color); border-radius: 3px; overflow: hidden;
11516
11553
  position: relative;
@@ -11536,25 +11573,25 @@ const STYLES$1 = `
11536
11573
  font-variant-numeric: tabular-nums;
11537
11574
  }
11538
11575
 
11539
- /* Circular ETA ring — 48×48 px SVG with a track + progress circle; ETA
11576
+ /* Circular ETA ring — 64×64 px SVG with a track + progress circle; ETA
11540
11577
  text centered. strokeDashoffset is driven by the ticker in
11541
11578
  PrimeStyleTryonInner, so CSS only styles the appearance. */
11542
11579
  .ps-tryon-progress-ring {
11543
- position: relative; width: 48px; height: 48px; flex: 0 0 48px;
11580
+ position: relative; width: 64px; height: 64px; flex: 0 0 64px;
11544
11581
  display: flex; align-items: center; justify-content: center;
11545
11582
  }
11546
11583
  .ps-tryon-progress-ring svg { transform: rotate(-90deg); }
11547
11584
  .ps-tryon-progress-ring-track {
11548
- fill: none; stroke: var(--ps-border-color); stroke-width: 3.5;
11585
+ fill: none; stroke: var(--ps-border-color); stroke-width: 5;
11549
11586
  }
11550
11587
  .ps-tryon-progress-ring-fill {
11551
- fill: none; stroke: var(--ps-accent); stroke-width: 3.5;
11588
+ fill: none; stroke: var(--ps-accent); stroke-width: 5;
11552
11589
  stroke-linecap: round;
11553
11590
  transition: stroke-dashoffset 0.3s ease;
11554
11591
  }
11555
11592
  .ps-tryon-progress-eta {
11556
11593
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
11557
- font-size: 10px; font-weight: 700; color: var(--ps-accent);
11594
+ font-size: 13px; font-weight: 700; color: var(--ps-accent);
11558
11595
  font-variant-numeric: tabular-nums; letter-spacing: 0.01em;
11559
11596
  pointer-events: none;
11560
11597
  }
@@ -16641,6 +16678,92 @@ function ProfileDetailModal({
16641
16678
  document.body
16642
16679
  );
16643
16680
  }
16681
+ function ConfirmMeasurementsModal({
16682
+ profile,
16683
+ onProceed,
16684
+ onEdit,
16685
+ t: t2
16686
+ }) {
16687
+ const heightUnit = profile.heightUnit === "in" || profile.heightUnit === "ft" ? "in" : "cm";
16688
+ const weightUnit = profile.weightUnit === "lbs" ? "lbs" : "kg";
16689
+ const systemLabel = getUnitLabel(heightUnit);
16690
+ const formatHeight = (h) => {
16691
+ if (!h) return "—";
16692
+ if (heightUnit === "in") {
16693
+ const ft = Math.floor(h / 12);
16694
+ const inches = Math.round(h % 12);
16695
+ return `${ft}'${inches}"`;
16696
+ }
16697
+ return `${Math.round(h)} cm`;
16698
+ };
16699
+ const formatWeight = (w2) => {
16700
+ if (!w2) return "—";
16701
+ return `${Math.round(w2)} ${weightUnit}`;
16702
+ };
16703
+ const height = profile.height ?? profile.heightCm;
16704
+ const weight = profile.weight ?? profile.weightKg;
16705
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-confirm-overlay", onClick: onEdit, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-confirm-modal", onClick: (e) => e.stopPropagation(), children: [
16706
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
16707
+ "button",
16708
+ {
16709
+ type: "button",
16710
+ "aria-label": t2("Close"),
16711
+ onClick: onEdit,
16712
+ style: {
16713
+ position: "absolute",
16714
+ top: "0.75vw",
16715
+ right: "0.75vw",
16716
+ width: "1.8vw",
16717
+ height: "1.8vw",
16718
+ borderRadius: "50%",
16719
+ background: "transparent",
16720
+ border: "none",
16721
+ cursor: "pointer",
16722
+ display: "flex",
16723
+ alignItems: "center",
16724
+ justifyContent: "center",
16725
+ color: "var(--ps-text-muted)"
16726
+ },
16727
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "16", height: "16", children: [
16728
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
16729
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
16730
+ ] })
16731
+ }
16732
+ ),
16733
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: { fontWeight: 700, marginBottom: "0.4vw" }, children: t2("Confirm your measurements") }),
16734
+ /* @__PURE__ */ jsxRuntimeExports.jsx("small", { style: { color: "var(--ps-text-muted)" }, children: systemLabel ? t2("You chose") + " " + systemLabel + ". " + t2("Review before continuing.") : t2("Review before continuing.") }),
16735
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { style: {
16736
+ listStyle: "none",
16737
+ padding: 0,
16738
+ margin: "0.8vw 0 0.2vw 0",
16739
+ width: "100%",
16740
+ textAlign: "left",
16741
+ fontSize: "0.78vw",
16742
+ lineHeight: 1.6
16743
+ }, children: [
16744
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { style: { display: "flex", justifyContent: "space-between", gap: "1vw" }, children: [
16745
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--ps-text-muted)" }, children: t2("Height") }),
16746
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: 600 }, children: formatHeight(height) })
16747
+ ] }),
16748
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { style: { display: "flex", justifyContent: "space-between", gap: "1vw" }, children: [
16749
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--ps-text-muted)" }, children: t2("Weight") }),
16750
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: 600 }, children: formatWeight(weight) })
16751
+ ] }),
16752
+ profile.age ? /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { style: { display: "flex", justifyContent: "space-between", gap: "1vw" }, children: [
16753
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--ps-text-muted)" }, children: t2("Age") }),
16754
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: 600 }, children: profile.age })
16755
+ ] }) : null,
16756
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { style: { display: "flex", justifyContent: "space-between", gap: "1vw" }, children: [
16757
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--ps-text-muted)" }, children: t2("Gender") }),
16758
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontWeight: 600 }, children: profile.gender === "female" ? t2("Female") : t2("Male") })
16759
+ ] })
16760
+ ] }),
16761
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-confirm-actions", children: [
16762
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-confirm-cancel", onClick: onEdit, children: t2("Edit") }),
16763
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-confirm-delete", onClick: onProceed, children: t2("Proceed") })
16764
+ ] })
16765
+ ] }) });
16766
+ }
16644
16767
  function WelcomeView({
16645
16768
  productImage,
16646
16769
  setView,
@@ -16876,17 +16999,71 @@ function MobileSkeleton({ landmarks, w: w2, h }) {
16876
16999
  }
16877
17000
  );
16878
17001
  }
17002
+ const MSC_TRYON_TARGET_SECONDS = 22;
17003
+ const MSC_RING_RADIUS = 27;
17004
+ const MSC_RING_CIRC = 2 * Math.PI * MSC_RING_RADIUS;
17005
+ function MscTryOnProgress({ t: t2 }) {
17006
+ const startRef = reactExports.useRef(Date.now());
17007
+ const ringRef = reactExports.useRef(null);
17008
+ const barRef = reactExports.useRef(null);
17009
+ const etaRef = reactExports.useRef(null);
17010
+ const pctRef = reactExports.useRef(null);
17011
+ reactExports.useEffect(() => {
17012
+ startRef.current = Date.now();
17013
+ const id2 = setInterval(() => {
17014
+ const elapsed = (Date.now() - startRef.current) / 1e3;
17015
+ const pct = Math.min(95, elapsed / MSC_TRYON_TARGET_SECONDS * 100);
17016
+ const val = Math.round(pct);
17017
+ if (barRef.current) barRef.current.style.width = `${val}%`;
17018
+ if (pctRef.current) pctRef.current.textContent = `${val}%`;
17019
+ if (ringRef.current) ringRef.current.style.strokeDashoffset = String(MSC_RING_CIRC * (1 - pct / 100));
17020
+ if (etaRef.current) {
17021
+ const remaining = Math.max(0, MSC_TRYON_TARGET_SECONDS - Math.floor(elapsed));
17022
+ etaRef.current.textContent = elapsed >= MSC_TRYON_TARGET_SECONDS ? t2("Finalizing...") : `~${remaining}s`;
17023
+ }
17024
+ }, 200);
17025
+ return () => clearInterval(id2);
17026
+ }, []);
17027
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-wrap", children: [
17028
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-ring", children: [
17029
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "64", height: "64", viewBox: "0 0 64 64", "aria-hidden": "true", children: [
17030
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "32", cy: "32", r: MSC_RING_RADIUS, className: "ps-tryon-progress-ring-track" }),
17031
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
17032
+ "circle",
17033
+ {
17034
+ ref: ringRef,
17035
+ cx: "32",
17036
+ cy: "32",
17037
+ r: MSC_RING_RADIUS,
17038
+ className: "ps-tryon-progress-ring-fill",
17039
+ strokeDasharray: MSC_RING_CIRC,
17040
+ strokeDashoffset: MSC_RING_CIRC
17041
+ }
17042
+ )
17043
+ ] }),
17044
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: etaRef, className: "ps-tryon-progress-eta", children: `~${MSC_TRYON_TARGET_SECONDS}s` })
17045
+ ] }),
17046
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: barRef, className: "ps-tryon-progress-bar-fill" }) }),
17047
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: pctRef, className: "ps-tryon-progress-pct", children: "0%" })
17048
+ ] });
17049
+ }
16879
17050
  function MobileScanningView({
16880
17051
  previewUrl,
16881
17052
  productImage,
16882
17053
  bodyLandmarks,
16883
17054
  sizingDone,
17055
+ tryOnProcessing,
16884
17056
  onSwitchToManual,
16885
17057
  t: t2
16886
17058
  }) {
16887
17059
  const displayImage = previewUrl || productImage || "";
16888
17060
  const isPhotoMode = !!previewUrl;
16889
- const stages = isPhotoMode ? [
17061
+ const stages = tryOnProcessing ? [
17062
+ { title: t2("GENERATING TRY-ON"), desc: t2("Rendering the garment on your photo."), viewfinderText: t2("GENERATING") },
17063
+ { title: t2("REFINING DETAILS"), desc: t2("Fine-tuning fit, drape and shadows."), viewfinderText: t2("REFINING") },
17064
+ { title: t2("ALMOST THERE"), desc: t2("Final compositing in progress."), viewfinderText: t2("COMPOSITING") },
17065
+ { title: t2("FINISHING TOUCHES"), desc: t2("Polishing the result."), viewfinderText: t2("FINISHING") }
17066
+ ] : isPhotoMode ? [
16890
17067
  { title: t2("DETECTING POSE"), desc: t2("Identifying body landmarks from your photo."), viewfinderText: t2("DETECTING POSE") },
16891
17068
  { title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions to calculate the perfect fit."), viewfinderText: t2("SCANNING FRAME") },
16892
17069
  { title: t2("ANALYZING BODY"), desc: t2("Measuring shoulders, chest, waist and hips."), viewfinderText: t2("ANALYZING") },
@@ -16905,11 +17082,12 @@ function MobileScanningView({
16905
17082
  };
16906
17083
  const [stageIdx, setStageIdx] = reactExports.useState(0);
16907
17084
  reactExports.useEffect(() => {
17085
+ const intervalMs = tryOnProcessing ? 2200 : 1500;
16908
17086
  const id2 = setInterval(() => {
16909
17087
  setStageIdx((i) => (i + 1) % stages.length);
16910
- }, 1500);
17088
+ }, intervalMs);
16911
17089
  return () => clearInterval(id2);
16912
- }, [stages.length]);
17090
+ }, [stages.length, tryOnProcessing]);
16913
17091
  reactExports.useEffect(() => {
16914
17092
  if (isPhotoMode && bodyLandmarks && stageIdx === 0) {
16915
17093
  setStageIdx(1);
@@ -16929,10 +17107,13 @@ function MobileScanningView({
16929
17107
  ),
16930
17108
  isPhotoMode && bodyLandmarks && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-pose-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MobileSkeleton, { landmarks: bodyLandmarks, w: dims.w, h: dims.h }) })
16931
17109
  ] }),
16932
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage-slot", children: [
16933
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
16934
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
16935
- ] }, stageIdx) }),
17110
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage", children: [
17111
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage-slot", children: [
17112
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
17113
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
17114
+ ] }, stageIdx),
17115
+ tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsx(MscTryOnProgress, { t: t2 })
17116
+ ] }),
16936
17117
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-spacer" }),
16937
17118
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
16938
17119
  MobileBottomTabs,
@@ -17063,7 +17244,7 @@ function MultiSectionMobile({
17063
17244
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msr-sections", children: sectionEntries.map(({ name, secResult }) => {
17064
17245
  const cleanName = name.replace(/\s*[—–-]\s*.*/g, "");
17065
17246
  const sec = secResult;
17066
- const sizeValue = sec.size || secResult.recommendedSize;
17247
+ const sizeValue = sec.found === false ? t2("No fit") : sec.size || secResult.recommendedSize;
17067
17248
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
17068
17249
  "button",
17069
17250
  {
@@ -17098,7 +17279,19 @@ function MultiSectionMobile({
17098
17279
  children: t2("Continue Shopping")
17099
17280
  }
17100
17281
  )
17101
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
17282
+ ] }) : sizingResult?.found === false ? (
17283
+ // Backend couldn't find a size that fits — Try-On is meaningless
17284
+ // without a recommendation, so surface a clear terminal action.
17285
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
17286
+ "button",
17287
+ {
17288
+ type: "button",
17289
+ className: "ps-msr-tryon-cta",
17290
+ onClick: onClose,
17291
+ children: t2("Continue Shopping")
17292
+ }
17293
+ )
17294
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
17102
17295
  "button",
17103
17296
  {
17104
17297
  type: "button",
@@ -17130,6 +17323,62 @@ const SKELETON_CONNECTIONS = [
17130
17323
  ["rightHip", "rightKnee"],
17131
17324
  ["rightKnee", "rightAnkle"]
17132
17325
  ];
17326
+ const TRYON_TARGET_SECONDS = 22;
17327
+ const TRYON_RING_RADIUS = 27;
17328
+ const TRYON_RING_CIRC = 2 * Math.PI * TRYON_RING_RADIUS;
17329
+ function TryOnProgress({ t: t2, isActive }) {
17330
+ const startRef = reactExports.useRef(null);
17331
+ const ringRef = reactExports.useRef(null);
17332
+ const barRef = reactExports.useRef(null);
17333
+ const etaRef = reactExports.useRef(null);
17334
+ const pctRef = reactExports.useRef(null);
17335
+ reactExports.useEffect(() => {
17336
+ if (!isActive) {
17337
+ startRef.current = null;
17338
+ return;
17339
+ }
17340
+ startRef.current = Date.now();
17341
+ const id2 = setInterval(() => {
17342
+ const start = startRef.current || Date.now();
17343
+ const elapsed = (Date.now() - start) / 1e3;
17344
+ const pct = Math.min(95, elapsed / TRYON_TARGET_SECONDS * 100);
17345
+ const val = Math.round(pct);
17346
+ if (barRef.current) barRef.current.style.width = `${val}%`;
17347
+ if (pctRef.current) pctRef.current.textContent = `${val}%`;
17348
+ if (ringRef.current) {
17349
+ ringRef.current.style.strokeDashoffset = String(TRYON_RING_CIRC * (1 - pct / 100));
17350
+ }
17351
+ if (etaRef.current) {
17352
+ const remaining = Math.max(0, TRYON_TARGET_SECONDS - Math.floor(elapsed));
17353
+ etaRef.current.textContent = elapsed >= TRYON_TARGET_SECONDS ? t2("Finalizing...") : `~${remaining}s`;
17354
+ }
17355
+ }, 200);
17356
+ return () => clearInterval(id2);
17357
+ }, [isActive]);
17358
+ if (!isActive) return null;
17359
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-wrap", children: [
17360
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-ring", children: [
17361
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "64", height: "64", viewBox: "0 0 64 64", "aria-hidden": "true", children: [
17362
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "32", cy: "32", r: TRYON_RING_RADIUS, className: "ps-tryon-progress-ring-track" }),
17363
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
17364
+ "circle",
17365
+ {
17366
+ ref: ringRef,
17367
+ cx: "32",
17368
+ cy: "32",
17369
+ r: TRYON_RING_RADIUS,
17370
+ className: "ps-tryon-progress-ring-fill",
17371
+ strokeDasharray: TRYON_RING_CIRC,
17372
+ strokeDashoffset: TRYON_RING_CIRC
17373
+ }
17374
+ )
17375
+ ] }),
17376
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: etaRef, className: "ps-tryon-progress-eta", children: `~${TRYON_TARGET_SECONDS}s` })
17377
+ ] }),
17378
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: barRef, className: "ps-tryon-progress-bar-fill" }) }),
17379
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: pctRef, className: "ps-tryon-progress-pct", children: "0%" })
17380
+ ] });
17381
+ }
17133
17382
  function FaceOverlay({
17134
17383
  landmarks,
17135
17384
  imgWidth,
@@ -17267,16 +17516,20 @@ function StageCycler({
17267
17516
  }, [tryOnProcessing]);
17268
17517
  reactExports.useEffect(() => {
17269
17518
  if (isDone) return;
17519
+ const intervalMs = tryOnProcessing ? 2200 : 900;
17270
17520
  const id2 = setInterval(() => {
17271
17521
  setIdx((i) => Math.min(i + 1, active.length - 1));
17272
- }, 900);
17522
+ }, intervalMs);
17273
17523
  return () => clearInterval(id2);
17274
- }, [isDone, active.length]);
17524
+ }, [isDone, active.length, tryOnProcessing]);
17275
17525
  const current = active[idx] ?? active[0];
17276
- 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: [
17277
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
17278
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
17279
- ] }, `${tryOnProcessing ? "t" : "s"}-${idx}`) });
17526
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage", style: { alignSelf: "center", marginTop: "auto", marginBottom: "auto" }, children: [
17527
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage-slot", children: [
17528
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
17529
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
17530
+ ] }, `${tryOnProcessing ? "t" : "s"}-${idx}`),
17531
+ tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnProgress, { t: t2, isActive: !!tryOnProcessing })
17532
+ ] });
17280
17533
  }
17281
17534
  function SkeletonOverlay({ landmarks, imgWidth, imgHeight }) {
17282
17535
  const W2 = imgWidth;
@@ -17515,7 +17768,8 @@ function SectionDetailView({
17515
17768
  backLabel,
17516
17769
  internationalSizes,
17517
17770
  continueLabel,
17518
- renderRaw = false
17771
+ renderRaw = false,
17772
+ sectionFound
17519
17773
  }) {
17520
17774
  const recSize = sectionResult?.recommendedSize || "";
17521
17775
  const [selectedSize, setSelectedSize] = reactExports.useState(null);
@@ -17560,7 +17814,8 @@ function SectionDetailView({
17560
17814
  const hasBadFit = details.some((d) => BAD_FIT.test(d.fit || ""));
17561
17815
  return hasBadFit ? t2("Not Recommended") : t2("Your Selection");
17562
17816
  }, [isRecommended, sectionResult, t2]);
17563
- const displaySizeLabel = selectedCountry && isRecommended && internationalSizes && internationalSizes[selectedCountry] ? internationalSizes[selectedCountry] : displaySize;
17817
+ const noFitMessage = t2("We couldn't find a size that fits for this product");
17818
+ const displaySizeLabel = sectionFound === false ? noFitMessage : selectedCountry && isRecommended && internationalSizes && internationalSizes[selectedCountry] ? internationalSizes[selectedCountry] : displaySize;
17564
17819
  const columnUnits = reactExports.useMemo(() => {
17565
17820
  const units = [];
17566
17821
  for (let i = 0; i < section.headers.length; i++) {
@@ -18414,6 +18669,7 @@ function SizeResultView({
18414
18669
  const allDone = hasPhoto ? sizingDone && tryOnDone : sizingDone;
18415
18670
  const isMobile = useIsMobile();
18416
18671
  const isAccessory = measurementType === "face" || measurementType === "head";
18672
+ const noFit = sizingResult?.found === false;
18417
18673
  const vtoExcluded = measurementType === "foot";
18418
18674
  console.log("[PS-SDK] SizeResultView render:", {
18419
18675
  hasPhoto,
@@ -18452,6 +18708,7 @@ function SizeResultView({
18452
18708
  previewUrl,
18453
18709
  bodyLandmarks: bodyLandmarks ?? null,
18454
18710
  sizingDone,
18711
+ tryOnProcessing,
18455
18712
  onSwitchToManual: () => setView("body-profile"),
18456
18713
  t: t2
18457
18714
  }
@@ -18497,6 +18754,7 @@ function SizeResultView({
18497
18754
  sectionName: entry.name,
18498
18755
  section: entry.section,
18499
18756
  sectionResult: entry.secResult,
18757
+ sectionFound: entry.secResult?.found,
18500
18758
  userMeasurements: entry.userMeasurements,
18501
18759
  unitLbl,
18502
18760
  chartUnit: resultUnit,
@@ -18508,7 +18766,7 @@ function SizeResultView({
18508
18766
  isMobile: true,
18509
18767
  isTryOnImage: !!resultImageUrl,
18510
18768
  showLines,
18511
- onToggleLines: () => setShowLines(!showLines),
18769
+ onToggleLines: isAccessory ? void 0 : () => setShowLines(!showLines),
18512
18770
  onImageLoad: handleImgLoad,
18513
18771
  overlayNode: resultImageUrl && poseReady && poseLines ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18514
18772
  MeasurementOverlay,
@@ -18546,6 +18804,7 @@ function SizeResultView({
18546
18804
  sectionName: entry.name,
18547
18805
  section: entry.section,
18548
18806
  sectionResult: entry.secResult,
18807
+ sectionFound: entry.secResult?.found,
18549
18808
  userMeasurements: entry.userMeasurements,
18550
18809
  unitLbl,
18551
18810
  chartUnit: resultUnit,
@@ -18582,7 +18841,7 @@ function SizeResultView({
18582
18841
  },
18583
18842
  onClose,
18584
18843
  showLines,
18585
- onToggleLines: () => setShowLines(!showLines),
18844
+ onToggleLines: isAccessory ? void 0 : () => setShowLines(!showLines),
18586
18845
  onImageLoad: handleImgLoad,
18587
18846
  overlayNode: resultImageUrl && poseReady && poseLines ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18588
18847
  MeasurementOverlay,
@@ -18617,7 +18876,10 @@ function SizeResultView({
18617
18876
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-bg", style: { position: "relative" }, children: [
18618
18877
  /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: tryOnProcessing && previewUrl ? previewUrl : resultImageUrl || productImage, alt: productTitle, className: "ps-tryon-v2-bg-img", onLoad: handleImgLoad }),
18619
18878
  tryOnProcessing && bodyLandmarks && /* @__PURE__ */ jsxRuntimeExports.jsx(SkeletonOverlay, { landmarks: bodyLandmarks, imgWidth: imgDims.w, imgHeight: imgDims.h }),
18620
- tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-processing-label", children: t2("Generating try-on...") }),
18879
+ tryOnProcessing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-processing-label", children: [
18880
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("Generating try-on...") }),
18881
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TryOnProgress, { t: t2, isActive: true })
18882
+ ] }),
18621
18883
  resultImageUrl && !tryOnProcessing && poseReady && poseLines && /* @__PURE__ */ jsxRuntimeExports.jsx(MeasurementOverlay, { lines: poseLines, fitRows: (() => {
18622
18884
  const all = [...sizingResult?.matchDetails || []];
18623
18885
  if (sizingResult?.sections) {
@@ -18634,7 +18896,7 @@ function SizeResultView({
18634
18896
  }).map((m2) => ({ area: m2.measurement, userNum: parseFloat(m2.userValue) || 0, chartLabel: m2.chartRange || "", fit: m2.fit }));
18635
18897
  })(), show: showLines, imgWidth: imgDims.w, imgHeight: imgDims.h }),
18636
18898
  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: [
18637
- /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-sr-glass-btn", onClick: () => setShowLines(!showLines), children: [
18899
+ !isAccessory && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-sr-glass-btn", onClick: () => setShowLines(!showLines), children: [
18638
18900
  /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", style: { marginRight: "0.3vw" }, children: [
18639
18901
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "4", y1: "9", x2: "20", y2: "9" }),
18640
18902
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "4", y1: "15", x2: "20", y2: "15" }),
@@ -18664,7 +18926,7 @@ function SizeResultView({
18664
18926
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: `ps-tryon-sr-card-v2${isLast ? " ps-full" : ""}`, onClick: () => setActiveSection(name), style: { animationDelay: `${idx * 0.07}s` }, children: [
18665
18927
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-card-v2-text", children: [
18666
18928
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-label", children: name.replace(/\s*[—–-]\s*.*/g, "") }),
18667
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-value", children: sec.size || secResult.recommendedSize }),
18929
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-value", children: sec.found === false ? t2("No fit") : sec.size || secResult.recommendedSize }),
18668
18930
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-rec", children: t2("recommended") })
18669
18931
  ] }),
18670
18932
  sectionImg && /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: sectionImg, alt: name, className: "ps-tryon-sr-card-v2-img" }),
@@ -18688,7 +18950,7 @@ function SizeResultView({
18688
18950
  " →"
18689
18951
  ]
18690
18952
  }
18691
- ) : vtoExcluded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
18953
+ ) : vtoExcluded || noFit ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
18692
18954
  "button",
18693
18955
  {
18694
18956
  className: "ps-tryon-v2-cta",
@@ -18741,6 +19003,7 @@ function SizeResultView({
18741
19003
  sectionName,
18742
19004
  section: singleSection,
18743
19005
  sectionResult: singleResult,
19006
+ sectionFound: sizingResult?.found,
18744
19007
  userMeasurements: singleUserMeasurements,
18745
19008
  unitLbl,
18746
19009
  chartUnit: resultUnit,
@@ -18748,7 +19011,7 @@ function SizeResultView({
18748
19011
  onBack: resultImageUrl ? onClose || (() => setView("body-profile")) : () => setView("body-profile"),
18749
19012
  backLabel: t2("Back"),
18750
19013
  internationalSizes: sizingResult?.internationalSizes,
18751
- onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
19014
+ onTryOn: resultImageUrl || vtoExcluded || noFit ? void 0 : handleSingleTryOn,
18752
19015
  continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
18753
19016
  tryOnProcessing,
18754
19017
  productImage: resultImageUrl || productImage,
@@ -18757,7 +19020,7 @@ function SizeResultView({
18757
19020
  renderRaw: isAccessory,
18758
19021
  isTryOnImage: !!resultImageUrl,
18759
19022
  showLines,
18760
- onToggleLines: () => setShowLines(!showLines),
19023
+ onToggleLines: isAccessory ? void 0 : () => setShowLines(!showLines),
18761
19024
  onImageLoad: handleImgLoad,
18762
19025
  overlayNode: resultImageUrl && poseReady && poseLines ? /* @__PURE__ */ jsxRuntimeExports.jsx(
18763
19026
  MeasurementOverlay,
@@ -18778,7 +19041,7 @@ function SizeResultView({
18778
19041
  /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: resultImageUrl || productImage, alt: productTitle, className: "ps-tryon-v2-bg-img", onLoad: handleImgLoad }),
18779
19042
  resultImageUrl && 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 }),
18780
19043
  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: [
18781
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ps-tryon-sr-glass-btn", onClick: () => setShowLines(!showLines), children: showLines ? t2("Hide Fit") : t2("Show Fit") }),
19044
+ !isAccessory && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ps-tryon-sr-glass-btn", onClick: () => setShowLines(!showLines), children: showLines ? t2("Hide Fit") : t2("Show Fit") }),
18782
19045
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ps-tryon-sr-glass-btn", onClick: handleDownload, children: t2("Download") })
18783
19046
  ] })
18784
19047
  ] }),
@@ -18788,6 +19051,7 @@ function SizeResultView({
18788
19051
  sectionName,
18789
19052
  section: singleSection,
18790
19053
  sectionResult: singleResult,
19054
+ sectionFound: sizingResult?.found,
18791
19055
  userMeasurements: singleUserMeasurements,
18792
19056
  unitLbl,
18793
19057
  chartUnit: resultUnit,
@@ -18795,7 +19059,7 @@ function SizeResultView({
18795
19059
  onBack: resultImageUrl ? onClose || (() => setView("body-profile")) : () => setView("body-profile"),
18796
19060
  backLabel: t2("Back"),
18797
19061
  internationalSizes: sizingResult?.internationalSizes,
18798
- onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
19062
+ onTryOn: resultImageUrl || vtoExcluded || noFit ? void 0 : handleSingleTryOn,
18799
19063
  continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
18800
19064
  tryOnProcessing,
18801
19065
  t: t2,
@@ -19171,7 +19435,7 @@ function UploadView({
19171
19435
  }
19172
19436
  ) });
19173
19437
  }
19174
- const RING_RADIUS = 20;
19438
+ const RING_RADIUS = 27;
19175
19439
  const RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS;
19176
19440
  function ProcessingView({
19177
19441
  previewUrl,
@@ -19216,12 +19480,12 @@ function ProcessingView({
19216
19480
  ] }),
19217
19481
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-section", children: [
19218
19482
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-ring", children: [
19219
- /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 48 48", width: "48", height: "48", "aria-hidden": "true", children: [
19483
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 64 64", width: "64", height: "64", "aria-hidden": "true", children: [
19220
19484
  /* @__PURE__ */ jsxRuntimeExports.jsx(
19221
19485
  "circle",
19222
19486
  {
19223
- cx: "24",
19224
- cy: "24",
19487
+ cx: "32",
19488
+ cy: "32",
19225
19489
  r: RING_RADIUS,
19226
19490
  className: "ps-tryon-progress-ring-track"
19227
19491
  }
@@ -19230,8 +19494,8 @@ function ProcessingView({
19230
19494
  "circle",
19231
19495
  {
19232
19496
  ref: ringCb,
19233
- cx: "24",
19234
- cy: "24",
19497
+ cx: "32",
19498
+ cy: "32",
19235
19499
  r: RING_RADIUS,
19236
19500
  className: "ps-tryon-progress-ring-fill",
19237
19501
  strokeDasharray: RING_CIRCUMFERENCE,
@@ -21801,7 +22065,7 @@ function BodyProfileView({
21801
22065
  hidePhotoOptions: hasActiveProfileWithMeasurements,
21802
22066
  onNext: hasActiveProfileWithMeasurements && onUseActiveProfile ? onUseActiveProfile : handleNext,
21803
22067
  canProceed: true,
21804
- fastPathLabel: hasActiveProfileWithMeasurements ? t2("Find My Best Fit") : void 0,
22068
+ fastPathLabel: hasActiveProfileWithMeasurements ? t2("Find My Best Fit") + (getUnitLabel(hUnit) ? ` (${getUnitLabel(hUnit)})` : "") : void 0,
21805
22069
  activeProfileName: hasActiveProfileWithMeasurements ? activeProfileName : null,
21806
22070
  onStartFresh,
21807
22071
  error,
@@ -22056,7 +22320,8 @@ function BodyProfileView({
22056
22320
  !(isMobile && step === "basics") && (() => {
22057
22321
  const useProfileFast = step === "basics" && hasActiveProfileWithMeasurements && !!onUseActiveProfile;
22058
22322
  const handleClick = useProfileFast ? onUseActiveProfile : handleNext;
22059
- const label = useProfileFast ? t2("Find My Best Fit") : isLastStep ? t2("Find My Size") : t2("Next");
22323
+ const unitSuffix = getUnitLabel(hUnit) ? ` (${getUnitLabel(hUnit)})` : "";
22324
+ const label = useProfileFast ? t2("Find My Best Fit") + unitSuffix : isLastStep ? t2("Find My Size") + unitSuffix : t2("Next");
22060
22325
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-nav", children: [
22061
22326
  step !== "basics" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-bp-back-btn", onClick: handleBackStep, type: "button", children: [
22062
22327
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
@@ -22246,6 +22511,7 @@ function AccessorySizeView({
22246
22511
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bpm-bottom", children: [
22247
22512
  /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "ps-bpm-next-btn", onClick: handleManualSubmit, children: [
22248
22513
  t2("Find My Size"),
22514
+ getUnitLabel(sizingUnit) ? ` (${getUnitLabel(sizingUnit)})` : "",
22249
22515
  " ",
22250
22516
  /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowRightIcon, {})
22251
22517
  ] }),
@@ -22580,6 +22846,7 @@ function AccessorySizeView({
22580
22846
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
22581
22847
  /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-bp-next-btn", onClick: handleManualSubmit, type: "button", children: [
22582
22848
  t2("Find My Size"),
22849
+ getUnitLabel(sizingUnit) ? ` (${getUnitLabel(sizingUnit)})` : "",
22583
22850
  " ",
22584
22851
  /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowRightIcon, {})
22585
22852
  ] })
@@ -22813,6 +23080,9 @@ function PrimeStyleTryonInner({
22813
23080
  const [sizingUnit, setSizingUnit] = reactExports.useState(imperial ? "in" : "cm");
22814
23081
  const [heightUnit, setHeightUnit] = reactExports.useState(imperial ? "in" : "cm");
22815
23082
  const [weightUnit, setWeightUnit] = reactExports.useState(imperial ? "lbs" : "kg");
23083
+ reactExports.useEffect(() => {
23084
+ if (detectMeasurementType(productTitle) === "foot") setSizingUnit("cm");
23085
+ }, [productTitle]);
22816
23086
  const formRef = reactExports.useRef({});
22817
23087
  const [formGender, setFormGender] = reactExports.useState("male");
22818
23088
  const [formKey, setFormKey] = reactExports.useState(0);
@@ -22887,7 +23157,7 @@ function PrimeStyleTryonInner({
22887
23157
  { at: 75, text: t2("Refining details...") },
22888
23158
  { at: 90, text: t2("Almost there...") }
22889
23159
  ];
22890
- const RING_CIRCUMFERENCE2 = 2 * Math.PI * 20;
23160
+ const RING_CIRCUMFERENCE2 = 2 * Math.PI * 27;
22891
23161
  progressIntervalRef.current = setInterval(() => {
22892
23162
  if (completedRef.current) return;
22893
23163
  const startTs = progressStartTsRef.current || Date.now();
@@ -23065,13 +23335,10 @@ function PrimeStyleTryonInner({
23065
23335
  [activeProfileId, profiles, apiUrl, productImage, productTitle, effectiveProductId, setActiveProfileId$1]
23066
23336
  );
23067
23337
  const snapSubmitRef = reactExports.useRef(null);
23068
- const handleUseActiveProfile = reactExports.useCallback(async () => {
23069
- const p2 = profiles.find((x2) => x2.id === activeProfileId);
23070
- if (!p2) return;
23338
+ const [confirmProfile, setConfirmProfile] = reactExports.useState(null);
23339
+ const runRecommendWithProfile = reactExports.useCallback(async (p2) => {
23071
23340
  const profileHeight = p2.height ?? p2.heightCm ?? 0;
23072
23341
  const profileWeight = p2.weight ?? p2.weightKg ?? 0;
23073
- const hasIdentity = profileHeight > 0 && profileWeight > 0;
23074
- if (!hasIdentity) return;
23075
23342
  const hasStored = !!p2.measurements && Object.keys(p2.measurements).length > 0;
23076
23343
  const storedPhoto = p2.photoBase64;
23077
23344
  if (!hasStored && storedPhoto && profileHeight > 0 && snapSubmitRef.current) {
@@ -23095,9 +23362,8 @@ function PrimeStyleTryonInner({
23095
23362
  }
23096
23363
  setSizingResult(null);
23097
23364
  setSizingLoading(true);
23098
- const hasStoredMeasurements = !!p2.measurements && Object.keys(p2.measurements).length > 0;
23099
- setEstimationDone(hasStoredMeasurements);
23100
- if (hasStoredMeasurements) {
23365
+ setEstimationDone(hasStored);
23366
+ if (hasStored) {
23101
23367
  setPreviewUrl(null);
23102
23368
  setBodyLandmarks(null);
23103
23369
  }
@@ -23130,7 +23396,27 @@ function PrimeStyleTryonInner({
23130
23396
  setEstimationDone(true);
23131
23397
  }).catch(() => {
23132
23398
  }).finally(() => setSizingLoading(false));
23133
- }, [profiles, activeProfileId, effectiveProductId, productTitle, productImage, sizeGuideData, apiUrl]);
23399
+ }, [effectiveProductId, productTitle, productImage, sizeGuideData, apiUrl, previewUrl]);
23400
+ const handleUseActiveProfile = reactExports.useCallback(async () => {
23401
+ const p2 = profiles.find((x2) => x2.id === activeProfileId);
23402
+ if (!p2) return;
23403
+ const profileHeight = p2.height ?? p2.heightCm ?? 0;
23404
+ const profileWeight = p2.weight ?? p2.weightKg ?? 0;
23405
+ const hasIdentity = profileHeight > 0 && profileWeight > 0;
23406
+ if (!hasIdentity) return;
23407
+ setConfirmProfile(p2);
23408
+ }, [profiles, activeProfileId]);
23409
+ const proceedFromConfirmProfile = reactExports.useCallback(() => {
23410
+ if (!confirmProfile) return;
23411
+ const p2 = confirmProfile;
23412
+ setConfirmProfile(null);
23413
+ void runRecommendWithProfile(p2);
23414
+ }, [confirmProfile, runRecommendWithProfile]);
23415
+ const cancelFromConfirmProfile = reactExports.useCallback(() => {
23416
+ setConfirmProfile(null);
23417
+ setFormKey((k2) => k2 + 1);
23418
+ setView("body-profile");
23419
+ }, []);
23134
23420
  const applyProfileRef = reactExports.useRef(() => {
23135
23421
  });
23136
23422
  const handleOpen = reactExports.useCallback(() => {
@@ -24505,6 +24791,15 @@ function PrimeStyleTryonInner({
24505
24791
  onCancel: () => setDeleteConfirmId(null),
24506
24792
  t: t2
24507
24793
  }
24794
+ ),
24795
+ confirmProfile && /* @__PURE__ */ jsxRuntimeExports.jsx(
24796
+ ConfirmMeasurementsModal,
24797
+ {
24798
+ profile: confirmProfile,
24799
+ onProceed: proceedFromConfirmProfile,
24800
+ onEdit: cancelFromConfirmProfile,
24801
+ t: t2
24802
+ }
24508
24803
  )
24509
24804
  ] }) }),
24510
24805
  document.body