@primestyleai/tryon 5.10.144 → 5.10.169
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-GW10cktY.js → index-B1_VQgps.js} +53 -68
- package/dist/{index-GW10cktY.js.map → index-B1_VQgps.js.map} +1 -1
- package/dist/primestyle-tryon.js +2 -2
- package/dist/react/index.js +4908 -4585
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/sizing/fit-compute.d.ts +13 -4
- package/dist/storefront/primestyle-tryon.js +623 -129
- package/package.json +1 -1
|
@@ -10098,20 +10098,15 @@ function parseNum(s) {
|
|
|
10098
10098
|
function computeFit(userValue, chartRange, unit) {
|
|
10099
10099
|
const { min: rMin, max: rMax } = parseRange(chartRange);
|
|
10100
10100
|
if (rMin === 0 && rMax === 0) return "good";
|
|
10101
|
-
const
|
|
10102
|
-
const
|
|
10103
|
-
const
|
|
10104
|
-
if (userValue
|
|
10105
|
-
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
|
|
10109
|
-
|
|
10110
|
-
}
|
|
10111
|
-
const diff = userValue - rMax;
|
|
10112
|
-
if (diff > threshold * 2) return "too-tight";
|
|
10113
|
-
if (diff > threshold) return "tight";
|
|
10114
|
-
return "a-bit-tight";
|
|
10101
|
+
const perfectTol = unit === "cm" ? 0.25 : unit === "mm" ? 2.5 : 0.1;
|
|
10102
|
+
const aBitTol = unit === "cm" ? 1.27 : unit === "mm" ? 12.7 : 0.5;
|
|
10103
|
+
const tooFarTol = unit === "cm" ? 5.08 : unit === "mm" ? 50.8 : 2;
|
|
10104
|
+
if (userValue >= rMin - perfectTol && userValue <= rMax + perfectTol) return "good";
|
|
10105
|
+
const isUnder = userValue < rMin;
|
|
10106
|
+
const diff = isUnder ? rMin - userValue : userValue - rMax;
|
|
10107
|
+
if (diff > tooFarTol) return isUnder ? "too-loose" : "too-tight";
|
|
10108
|
+
if (diff > aBitTol) return isUnder ? "loose" : "tight";
|
|
10109
|
+
return isUnder ? "a-bit-loose" : "a-bit-tight";
|
|
10115
10110
|
}
|
|
10116
10111
|
const AREA_TO_POSE_KEY = {
|
|
10117
10112
|
chest: "chest",
|
|
@@ -10151,10 +10146,44 @@ function buildFitInfo(matchDetails, poseLines, unit) {
|
|
|
10151
10146
|
function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, userHeight, userWeight) {
|
|
10152
10147
|
if (!sizingResult && !sizeGuide && !userHeight && !userWeight) return void 0;
|
|
10153
10148
|
const out = {};
|
|
10154
|
-
|
|
10155
|
-
else if (sizingResult?.recommendedSize) out.recommendedSize = sizingResult.recommendedSize;
|
|
10149
|
+
const baseSize = (selectedSizeOverride || sizingResult?.recommendedSize || "").toString().trim();
|
|
10156
10150
|
if (userHeight) out.userHeight = userHeight;
|
|
10157
10151
|
if (userWeight) out.userWeight = userWeight;
|
|
10152
|
+
let chartRowLength = null;
|
|
10153
|
+
let chartRowFit = null;
|
|
10154
|
+
if (baseSize && sizeGuide?.headers?.length && sizeGuide.rows?.length) {
|
|
10155
|
+
const matchRow = sizeGuide.rows.find((r2) => (r2[0] ?? "").toString().trim() === baseSize);
|
|
10156
|
+
if (matchRow) {
|
|
10157
|
+
const hdrs = sizeGuide.headers;
|
|
10158
|
+
const bits = [];
|
|
10159
|
+
for (let i = 1; i < hdrs.length; i++) {
|
|
10160
|
+
const v2 = matchRow[i];
|
|
10161
|
+
const vStr = v2 == null ? "" : String(v2).trim();
|
|
10162
|
+
const h = hdrs[i] || "";
|
|
10163
|
+
if (chartRowFit == null && /^(fit|silhouette|category|body[\s_]?type)$/i.test(h) && vStr) {
|
|
10164
|
+
chartRowFit = vStr;
|
|
10165
|
+
continue;
|
|
10166
|
+
}
|
|
10167
|
+
if (vStr) bits.push(`${h} ${vStr}`);
|
|
10168
|
+
if (chartRowLength == null && /^length\b|inseam/i.test(h) && vStr) {
|
|
10169
|
+
chartRowLength = vStr;
|
|
10170
|
+
}
|
|
10171
|
+
}
|
|
10172
|
+
if (bits.length) out.recommendedSizeMeasurements = bits.join(", ");
|
|
10173
|
+
}
|
|
10174
|
+
}
|
|
10175
|
+
if (baseSize) {
|
|
10176
|
+
const prefixed = chartRowFit ? `${chartRowFit} ${baseSize}` : baseSize;
|
|
10177
|
+
const length = sizingResult?.recommendedLength || chartRowLength;
|
|
10178
|
+
if (length) {
|
|
10179
|
+
const lenStr = String(length).trim();
|
|
10180
|
+
const unit = (sizingResult?.unit || "in").toString();
|
|
10181
|
+
const hasUnit = /[a-z]/i.test(lenStr);
|
|
10182
|
+
out.recommendedSize = `${prefixed} / Length ${lenStr}${hasUnit ? "" : ` ${unit}`}`;
|
|
10183
|
+
} else {
|
|
10184
|
+
out.recommendedSize = prefixed;
|
|
10185
|
+
}
|
|
10186
|
+
}
|
|
10158
10187
|
const seen = /* @__PURE__ */ new Set();
|
|
10159
10188
|
const userLines = [];
|
|
10160
10189
|
const push = (md2) => {
|
|
@@ -10806,6 +10835,40 @@ const STYLES$1 = `
|
|
|
10806
10835
|
}
|
|
10807
10836
|
.ps-tryon-header-icon:hover { border-color: var(--ps-accent); color: var(--ps-accent); }
|
|
10808
10837
|
.ps-tryon-header-icon svg { stroke: currentColor; fill: none; width: clamp(14px, 0.9vw, 16px); height: clamp(14px, 0.9vw, 16px); }
|
|
10838
|
+
/* Labeled variant — icon + text. Auto width, vw-scaled padding/gap so the
|
|
10839
|
+
glyph and the label baseline-align cleanly across breakpoints. */
|
|
10840
|
+
.ps-tryon-header-icon-labeled {
|
|
10841
|
+
width: auto !important;
|
|
10842
|
+
padding: 0 clamp(8px, 0.6vw, 12px);
|
|
10843
|
+
gap: clamp(5px, 0.42vw, 8px);
|
|
10844
|
+
font-size: clamp(11px, 0.73vw, 13px);
|
|
10845
|
+
font-family: inherit;
|
|
10846
|
+
font-weight: 500;
|
|
10847
|
+
line-height: 1;
|
|
10848
|
+
white-space: nowrap;
|
|
10849
|
+
}
|
|
10850
|
+
.ps-tryon-header-icon-label { line-height: 1; }
|
|
10851
|
+
/* "Powered by PrimeStyleAI" — left-aligned tag in the modal header,
|
|
10852
|
+
links out to primestyleai.com in a new tab. */
|
|
10853
|
+
.ps-tryon-powered-by {
|
|
10854
|
+
margin-right: auto;
|
|
10855
|
+
font-size: clamp(10px, 0.68vw, 12px);
|
|
10856
|
+
color: #9aa0a6;
|
|
10857
|
+
letter-spacing: 0.04em;
|
|
10858
|
+
font-weight: 400;
|
|
10859
|
+
line-height: 1.4;
|
|
10860
|
+
text-transform: uppercase;
|
|
10861
|
+
white-space: nowrap;
|
|
10862
|
+
text-decoration: none;
|
|
10863
|
+
transition: color 0.2s;
|
|
10864
|
+
}
|
|
10865
|
+
.ps-tryon-powered-by:hover { color: #5a6168; }
|
|
10866
|
+
.ps-tryon-powered-by:hover strong { color: var(--ps-accent); }
|
|
10867
|
+
.ps-tryon-powered-by strong { color: #5a6168; font-weight: 600; letter-spacing: 0.02em; text-transform: none; transition: color 0.2s; }
|
|
10868
|
+
/* Mobile hamburger button (desktop: hidden — inline buttons handle this) */
|
|
10869
|
+
.ps-tryon-header-mobile-menu-btn { display: none; }
|
|
10870
|
+
.ps-tryon-header-mobile-backdrop { display: none; }
|
|
10871
|
+
.ps-tryon-header-mobile-menu { display: none; }
|
|
10809
10872
|
.ps-tryon-close {
|
|
10810
10873
|
width: 2.2vw; height: 2.2vw; display: flex; align-items: center; justify-content: center;
|
|
10811
10874
|
background: none; border: none; color: var(--ps-modal-close-color, #999);
|
|
@@ -13812,15 +13875,112 @@ const STYLES$1 = `
|
|
|
13812
13875
|
flex-shrink: 0;
|
|
13813
13876
|
background: var(--ps-modal-header-bg, rgba(255,255,255,0.95)) !important;
|
|
13814
13877
|
}
|
|
13815
|
-
/* Mobile header icons: minimal flat glyphs,
|
|
13816
|
-
*
|
|
13817
|
-
*
|
|
13878
|
+
/* Mobile header icons: minimal flat glyphs, slightly bigger touch
|
|
13879
|
+
* targets than before so the icons read clearly at arms length, and
|
|
13880
|
+
* with extra spacing between adjacent buttons (gap below). Labels are
|
|
13881
|
+
* desktop-only — hide the inline text on mobile so it stays icon-only. */
|
|
13818
13882
|
.ps-tryon-header-icon {
|
|
13819
|
-
width:
|
|
13883
|
+
width: 34px !important; height: 34px !important;
|
|
13820
13884
|
border: none !important; background: transparent !important;
|
|
13821
13885
|
border-radius: 0 !important; padding: 0 !important;
|
|
13886
|
+
gap: 0 !important;
|
|
13887
|
+
}
|
|
13888
|
+
.ps-tryon-header-icon svg { width: 20px !important; height: 20px !important; }
|
|
13889
|
+
.ps-tryon-header-icon-labeled { padding: 0 !important; font-size: 0 !important; }
|
|
13890
|
+
.ps-tryon-header-icon-label { display: none !important; }
|
|
13891
|
+
.ps-tryon-header-minimal { gap: 10px !important; }
|
|
13892
|
+
.ps-tryon-powered-by {
|
|
13893
|
+
font-size: 10px !important;
|
|
13894
|
+
letter-spacing: 0.05em !important;
|
|
13895
|
+
}
|
|
13896
|
+
/* Mobile-only header collapse: Profile + History + LangSwitcher move
|
|
13897
|
+
into the hamburger popover. The inline icons render NOTHING on
|
|
13898
|
+
mobile so the header reads "PoweredBy ... [☰] [×]". */
|
|
13899
|
+
.ps-tryon-header-icon-labeled,
|
|
13900
|
+
.ps-tryon-header-minimal > .ps-tryon-lang-trigger { display: none !important; }
|
|
13901
|
+
.ps-tryon-header-mobile-menu-btn {
|
|
13902
|
+
display: flex !important;
|
|
13903
|
+
width: 34px !important; height: 34px !important;
|
|
13904
|
+
border: none !important; background: transparent !important;
|
|
13905
|
+
align-items: center !important; justify-content: center !important;
|
|
13906
|
+
color: var(--ps-text-secondary) !important;
|
|
13907
|
+
padding: 0 !important; cursor: pointer !important;
|
|
13908
|
+
}
|
|
13909
|
+
.ps-tryon-header-mobile-menu-btn:hover { color: var(--ps-accent) !important; }
|
|
13910
|
+
.ps-tryon-header-mobile-backdrop {
|
|
13911
|
+
display: block !important;
|
|
13912
|
+
position: fixed !important; inset: 0 !important;
|
|
13913
|
+
z-index: 2147483646 !important;
|
|
13914
|
+
background: rgba(0,0,0,0.18) !important;
|
|
13915
|
+
}
|
|
13916
|
+
.ps-tryon-header-mobile-menu {
|
|
13917
|
+
display: flex !important;
|
|
13918
|
+
flex-direction: column;
|
|
13919
|
+
position: fixed !important;
|
|
13920
|
+
z-index: 2147483647 !important;
|
|
13921
|
+
min-width: 168px;
|
|
13922
|
+
background: #fff;
|
|
13923
|
+
border-radius: 12px;
|
|
13924
|
+
box-shadow: 0 10px 28px rgba(0,0,0,0.14), 0 1px 2px rgba(0,0,0,0.06);
|
|
13925
|
+
overflow: hidden;
|
|
13926
|
+
animation: ps-tryon-mobile-menu-in 0.18s ease-out both;
|
|
13927
|
+
padding: 4px 0;
|
|
13928
|
+
}
|
|
13929
|
+
@keyframes ps-tryon-mobile-menu-in {
|
|
13930
|
+
from { opacity: 0; transform: translateY(-6px) scale(0.97); }
|
|
13931
|
+
to { opacity: 1; transform: none; }
|
|
13932
|
+
}
|
|
13933
|
+
.ps-tryon-header-mobile-menu-item {
|
|
13934
|
+
display: flex !important; align-items: center; gap: 10px;
|
|
13935
|
+
padding: 11px 14px !important;
|
|
13936
|
+
border: none !important; background: transparent !important;
|
|
13937
|
+
cursor: pointer !important;
|
|
13938
|
+
font: inherit; font-size: 14px !important; font-weight: 500 !important;
|
|
13939
|
+
color: var(--ps-text-primary, #111) !important;
|
|
13940
|
+
text-align: left !important;
|
|
13941
|
+
transition: background 0.15s;
|
|
13942
|
+
}
|
|
13943
|
+
.ps-tryon-header-mobile-menu-item:hover { background: rgba(0,0,0,0.04) !important; }
|
|
13944
|
+
.ps-tryon-header-mobile-menu-item svg {
|
|
13945
|
+
width: 18px !important; height: 18px !important;
|
|
13946
|
+
stroke: currentColor !important; fill: none !important;
|
|
13947
|
+
}
|
|
13948
|
+
.ps-tryon-header-mobile-menu-lang {
|
|
13949
|
+
border-top: 1px solid rgba(0,0,0,0.06);
|
|
13950
|
+
}
|
|
13951
|
+
/* Inside the popover, force the language trigger to match the
|
|
13952
|
+
Profile/History rows: same padding, gap, font-size, icon size. */
|
|
13953
|
+
.ps-tryon-header-mobile-menu-lang .ps-tryon-lang-trigger {
|
|
13954
|
+
display: flex !important;
|
|
13955
|
+
align-items: center !important;
|
|
13956
|
+
gap: 10px !important;
|
|
13957
|
+
width: 100% !important;
|
|
13958
|
+
padding: 11px 14px !important;
|
|
13959
|
+
min-height: 0 !important;
|
|
13960
|
+
border: none !important;
|
|
13961
|
+
background: transparent !important;
|
|
13962
|
+
border-radius: 0 !important;
|
|
13963
|
+
font: inherit !important;
|
|
13964
|
+
font-size: 14px !important;
|
|
13965
|
+
font-weight: 500 !important;
|
|
13966
|
+
color: var(--ps-text-primary, #111) !important;
|
|
13967
|
+
text-align: left !important;
|
|
13968
|
+
cursor: pointer !important;
|
|
13969
|
+
transition: background 0.15s !important;
|
|
13970
|
+
}
|
|
13971
|
+
.ps-tryon-header-mobile-menu-lang .ps-tryon-lang-trigger:hover { background: rgba(0,0,0,0.04) !important; }
|
|
13972
|
+
.ps-tryon-header-mobile-menu-lang .ps-tryon-lang-trigger svg {
|
|
13973
|
+
width: 18px !important; height: 18px !important;
|
|
13974
|
+
flex-shrink: 0 !important;
|
|
13975
|
+
}
|
|
13976
|
+
.ps-tryon-header-mobile-menu-lang .ps-tryon-lang-current {
|
|
13977
|
+
font-size: 14px !important;
|
|
13978
|
+
font-weight: 500 !important;
|
|
13979
|
+
flex: 1;
|
|
13980
|
+
}
|
|
13981
|
+
.ps-tryon-header-mobile-menu-lang .ps-tryon-lang-arrow {
|
|
13982
|
+
margin-left: auto;
|
|
13822
13983
|
}
|
|
13823
|
-
.ps-tryon-header-icon svg { width: 14px !important; height: 14px !important; }
|
|
13824
13984
|
.ps-tryon-close {
|
|
13825
13985
|
width: 24px !important; height: 24px !important;
|
|
13826
13986
|
border: none !important; background: transparent !important;
|
|
@@ -19619,6 +19779,12 @@ function garmentIconForSection(name) {
|
|
|
19619
19779
|
if (n2.includes("vest") || n2.includes("waistcoat") || n2.includes("gilet")) return garmentVestImg;
|
|
19620
19780
|
return null;
|
|
19621
19781
|
}
|
|
19782
|
+
function formatPillLabel(s) {
|
|
19783
|
+
if (!s) return s;
|
|
19784
|
+
const head = s.split("/")[0]?.trim() || s;
|
|
19785
|
+
const tokens = head.split(/\s+/);
|
|
19786
|
+
return tokens[tokens.length - 1] || s;
|
|
19787
|
+
}
|
|
19622
19788
|
const SKELETON_CONNECTIONS = [
|
|
19623
19789
|
["nose", "leftShoulder"],
|
|
19624
19790
|
["nose", "rightShoulder"],
|
|
@@ -19872,7 +20038,7 @@ function MeasurementOverlay({ lines, fitRows, show, imgWidth, imgHeight }) {
|
|
|
19872
20038
|
const x2 = line.x2 * W2;
|
|
19873
20039
|
const cy = line.y * H2;
|
|
19874
20040
|
const width = x2 - x1;
|
|
19875
|
-
const
|
|
20041
|
+
const ellipseRy = width * 0.12;
|
|
19876
20042
|
const midX = (x1 + x2) / 2;
|
|
19877
20043
|
const fitRow = fitRows.find((r2) => {
|
|
19878
20044
|
const a = r2.area.toLowerCase().trim();
|
|
@@ -19882,31 +20048,54 @@ function MeasurementOverlay({ lines, fitRows, show, imgWidth, imgHeight }) {
|
|
|
19882
20048
|
if (key === "hips" && (a.includes("hip") || a === "hips")) return true;
|
|
19883
20049
|
return false;
|
|
19884
20050
|
});
|
|
19885
|
-
|
|
20051
|
+
if (!fitRow) return null;
|
|
20052
|
+
const color = "rgba(255,255,255,0.95)";
|
|
19886
20053
|
const delay = i * 0.35;
|
|
19887
|
-
const
|
|
19888
|
-
const
|
|
20054
|
+
const frontArc = `M ${x1} ${cy} Q ${midX} ${cy + ellipseRy} ${x2} ${cy}`;
|
|
20055
|
+
const backArc = `M ${x1} ${cy} Q ${midX} ${cy - ellipseRy} ${x2} ${cy}`;
|
|
19889
20056
|
const labelText = fitRow ? fitRow.fit === "good" ? "✓ Fit" : fitRow.isLength ? fitRow.fit.includes("short") || fitRow.fit.includes("tight") ? "Short" : "Long" : fitRow.fit.includes("tight") ? "Tight" : "Loose" : label;
|
|
19890
|
-
const labelFont = Math.max(
|
|
20057
|
+
const labelFont = Math.max(26, Math.round(48 * scale));
|
|
19891
20058
|
const labelWidthEst = labelText.length * labelFont * 0.62;
|
|
19892
|
-
const
|
|
19893
|
-
const
|
|
19894
|
-
const
|
|
19895
|
-
const
|
|
20059
|
+
const boxPadX = Math.max(10, Math.round(14 * scale));
|
|
20060
|
+
const boxPadY = Math.max(6, Math.round(10 * scale));
|
|
20061
|
+
const boxW = labelWidthEst + boxPadX * 2;
|
|
20062
|
+
const boxH = labelFont + boxPadY * 2;
|
|
20063
|
+
const armLen = Math.max(28, Math.round(50 * scale));
|
|
20064
|
+
const rightSpace = W2 - x2 - boxW - armLen - 12 * scale;
|
|
20065
|
+
const flipLeft = rightSpace < 0;
|
|
19896
20066
|
const tickX1 = flipLeft ? x1 : x2;
|
|
19897
|
-
const tickX2 = flipLeft ? x1 -
|
|
20067
|
+
const tickX2 = flipLeft ? x1 - armLen : x2 + armLen;
|
|
20068
|
+
const boxX = flipLeft ? tickX2 - boxW : tickX2;
|
|
20069
|
+
const boxY = cy - boxH / 2;
|
|
20070
|
+
const boxFill = fitRow ? fitColor(fitRow.fit) : "rgba(255,255,255,0.95)";
|
|
20071
|
+
const arrowHeadW = Math.max(6, Math.round(10 * scale));
|
|
20072
|
+
const dashLen = Math.max(6, Math.round(8 * scale));
|
|
20073
|
+
const gapLen = Math.max(5, Math.round(7 * scale));
|
|
19898
20074
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("g", { children: [
|
|
20075
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("g", { opacity: "0.45", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20076
|
+
"path",
|
|
20077
|
+
{
|
|
20078
|
+
d: backArc,
|
|
20079
|
+
fill: "none",
|
|
20080
|
+
stroke: color,
|
|
20081
|
+
strokeWidth: strokeW,
|
|
20082
|
+
strokeLinecap: "round",
|
|
20083
|
+
strokeDasharray: `${dashLen} ${gapLen}`,
|
|
20084
|
+
opacity: "0",
|
|
20085
|
+
style: { animation: `ps-pose-fade 0.45s ease ${delay}s forwards` }
|
|
20086
|
+
}
|
|
20087
|
+
) }),
|
|
19899
20088
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19900
20089
|
"path",
|
|
19901
20090
|
{
|
|
19902
|
-
d:
|
|
20091
|
+
d: frontArc,
|
|
19903
20092
|
fill: "none",
|
|
19904
20093
|
stroke: color,
|
|
19905
20094
|
strokeWidth: strokeW,
|
|
19906
20095
|
strokeLinecap: "round",
|
|
19907
|
-
strokeDasharray:
|
|
19908
|
-
|
|
19909
|
-
style: { animation: `ps-pose-
|
|
20096
|
+
strokeDasharray: `${dashLen} ${gapLen}`,
|
|
20097
|
+
opacity: "0",
|
|
20098
|
+
style: { animation: `ps-pose-fade 0.45s ease ${delay + 0.05}s forwards` }
|
|
19910
20099
|
}
|
|
19911
20100
|
),
|
|
19912
20101
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -19917,7 +20106,7 @@ function MeasurementOverlay({ lines, fitRows, show, imgWidth, imgHeight }) {
|
|
|
19917
20106
|
r: dotR,
|
|
19918
20107
|
fill: color,
|
|
19919
20108
|
opacity: "0",
|
|
19920
|
-
style: { animation: `ps-pose-fade 0.3s ease ${delay + 0.
|
|
20109
|
+
style: { animation: `ps-pose-fade 0.3s ease ${delay + 0.4}s forwards` }
|
|
19921
20110
|
}
|
|
19922
20111
|
),
|
|
19923
20112
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
@@ -19928,10 +20117,10 @@ function MeasurementOverlay({ lines, fitRows, show, imgWidth, imgHeight }) {
|
|
|
19928
20117
|
r: dotR,
|
|
19929
20118
|
fill: color,
|
|
19930
20119
|
opacity: "0",
|
|
19931
|
-
style: { animation: `ps-pose-fade 0.3s ease ${delay + 0.
|
|
20120
|
+
style: { animation: `ps-pose-fade 0.3s ease ${delay + 0.4}s forwards` }
|
|
19932
20121
|
}
|
|
19933
20122
|
),
|
|
19934
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("g", { opacity: "0", style: { animation: `ps-pose-fade 0.4s ease ${delay + 0.
|
|
20123
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("g", { opacity: "0", style: { animation: `ps-pose-fade 0.4s ease ${delay + 0.5}s forwards` }, children: [
|
|
19935
20124
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19936
20125
|
"line",
|
|
19937
20126
|
{
|
|
@@ -19940,20 +20129,45 @@ function MeasurementOverlay({ lines, fitRows, show, imgWidth, imgHeight }) {
|
|
|
19940
20129
|
x2: tickX2,
|
|
19941
20130
|
y2: cy,
|
|
19942
20131
|
stroke: color,
|
|
19943
|
-
strokeWidth: 2 * scale
|
|
20132
|
+
strokeWidth: Math.max(2, 2.5 * scale),
|
|
20133
|
+
strokeLinecap: "round"
|
|
20134
|
+
}
|
|
20135
|
+
),
|
|
20136
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20137
|
+
"polygon",
|
|
20138
|
+
{
|
|
20139
|
+
points: flipLeft ? `${tickX2 - arrowHeadW},${cy - arrowHeadW * 0.6} ${tickX2},${cy} ${tickX2 - arrowHeadW},${cy + arrowHeadW * 0.6}` : `${tickX2 + arrowHeadW},${cy - arrowHeadW * 0.6} ${tickX2},${cy} ${tickX2 + arrowHeadW},${cy + arrowHeadW * 0.6}`,
|
|
20140
|
+
fill: color
|
|
20141
|
+
}
|
|
20142
|
+
),
|
|
20143
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20144
|
+
"rect",
|
|
20145
|
+
{
|
|
20146
|
+
x: boxX,
|
|
20147
|
+
y: boxY,
|
|
20148
|
+
width: boxW,
|
|
20149
|
+
height: boxH,
|
|
20150
|
+
rx: boxH / 2,
|
|
20151
|
+
ry: boxH / 2,
|
|
20152
|
+
fill: boxFill,
|
|
20153
|
+
stroke: "rgba(0,0,0,0.18)",
|
|
20154
|
+
strokeWidth: 1
|
|
19944
20155
|
}
|
|
19945
20156
|
),
|
|
19946
20157
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19947
20158
|
"text",
|
|
19948
20159
|
{
|
|
19949
|
-
x:
|
|
20160
|
+
x: boxX + boxW / 2,
|
|
19950
20161
|
y: cy + 1 * scale,
|
|
19951
|
-
fill:
|
|
20162
|
+
fill: "#FFFFFF",
|
|
19952
20163
|
fontSize: labelFont,
|
|
19953
|
-
fontWeight: "
|
|
20164
|
+
fontWeight: "800",
|
|
19954
20165
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
19955
20166
|
dominantBaseline: "middle",
|
|
19956
|
-
textAnchor:
|
|
20167
|
+
textAnchor: "middle",
|
|
20168
|
+
stroke: "rgba(0,0,0,0.35)",
|
|
20169
|
+
strokeWidth: Math.max(2, scale * 2),
|
|
20170
|
+
paintOrder: "stroke",
|
|
19957
20171
|
children: labelText
|
|
19958
20172
|
}
|
|
19959
20173
|
)
|
|
@@ -20091,7 +20305,22 @@ function SectionDetailView({
|
|
|
20091
20305
|
const raw = section.rows.map((r2) => cellValFn(r2, sizeColIdx, sizeHeader)).filter(Boolean);
|
|
20092
20306
|
return [...new Set(raw)];
|
|
20093
20307
|
}, [section, sizeColIdx, sizeHeader]);
|
|
20094
|
-
const displaySize =
|
|
20308
|
+
const displaySize = reactExports.useMemo(() => {
|
|
20309
|
+
const stripLen = (s) => {
|
|
20310
|
+
if (!s) return s;
|
|
20311
|
+
const head = (s.split("/")[0] ?? s).trim();
|
|
20312
|
+
const tokens = head.split(/\s+/);
|
|
20313
|
+
return tokens[tokens.length - 1] || s;
|
|
20314
|
+
};
|
|
20315
|
+
const sizeBase = selectedSize || recSize;
|
|
20316
|
+
if (!sizeBase || !selectedLength || !allSizes) return sizeBase;
|
|
20317
|
+
const baseBare = stripLen(sizeBase);
|
|
20318
|
+
const lengthLower = selectedLength.toLowerCase().trim();
|
|
20319
|
+
const match = Object.keys(allSizes).find(
|
|
20320
|
+
(k2) => stripLen(k2) === baseBare && k2.toLowerCase().includes(lengthLower)
|
|
20321
|
+
);
|
|
20322
|
+
return match || sizeBase;
|
|
20323
|
+
}, [selectedSize, recSize, selectedLength, allSizes]);
|
|
20095
20324
|
const isRecommended = displaySize === recSize;
|
|
20096
20325
|
reactExports.useMemo(() => {
|
|
20097
20326
|
if (isRecommended) return null;
|
|
@@ -20100,7 +20329,21 @@ function SectionDetailView({
|
|
|
20100
20329
|
const hasBadFit = details.some((d) => BAD_FIT.test(d.fit || ""));
|
|
20101
20330
|
return hasBadFit ? t2("Not Recommended") : t2("Your Selection");
|
|
20102
20331
|
}, [isRecommended, sectionResult, t2]);
|
|
20103
|
-
const
|
|
20332
|
+
const sizeFitPrefix = (() => {
|
|
20333
|
+
const target = displaySize?.toString().trim();
|
|
20334
|
+
if (!target || !section.headers?.length || !section.rows?.length) return "";
|
|
20335
|
+
const row = section.rows.find((r2) => (r2[0] ?? "").toString().trim() === target);
|
|
20336
|
+
if (!row) return "";
|
|
20337
|
+
for (let i = 1; i < section.headers.length; i++) {
|
|
20338
|
+
const h = section.headers[i] || "";
|
|
20339
|
+
const v2 = row[i];
|
|
20340
|
+
if (/^(fit|silhouette|category|body[\s_]?type)$/i.test(h) && v2 != null && String(v2).trim()) {
|
|
20341
|
+
return String(v2).trim();
|
|
20342
|
+
}
|
|
20343
|
+
}
|
|
20344
|
+
return "";
|
|
20345
|
+
})();
|
|
20346
|
+
const displaySizeLabel = selectedCountry && isRecommended && internationalSizes && internationalSizes[selectedCountry] ? internationalSizes[selectedCountry] : sizeFitPrefix ? `${sizeFitPrefix} ${displaySize}` : displaySize;
|
|
20104
20347
|
const columnUnits = reactExports.useMemo(() => {
|
|
20105
20348
|
const units = [];
|
|
20106
20349
|
for (let i = 0; i < section.headers.length; i++) {
|
|
@@ -20186,16 +20429,17 @@ function SectionDetailView({
|
|
|
20186
20429
|
const uNum = pNumFn(m2.userValue);
|
|
20187
20430
|
if (uNum > 0) {
|
|
20188
20431
|
const rMin = alt.min, rMax = alt.max;
|
|
20189
|
-
const
|
|
20190
|
-
const
|
|
20191
|
-
const
|
|
20432
|
+
const isCm = /\bcm\b/i.test(rawChartRange);
|
|
20433
|
+
const aBitTol = isCm ? 1.27 : 0.5;
|
|
20434
|
+
const tooFarTol = isCm ? 5.08 : 2;
|
|
20435
|
+
const tol = Math.max((rMax || rMin) * 5e-3, isCm ? 0.25 : 0.1);
|
|
20192
20436
|
if (uNum >= rMin - tol && uNum <= rMax + tol) fit = "good";
|
|
20193
20437
|
else if (uNum < rMin) {
|
|
20194
20438
|
const d = rMin - uNum;
|
|
20195
|
-
fit = d >
|
|
20439
|
+
fit = d > tooFarTol ? "too-loose" : d > aBitTol ? "loose" : "a-bit-loose";
|
|
20196
20440
|
} else {
|
|
20197
20441
|
const d = uNum - rMax;
|
|
20198
|
-
fit = d >
|
|
20442
|
+
fit = d > tooFarTol ? "too-tight" : d > aBitTol ? "tight" : "a-bit-tight";
|
|
20199
20443
|
}
|
|
20200
20444
|
}
|
|
20201
20445
|
}
|
|
@@ -20291,20 +20535,85 @@ function SectionDetailView({
|
|
|
20291
20535
|
(m2) => /inseam|length/i.test(m2.measurement) && !/neck|arm|sleeve|back|shoulder/i.test(m2.measurement)
|
|
20292
20536
|
);
|
|
20293
20537
|
const inseamFallback = lengthFromDetails ? (lengthFromDetails.chartRange || "").replace(/\s*(cm|in|inches)\s*/i, "").trim() : "";
|
|
20294
|
-
const
|
|
20538
|
+
const recLengthFromSuffix = (() => {
|
|
20539
|
+
const r2 = String(recSize || "");
|
|
20540
|
+
const slash = r2.indexOf("/");
|
|
20541
|
+
return slash > 0 ? r2.slice(slash + 1).trim() : "";
|
|
20542
|
+
})();
|
|
20543
|
+
const backendLength = secAny?.length || recLength || recLengthFromSuffix || inseamFallback;
|
|
20295
20544
|
const backendAvailableSizes = secAny?.availableSizes || [];
|
|
20296
20545
|
const backendAvailableLengths = secAny?.availableLengths || [];
|
|
20297
20546
|
const finalDisplayLength = selectedLength || backendLength;
|
|
20298
20547
|
const allSizesKeys = allSizes ? Object.keys(allSizes) : [];
|
|
20299
|
-
const
|
|
20548
|
+
const stripLengthVariant = (s) => {
|
|
20549
|
+
if (!s) return s;
|
|
20550
|
+
const head = (s.split("/")[0] ?? s).trim();
|
|
20551
|
+
const tokens = head.split(/\s+/);
|
|
20552
|
+
return tokens[tokens.length - 1] || s;
|
|
20553
|
+
};
|
|
20554
|
+
const SIZE_LETTER_ORDER = {
|
|
20555
|
+
XXS: 0,
|
|
20556
|
+
XS: 1,
|
|
20557
|
+
S: 2,
|
|
20558
|
+
M: 3,
|
|
20559
|
+
L: 4,
|
|
20560
|
+
XL: 5,
|
|
20561
|
+
XXL: 6,
|
|
20562
|
+
"2XL": 6,
|
|
20563
|
+
XXXL: 7,
|
|
20564
|
+
"3XL": 7,
|
|
20565
|
+
"4XL": 8,
|
|
20566
|
+
"5XL": 9,
|
|
20567
|
+
"6XL": 10
|
|
20568
|
+
};
|
|
20569
|
+
const compareSizes = (a, b) => {
|
|
20570
|
+
const numA = parseFloat(a);
|
|
20571
|
+
const numB = parseFloat(b);
|
|
20572
|
+
if (!isNaN(numA) && !isNaN(numB)) {
|
|
20573
|
+
if (numA !== numB) return numA - numB;
|
|
20574
|
+
return a.localeCompare(b);
|
|
20575
|
+
}
|
|
20576
|
+
const oa2 = SIZE_LETTER_ORDER[a.toUpperCase()];
|
|
20577
|
+
const ob2 = SIZE_LETTER_ORDER[b.toUpperCase()];
|
|
20578
|
+
if (oa2 != null && ob2 != null) return oa2 - ob2;
|
|
20579
|
+
if (oa2 != null) return -1;
|
|
20580
|
+
if (ob2 != null) return 1;
|
|
20581
|
+
return a.localeCompare(b);
|
|
20582
|
+
};
|
|
20583
|
+
const dedupedSizes = (() => {
|
|
20584
|
+
const lengthLower = String(finalDisplayLength ?? "").toLowerCase().trim();
|
|
20585
|
+
const out = /* @__PURE__ */ new Map();
|
|
20586
|
+
for (const k2 of allSizesKeys) {
|
|
20587
|
+
const bare = stripLengthVariant(k2);
|
|
20588
|
+
if (!out.has(bare)) {
|
|
20589
|
+
out.set(bare, k2);
|
|
20590
|
+
} else if (lengthLower && k2.toLowerCase().includes(lengthLower)) {
|
|
20591
|
+
out.set(bare, k2);
|
|
20592
|
+
}
|
|
20593
|
+
}
|
|
20594
|
+
return Array.from(out.entries()).sort(([a], [b]) => compareSizes(a, b)).map(([, full]) => full);
|
|
20595
|
+
})();
|
|
20596
|
+
const finalAllSizes = dedupedSizes.length > 0 ? dedupedSizes : backendAvailableSizes.length > 0 ? backendAvailableSizes : chartSizes;
|
|
20300
20597
|
const visibleSizes = (() => {
|
|
20301
20598
|
if (finalAllSizes.length <= 3) return finalAllSizes;
|
|
20302
|
-
const
|
|
20599
|
+
const recBare = stripLengthVariant(recSize || "");
|
|
20600
|
+
const idx = finalAllSizes.findIndex((k2) => stripLengthVariant(k2) === recBare);
|
|
20303
20601
|
if (idx < 0) return finalAllSizes.slice(0, 3);
|
|
20304
20602
|
const start = Math.max(0, Math.min(finalAllSizes.length - 3, idx - 1));
|
|
20305
20603
|
return finalAllSizes.slice(start, start + 3);
|
|
20306
20604
|
})();
|
|
20307
|
-
const
|
|
20605
|
+
const derivedLengths = (() => {
|
|
20606
|
+
const out = /* @__PURE__ */ new Set();
|
|
20607
|
+
for (const k2 of allSizesKeys) {
|
|
20608
|
+
const slash = k2.indexOf("/");
|
|
20609
|
+
if (slash > 0) {
|
|
20610
|
+
const tail = k2.slice(slash + 1).trim();
|
|
20611
|
+
if (tail) out.add(tail);
|
|
20612
|
+
}
|
|
20613
|
+
}
|
|
20614
|
+
return Array.from(out);
|
|
20615
|
+
})();
|
|
20616
|
+
const lengthOptions = backendAvailableLengths.length > 0 ? backendAvailableLengths : derivedLengths.length > 0 ? derivedLengths : lengthSizes;
|
|
20308
20617
|
const visibleLengths = (() => {
|
|
20309
20618
|
if (lengthOptions.length <= 3) return lengthOptions;
|
|
20310
20619
|
const idx = lengthOptions.indexOf(backendLength);
|
|
@@ -20503,14 +20812,14 @@ function SectionDetailView({
|
|
|
20503
20812
|
sectionFound !== false && visibleSizes.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msd-sizes", children: [
|
|
20504
20813
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-sizes-label", children: t2("TRY ANOTHER SIZE") }),
|
|
20505
20814
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msd-sizes-pills", children: visibleSizes.map((s) => {
|
|
20506
|
-
const isActive = s === displaySize;
|
|
20815
|
+
const isActive = stripLengthVariant(s) === stripLengthVariant(displaySize || "");
|
|
20507
20816
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20508
20817
|
"button",
|
|
20509
20818
|
{
|
|
20510
20819
|
type: "button",
|
|
20511
20820
|
className: `ps-msd-size-pill${isActive ? " ps-active" : ""}`,
|
|
20512
|
-
onClick: () => setSelectedSize(s === recSize ? null : s),
|
|
20513
|
-
children: s
|
|
20821
|
+
onClick: () => setSelectedSize(stripLengthVariant(s) === stripLengthVariant(recSize || "") ? null : s),
|
|
20822
|
+
children: formatPillLabel(s)
|
|
20514
20823
|
},
|
|
20515
20824
|
s
|
|
20516
20825
|
);
|
|
@@ -20743,11 +21052,11 @@ function SectionDetailView({
|
|
|
20743
21052
|
t2("Size")
|
|
20744
21053
|
] }),
|
|
20745
21054
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { display: "flex", gap: "0.3vw", flexWrap: "wrap" }, children: visibleSizes.map((s) => {
|
|
20746
|
-
const isActive = s === displaySize;
|
|
21055
|
+
const isActive = stripLengthVariant(s) === stripLengthVariant(displaySize || "");
|
|
20747
21056
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
20748
21057
|
"button",
|
|
20749
21058
|
{
|
|
20750
|
-
onClick: () => setSelectedSize(s === recSize ? null : s),
|
|
21059
|
+
onClick: () => setSelectedSize(stripLengthVariant(s) === stripLengthVariant(recSize || "") ? null : s),
|
|
20751
21060
|
style: {
|
|
20752
21061
|
padding: "0.35vw 0.7vw",
|
|
20753
21062
|
borderRadius: "0.35vw",
|
|
@@ -20762,7 +21071,7 @@ function SectionDetailView({
|
|
|
20762
21071
|
minWidth: "2vw",
|
|
20763
21072
|
textAlign: "center"
|
|
20764
21073
|
},
|
|
20765
|
-
children: s
|
|
21074
|
+
children: formatPillLabel(s)
|
|
20766
21075
|
},
|
|
20767
21076
|
s
|
|
20768
21077
|
);
|
|
@@ -22920,10 +23229,20 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
22920
23229
|
};
|
|
22921
23230
|
}, [imageStep, photoBase64]);
|
|
22922
23231
|
reactExports.useEffect(() => {
|
|
22923
|
-
if (imageStep !== "calculating"
|
|
22924
|
-
|
|
22925
|
-
|
|
22926
|
-
|
|
23232
|
+
if (imageStep !== "calculating") return;
|
|
23233
|
+
setScanStageIdx(0);
|
|
23234
|
+
}, [imageStep]);
|
|
23235
|
+
reactExports.useEffect(() => {
|
|
23236
|
+
if (imageStep !== "calculating") return;
|
|
23237
|
+
const STAGE_DWELL_MS = 1800;
|
|
23238
|
+
const TOTAL_STAGES = 5;
|
|
23239
|
+
if (scanStageIdx >= TOTAL_STAGES - 1) return;
|
|
23240
|
+
const id2 = setTimeout(
|
|
23241
|
+
() => setScanStageIdx((i) => Math.min(TOTAL_STAGES - 1, i + 1)),
|
|
23242
|
+
STAGE_DWELL_MS
|
|
23243
|
+
);
|
|
23244
|
+
return () => clearTimeout(id2);
|
|
23245
|
+
}, [imageStep, scanStageIdx]);
|
|
22927
23246
|
const photoInputRef = reactExports.useRef(null);
|
|
22928
23247
|
const nameInputRef = reactExports.useRef(null);
|
|
22929
23248
|
const [nameShaking, setNameShaking] = reactExports.useState(false);
|
|
@@ -23190,6 +23509,7 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23190
23509
|
setError(t2("Please enter a valid weight"));
|
|
23191
23510
|
return;
|
|
23192
23511
|
}
|
|
23512
|
+
const a = parseFloat(ageVal);
|
|
23193
23513
|
if (isWomen && (!bandSize || !cupSize)) {
|
|
23194
23514
|
setError(t2("Please select your bra band and cup size"));
|
|
23195
23515
|
return;
|
|
@@ -23197,9 +23517,10 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23197
23517
|
setError("");
|
|
23198
23518
|
setImageStep("calculating");
|
|
23199
23519
|
setEstimating(true);
|
|
23520
|
+
const MIN_HOLD_MS = 6e3;
|
|
23521
|
+
const minHold = new Promise((r2) => setTimeout(r2, MIN_HOLD_MS));
|
|
23200
23522
|
if (onEstimate && photoBase64) {
|
|
23201
23523
|
const heightRaw = unit === "in" ? (parseInt(heightFt, 10) || 0) * 12 + (parseInt(heightInch, 10) || 0) : parseFloat(heightVal);
|
|
23202
|
-
const a = parseFloat(ageVal);
|
|
23203
23524
|
try {
|
|
23204
23525
|
const result = await onEstimate({
|
|
23205
23526
|
photoBase64,
|
|
@@ -23216,7 +23537,9 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23216
23537
|
} catch {
|
|
23217
23538
|
}
|
|
23218
23539
|
}
|
|
23540
|
+
await minHold;
|
|
23219
23541
|
setEstimating(false);
|
|
23542
|
+
setImageStep("name-photo");
|
|
23220
23543
|
return;
|
|
23221
23544
|
}
|
|
23222
23545
|
if (imageStep === "details") {
|
|
@@ -23460,7 +23783,8 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23460
23783
|
setCupSize(null);
|
|
23461
23784
|
setInlineBraOpen(null);
|
|
23462
23785
|
setError("");
|
|
23463
|
-
}
|
|
23786
|
+
},
|
|
23787
|
+
direction: "up"
|
|
23464
23788
|
}
|
|
23465
23789
|
) })
|
|
23466
23790
|
] }),
|
|
@@ -23478,7 +23802,8 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23478
23802
|
setBandSize(v2);
|
|
23479
23803
|
setInlineBraOpen(null);
|
|
23480
23804
|
setError("");
|
|
23481
|
-
}
|
|
23805
|
+
},
|
|
23806
|
+
direction: "up"
|
|
23482
23807
|
}
|
|
23483
23808
|
) })
|
|
23484
23809
|
] }),
|
|
@@ -23496,7 +23821,8 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
23496
23821
|
setCupSize(v2);
|
|
23497
23822
|
setInlineBraOpen(null);
|
|
23498
23823
|
setError("");
|
|
23499
|
-
}
|
|
23824
|
+
},
|
|
23825
|
+
direction: "up"
|
|
23500
23826
|
}
|
|
23501
23827
|
) })
|
|
23502
23828
|
] })
|
|
@@ -24025,7 +24351,8 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24025
24351
|
setBandSize(null);
|
|
24026
24352
|
setCupSize(null);
|
|
24027
24353
|
setInlineBraOpen(null);
|
|
24028
|
-
}
|
|
24354
|
+
},
|
|
24355
|
+
direction: "up"
|
|
24029
24356
|
}
|
|
24030
24357
|
) })
|
|
24031
24358
|
] }),
|
|
@@ -24042,7 +24369,8 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24042
24369
|
onSelect: (v2) => {
|
|
24043
24370
|
setBandSize(v2);
|
|
24044
24371
|
setInlineBraOpen(null);
|
|
24045
|
-
}
|
|
24372
|
+
},
|
|
24373
|
+
direction: "up"
|
|
24046
24374
|
}
|
|
24047
24375
|
) })
|
|
24048
24376
|
] }),
|
|
@@ -24189,16 +24517,6 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24189
24517
|
} }),
|
|
24190
24518
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-inline-unit", children: unit === "in" ? "lbs" : "kg" })
|
|
24191
24519
|
] })
|
|
24192
|
-
] }),
|
|
24193
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-inline-row", children: [
|
|
24194
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-inline-label", children: t2("AGE") }),
|
|
24195
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-inline-input-group", children: [
|
|
24196
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "number", inputMode: "numeric", className: "ps-bp-inline-input", value: ageVal, placeholder: t2("e.g. 30"), onChange: (e) => {
|
|
24197
|
-
setAgeVal(e.target.value);
|
|
24198
|
-
setError("");
|
|
24199
|
-
} }),
|
|
24200
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-inline-unit", children: t2("years") })
|
|
24201
|
-
] })
|
|
24202
24520
|
] })
|
|
24203
24521
|
] }),
|
|
24204
24522
|
error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error })
|
|
@@ -24206,12 +24524,12 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24206
24524
|
mode === "image" && imageStep === "calculating" && (() => {
|
|
24207
24525
|
const stages = [
|
|
24208
24526
|
{ title: t2("DETECTING POSE"), desc: t2("Identifying body landmarks from your photo.") },
|
|
24209
|
-
{ title: t2("SCANNING FRAME"), desc: t2("
|
|
24527
|
+
{ title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions to calculate the perfect fit.") },
|
|
24210
24528
|
{ title: t2("ANALYZING BODY"), desc: t2("Measuring shoulders, chest, waist and hips.") },
|
|
24211
|
-
{ title: t2("
|
|
24212
|
-
{ title: t2("FINALIZING"), desc: t2("Almost done — preparing your
|
|
24529
|
+
{ title: t2("MATCHING SIZE"), desc: t2("Comparing your measurements to the size guide.") },
|
|
24530
|
+
{ title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation.") }
|
|
24213
24531
|
];
|
|
24214
|
-
const stage = stages[scanStageIdx
|
|
24532
|
+
const stage = stages[Math.min(scanStageIdx, stages.length - 1)] ?? stages[0];
|
|
24215
24533
|
const SKELETON_CONNECTIONS2 = [
|
|
24216
24534
|
["leftShoulder", "rightShoulder"],
|
|
24217
24535
|
["leftShoulder", "leftElbow"],
|
|
@@ -24342,11 +24660,13 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24342
24660
|
mode === "image" && imageStep === "name-photo" && (() => {
|
|
24343
24661
|
const heightOk = unit === "in" ? parseFloat(heightFt) > 0 || parseFloat(heightInch) > 0 : parseFloat(heightVal) > 0;
|
|
24344
24662
|
const weightOk = parseFloat(weightVal) > 0;
|
|
24663
|
+
const braOk = !isWomen || !!bandSize && !!cupSize;
|
|
24345
24664
|
const nameOk = !!name.trim();
|
|
24346
24665
|
const photoOk = !!photoBase64;
|
|
24347
24666
|
const analyzing = photoUploading;
|
|
24348
|
-
const
|
|
24349
|
-
const
|
|
24667
|
+
const reviewMode = !!estimateResults;
|
|
24668
|
+
const label = analyzing ? t2("Analyzing photo…") : !photoOk ? t2("Upload a photo") : !nameOk ? t2("Add a name for this profile") : !heightOk ? t2("Enter your height") : !weightOk ? t2("Enter your weight") : !braOk ? t2("Select bra band and cup") : reviewMode ? t2("Save Profile") : t2("Calculate My Body Parts");
|
|
24669
|
+
const disabled = analyzing || !photoOk || !nameOk || !heightOk || !weightOk || !braOk;
|
|
24350
24670
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
24351
24671
|
"button",
|
|
24352
24672
|
{
|
|
@@ -24358,6 +24678,15 @@ function CreateProfileWizard({ onSave, onCancel, apiUrl, apiKey, onPhotoPreview,
|
|
|
24358
24678
|
nameInputRef.current?.focus();
|
|
24359
24679
|
return;
|
|
24360
24680
|
}
|
|
24681
|
+
if (reviewMode) {
|
|
24682
|
+
const payload = buildImagePayload();
|
|
24683
|
+
if (estimateResults) {
|
|
24684
|
+
payload.measurements = estimateResults;
|
|
24685
|
+
payload.measurementsUnit = "cm";
|
|
24686
|
+
}
|
|
24687
|
+
onSave(payload);
|
|
24688
|
+
return;
|
|
24689
|
+
}
|
|
24361
24690
|
advanceImage();
|
|
24362
24691
|
},
|
|
24363
24692
|
disabled,
|
|
@@ -25619,15 +25948,31 @@ function BodyProfileView({
|
|
|
25619
25948
|
const [hipProfile, setHipProfile] = reactExports.useState(null);
|
|
25620
25949
|
const [seatProfile, setSeatProfile] = reactExports.useState(null);
|
|
25621
25950
|
const [hoverDesc, setHoverDesc] = reactExports.useState("");
|
|
25622
|
-
const
|
|
25623
|
-
const
|
|
25951
|
+
const seedBand = activeProfile?.bandSize ?? null;
|
|
25952
|
+
const seedCup = activeProfile?.cupSize ?? null;
|
|
25953
|
+
const seedRegion = activeProfile?.braSizeRegion ?? activeProfile?.braRegion ?? null;
|
|
25954
|
+
const [bandSize, setBandSize] = reactExports.useState(seedBand);
|
|
25955
|
+
const [cupSize, setCupSize] = reactExports.useState(seedCup);
|
|
25624
25956
|
const [braSizeRegion, setBraSizeRegion] = reactExports.useState(() => {
|
|
25957
|
+
if (seedRegion) return seedRegion;
|
|
25625
25958
|
if (["US", "UK", "AU"].includes(sizingCountry)) return sizingCountry === "AU" ? "UK" : sizingCountry;
|
|
25626
25959
|
if (["FR", "ES"].includes(sizingCountry)) return "FR";
|
|
25627
25960
|
if (["IT"].includes(sizingCountry)) return "IT";
|
|
25628
25961
|
if (["JP", "CN", "KR"].includes(sizingCountry)) return "JP";
|
|
25629
25962
|
return "EU";
|
|
25630
25963
|
});
|
|
25964
|
+
const seededBraProfileIdRef = reactExports.useRef(null);
|
|
25965
|
+
reactExports.useEffect(() => {
|
|
25966
|
+
const id2 = activeProfile?.id ?? null;
|
|
25967
|
+
if (!id2 || seededBraProfileIdRef.current === id2) return;
|
|
25968
|
+
seededBraProfileIdRef.current = id2;
|
|
25969
|
+
const b = activeProfile?.bandSize;
|
|
25970
|
+
const c = activeProfile?.cupSize;
|
|
25971
|
+
const r2 = activeProfile?.braSizeRegion ?? activeProfile?.braRegion;
|
|
25972
|
+
if (b) setBandSize(b);
|
|
25973
|
+
if (c) setCupSize(c);
|
|
25974
|
+
if (r2) setBraSizeRegion(r2);
|
|
25975
|
+
}, [activeProfile]);
|
|
25631
25976
|
const [braRegionOpen, setBraRegionOpen] = reactExports.useState(false);
|
|
25632
25977
|
const [inlineBraOpen, setInlineBraOpen] = reactExports.useState(null);
|
|
25633
25978
|
const inlineBraWrapRef = reactExports.useRef(null);
|
|
@@ -26522,12 +26867,7 @@ function BodyProfileView({
|
|
|
26522
26867
|
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${isImperialMode ? " ps-bp-system-active" : ""}`, onClick: photoSwitchToImperial, type: "button", children: t2("Imperial") })
|
|
26523
26868
|
] }),
|
|
26524
26869
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: "auto", marginBottom: "auto" }, children: [
|
|
26525
|
-
|
|
26526
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-loaded-pill-dot", "aria-hidden": "true", children: "✓" }),
|
|
26527
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-loaded-pill-text", children: t2("Loaded from profile") }),
|
|
26528
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-loaded-pill-clear", onClick: handleClearFromProfile, children: t2("Clear") })
|
|
26529
|
-
] }) }),
|
|
26530
|
-
hasActiveProfileWithMeasurements && activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", style: { textAlign: "center", margin: "0 0 0.5vw" }, children: [
|
|
26870
|
+
activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", style: { textAlign: "center", margin: "0 0 0.5vw" }, children: [
|
|
26531
26871
|
t2("Using"),
|
|
26532
26872
|
" ",
|
|
26533
26873
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
|
|
@@ -26825,7 +27165,7 @@ function BodyProfileView({
|
|
|
26825
27165
|
onNext: hasActiveProfileWithMeasurements && onUseActiveProfile ? onUseActiveProfile : handleNext,
|
|
26826
27166
|
canProceed: true,
|
|
26827
27167
|
fastPathLabel: hasActiveProfileWithMeasurements ? t2("Find My Best Fit") + (getUnitLabel(hUnit) ? ` (${getUnitLabel(hUnit)})` : "") : void 0,
|
|
26828
|
-
activeProfileName:
|
|
27168
|
+
activeProfileName: activeProfileName ?? null,
|
|
26829
27169
|
onStartFresh,
|
|
26830
27170
|
error,
|
|
26831
27171
|
t: t2
|
|
@@ -26835,13 +27175,13 @@ function BodyProfileView({
|
|
|
26835
27175
|
}
|
|
26836
27176
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-step ps-bp-step-enter", children: [
|
|
26837
27177
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-bp-title", children: t2("Body Measurements") }),
|
|
26838
|
-
|
|
27178
|
+
activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", style: { textAlign: "center", margin: "0 0 0.5vw" }, children: [
|
|
26839
27179
|
t2("Using"),
|
|
26840
27180
|
" ",
|
|
26841
27181
|
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
|
|
26842
27182
|
onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
26843
27183
|
" · ",
|
|
26844
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-hint-link", onClick:
|
|
27184
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-hint-link", onClick: handleClearFromProfile, children: t2("start fresh") })
|
|
26845
27185
|
] })
|
|
26846
27186
|
] }),
|
|
26847
27187
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-system-toggle", children: [
|
|
@@ -28172,6 +28512,10 @@ function PrimeStyleTryonInner({
|
|
|
28172
28512
|
const [estimationLoading, setEstimationLoading] = reactExports.useState(false);
|
|
28173
28513
|
const [profiles, setProfiles] = reactExports.useState(() => lsGet("profiles", []));
|
|
28174
28514
|
const [history, setHistory] = reactExports.useState(() => lsGet("history", []));
|
|
28515
|
+
const [mobileMenuOpen, setMobileMenuOpen] = reactExports.useState(false);
|
|
28516
|
+
const mobileMenuBtnRef = reactExports.useRef(null);
|
|
28517
|
+
const [restoredProductImage, setRestoredProductImage] = reactExports.useState(null);
|
|
28518
|
+
const [restoredProductTitle, setRestoredProductTitle] = reactExports.useState(null);
|
|
28175
28519
|
const [activeProfileId, setActiveProfileIdState] = reactExports.useState(() => getActiveProfileId());
|
|
28176
28520
|
const [estimatingProfileIds, setEstimatingProfileIds] = reactExports.useState(() => /* @__PURE__ */ new Set());
|
|
28177
28521
|
const [deleteConfirmId, setDeleteConfirmId] = reactExports.useState(null);
|
|
@@ -28313,18 +28657,25 @@ function PrimeStyleTryonInner({
|
|
|
28313
28657
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
28314
28658
|
};
|
|
28315
28659
|
}, [previewUrl]);
|
|
28660
|
+
const lockedScrollRef = reactExports.useRef(null);
|
|
28316
28661
|
reactExports.useEffect(() => {
|
|
28317
|
-
|
|
28318
|
-
|
|
28319
|
-
|
|
28320
|
-
|
|
28662
|
+
const isOpen = view !== "idle";
|
|
28663
|
+
if (isOpen && lockedScrollRef.current == null) {
|
|
28664
|
+
lockedScrollRef.current = {
|
|
28665
|
+
scrollY: window.scrollY,
|
|
28666
|
+
prevOverflow: document.body.style.overflow,
|
|
28667
|
+
prevOverscroll: document.body.style.overscrollBehavior
|
|
28668
|
+
};
|
|
28321
28669
|
document.body.style.overflow = "hidden";
|
|
28322
28670
|
document.body.style.overscrollBehavior = "none";
|
|
28323
|
-
return
|
|
28324
|
-
|
|
28325
|
-
|
|
28326
|
-
|
|
28327
|
-
|
|
28671
|
+
return;
|
|
28672
|
+
}
|
|
28673
|
+
if (!isOpen && lockedScrollRef.current != null) {
|
|
28674
|
+
const { scrollY, prevOverflow, prevOverscroll } = lockedScrollRef.current;
|
|
28675
|
+
lockedScrollRef.current = null;
|
|
28676
|
+
document.body.style.overflow = prevOverflow;
|
|
28677
|
+
document.body.style.overscrollBehavior = prevOverscroll;
|
|
28678
|
+
window.scrollTo(0, scrollY);
|
|
28328
28679
|
}
|
|
28329
28680
|
}, [view]);
|
|
28330
28681
|
reactExports.useEffect(() => {
|
|
@@ -28524,16 +28875,15 @@ function PrimeStyleTryonInner({
|
|
|
28524
28875
|
onOpen?.();
|
|
28525
28876
|
}, [onOpen]);
|
|
28526
28877
|
const handleClose = reactExports.useCallback(() => {
|
|
28878
|
+
const tryOnInFlight = tryOnProcessing;
|
|
28527
28879
|
setView("idle");
|
|
28528
28880
|
setSelectedFile(null);
|
|
28529
28881
|
setDrawer(null);
|
|
28530
28882
|
setProfileDetail(null);
|
|
28531
28883
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
28532
28884
|
setPreviewUrl(null);
|
|
28533
|
-
setResultImageUrl(null);
|
|
28534
28885
|
setErrorMessage(null);
|
|
28535
28886
|
setSizingMethod(null);
|
|
28536
|
-
setSizingResult(null);
|
|
28537
28887
|
setSizingLoading(false);
|
|
28538
28888
|
setEstimatedValues(null);
|
|
28539
28889
|
setEstimationLoading(false);
|
|
@@ -28541,15 +28891,19 @@ function PrimeStyleTryonInner({
|
|
|
28541
28891
|
setProfileSaved(false);
|
|
28542
28892
|
formRef.current = {};
|
|
28543
28893
|
setFormGender("male");
|
|
28544
|
-
|
|
28545
|
-
|
|
28546
|
-
|
|
28547
|
-
|
|
28548
|
-
|
|
28549
|
-
|
|
28894
|
+
if (!tryOnInFlight) {
|
|
28895
|
+
setResultImageUrl(null);
|
|
28896
|
+
setSizingResult(null);
|
|
28897
|
+
historySavedRef.current = false;
|
|
28898
|
+
unsubRef.current?.();
|
|
28899
|
+
unsubRef.current = null;
|
|
28900
|
+
if (pollingRef.current) {
|
|
28901
|
+
clearInterval(pollingRef.current);
|
|
28902
|
+
pollingRef.current = null;
|
|
28903
|
+
}
|
|
28550
28904
|
}
|
|
28551
28905
|
onClose?.();
|
|
28552
|
-
}, [onClose, previewUrl]);
|
|
28906
|
+
}, [onClose, previewUrl, tryOnProcessing]);
|
|
28553
28907
|
const handleBack = reactExports.useCallback(() => {
|
|
28554
28908
|
if (drawer) {
|
|
28555
28909
|
setDrawer(null);
|
|
@@ -28937,6 +29291,8 @@ function PrimeStyleTryonInner({
|
|
|
28937
29291
|
if (hipProfile) formRef.current.hipProfile = hipProfile;
|
|
28938
29292
|
setSizingResult(null);
|
|
28939
29293
|
setResultImageUrl(null);
|
|
29294
|
+
setRestoredProductImage(null);
|
|
29295
|
+
setRestoredProductTitle(null);
|
|
28940
29296
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
28941
29297
|
setSelectedFile(null);
|
|
28942
29298
|
selectedFileRef.current = null;
|
|
@@ -28969,6 +29325,14 @@ function PrimeStyleTryonInner({
|
|
|
28969
29325
|
selectedFileRef.current = data.photoFile;
|
|
28970
29326
|
const objUrl = data.photoFile ? URL.createObjectURL(data.photoFile) : data.photoBase64.startsWith("data:") ? data.photoBase64 : `data:image/jpeg;base64,${data.photoBase64}`;
|
|
28971
29327
|
setPreviewUrl(objUrl);
|
|
29328
|
+
formRef.current.height = String(data.height);
|
|
29329
|
+
formRef.current.weight = String(data.weight);
|
|
29330
|
+
formRef.current.heightUnit = data.heightUnit;
|
|
29331
|
+
formRef.current.weightUnit = data.weightUnit;
|
|
29332
|
+
formRef.current.gender = data.gender;
|
|
29333
|
+
if (data.age != null) formRef.current.age = String(data.age);
|
|
29334
|
+
setRestoredProductImage(null);
|
|
29335
|
+
setRestoredProductTitle(null);
|
|
28972
29336
|
completedRef.current = false;
|
|
28973
29337
|
modelImageIdRef.current = null;
|
|
28974
29338
|
noFitFoundRef.current = false;
|
|
@@ -29349,11 +29713,12 @@ function PrimeStyleTryonInner({
|
|
|
29349
29713
|
if (noFitFoundRef.current) return;
|
|
29350
29714
|
if (autoTryOnFiredRef.current) return;
|
|
29351
29715
|
if (tryOnProcessing || resultImageUrl) return;
|
|
29716
|
+
if (!sizingResult) return;
|
|
29352
29717
|
const file = selectedFile || selectedFileRef.current;
|
|
29353
29718
|
if (!file) return;
|
|
29354
29719
|
autoTryOnFiredRef.current = true;
|
|
29355
29720
|
handleTryOnSubmit();
|
|
29356
|
-
}, [view, selectedFile, tryOnProcessing, resultImageUrl, handleTryOnSubmit]);
|
|
29721
|
+
}, [view, selectedFile, sizingResult, tryOnProcessing, resultImageUrl, handleTryOnSubmit]);
|
|
29357
29722
|
const handleDownload = reactExports.useCallback(() => {
|
|
29358
29723
|
if (!resultImageUrl) return;
|
|
29359
29724
|
if (resultImageUrl.startsWith("data:")) {
|
|
@@ -29493,9 +29858,7 @@ function PrimeStyleTryonInner({
|
|
|
29493
29858
|
const file = selectedFile || selectedFileRef.current;
|
|
29494
29859
|
if (file) {
|
|
29495
29860
|
try {
|
|
29496
|
-
|
|
29497
|
-
const blob = await (await fetch(dataUrl)).blob();
|
|
29498
|
-
hasPhoto = await savePhoto(id2, blob);
|
|
29861
|
+
hasPhoto = await savePhoto(id2, file);
|
|
29499
29862
|
} catch {
|
|
29500
29863
|
}
|
|
29501
29864
|
}
|
|
@@ -29550,7 +29913,7 @@ function PrimeStyleTryonInner({
|
|
|
29550
29913
|
historyTryonSavedRef.current = false;
|
|
29551
29914
|
saveHistoryEntry().catch(() => {
|
|
29552
29915
|
});
|
|
29553
|
-
} else if (view === "size-result" && sizingResult && resultImageUrl && !historyTryonSavedRef.current) {
|
|
29916
|
+
} else if ((view === "size-result" || view === "idle") && sizingResult && resultImageUrl && !historyTryonSavedRef.current) {
|
|
29554
29917
|
historyTryonSavedRef.current = true;
|
|
29555
29918
|
const overrides = pendingCustomSizesRef.current;
|
|
29556
29919
|
const recommended = sizingResult?.recommendedSize ?? "";
|
|
@@ -29583,6 +29946,14 @@ function PrimeStyleTryonInner({
|
|
|
29583
29946
|
await saveResult(id2, blob);
|
|
29584
29947
|
} catch {
|
|
29585
29948
|
}
|
|
29949
|
+
if (view === "idle") {
|
|
29950
|
+
unsubRef.current?.();
|
|
29951
|
+
unsubRef.current = null;
|
|
29952
|
+
if (pollingRef.current) {
|
|
29953
|
+
clearInterval(pollingRef.current);
|
|
29954
|
+
pollingRef.current = null;
|
|
29955
|
+
}
|
|
29956
|
+
}
|
|
29586
29957
|
})();
|
|
29587
29958
|
}
|
|
29588
29959
|
} else if (view === "result" && resultImageUrl && !historySavedRef.current) {
|
|
@@ -29598,6 +29969,8 @@ function PrimeStyleTryonInner({
|
|
|
29598
29969
|
historySavedRef.current = true;
|
|
29599
29970
|
historyTryonSavedRef.current = !!entry.resultImageUrl;
|
|
29600
29971
|
autoTryOnFiredRef.current = true;
|
|
29972
|
+
setRestoredProductImage(entry.productImage || null);
|
|
29973
|
+
setRestoredProductTitle(entry.productTitle || null);
|
|
29601
29974
|
if (entry.sizingResult) {
|
|
29602
29975
|
setSizingResult(entry.sizingResult);
|
|
29603
29976
|
} else if (entry.recommendedSize) {
|
|
@@ -29645,7 +30018,12 @@ function PrimeStyleTryonInner({
|
|
|
29645
30018
|
setSizingLoading(false);
|
|
29646
30019
|
setTryOnProcessing(false);
|
|
29647
30020
|
setTryOnStartedAt(null);
|
|
29648
|
-
|
|
30021
|
+
const sectionNames = entry.sizeGuide?.sections ? Object.keys(entry.sizeGuide.sections) : [];
|
|
30022
|
+
if (sectionNames.length === 1) {
|
|
30023
|
+
setActiveSection(sectionNames[0]);
|
|
30024
|
+
} else {
|
|
30025
|
+
setActiveSection(null);
|
|
30026
|
+
}
|
|
29649
30027
|
setDrawer(null);
|
|
29650
30028
|
setView("size-result");
|
|
29651
30029
|
}, []);
|
|
@@ -29821,9 +30199,9 @@ function PrimeStyleTryonInner({
|
|
|
29821
30199
|
sizingResult,
|
|
29822
30200
|
sizeGuide,
|
|
29823
30201
|
resultImageUrl,
|
|
29824
|
-
productImage,
|
|
29825
|
-
productImages,
|
|
29826
|
-
productTitle,
|
|
30202
|
+
productImage: restoredProductImage || productImage,
|
|
30203
|
+
productImages: restoredProductImage ? [restoredProductImage] : productImages,
|
|
30204
|
+
productTitle: restoredProductTitle || productTitle,
|
|
29827
30205
|
productMaterial,
|
|
29828
30206
|
productDescription,
|
|
29829
30207
|
sizingUnit,
|
|
@@ -30102,8 +30480,21 @@ function PrimeStyleTryonInner({
|
|
|
30102
30480
|
view !== "idle" && typeof document !== "undefined" && reactDomExports.createPortal(
|
|
30103
30481
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" || view === "profiles" || view === "no-chart" || view === "photo-guide" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
|
|
30104
30482
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-header ps-tryon-header-minimal", cn.header), children: [
|
|
30483
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30484
|
+
"a",
|
|
30485
|
+
{
|
|
30486
|
+
className: "ps-tryon-powered-by",
|
|
30487
|
+
href: "https://primestyleai.com",
|
|
30488
|
+
target: "_blank",
|
|
30489
|
+
rel: "noopener noreferrer",
|
|
30490
|
+
children: [
|
|
30491
|
+
"Powered by ",
|
|
30492
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "PrimeStyleAI" })
|
|
30493
|
+
]
|
|
30494
|
+
}
|
|
30495
|
+
),
|
|
30105
30496
|
/* @__PURE__ */ jsxRuntimeExports.jsx(LangSwitcher, { activeLocale, onSelect: setActiveLocale }),
|
|
30106
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
30497
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "ps-tryon-header-icon ps-tryon-header-icon-labeled", title: t2("Profiles"), onClick: () => {
|
|
30107
30498
|
if (drawer) setDrawer(null);
|
|
30108
30499
|
if (view === "profiles") {
|
|
30109
30500
|
setView(prevViewRef.current || "body-profile");
|
|
@@ -30112,8 +30503,11 @@ function PrimeStyleTryonInner({
|
|
|
30112
30503
|
prevViewRef.current = view;
|
|
30113
30504
|
setView("profiles");
|
|
30114
30505
|
}
|
|
30115
|
-
}, children:
|
|
30116
|
-
|
|
30506
|
+
}, children: [
|
|
30507
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(UserIcon, {}),
|
|
30508
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-header-icon-label", children: t2("Profile") })
|
|
30509
|
+
] }),
|
|
30510
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "ps-tryon-header-icon ps-tryon-header-icon-labeled", title: t2("History"), onClick: () => {
|
|
30117
30511
|
if (view === "profiles") {
|
|
30118
30512
|
setView(prevViewRef.current || "body-profile");
|
|
30119
30513
|
prevViewRef.current = null;
|
|
@@ -30124,9 +30518,109 @@ function PrimeStyleTryonInner({
|
|
|
30124
30518
|
prevViewRef.current = prevViewRef.current || view;
|
|
30125
30519
|
setDrawer("history");
|
|
30126
30520
|
}
|
|
30127
|
-
}, children:
|
|
30128
|
-
|
|
30521
|
+
}, children: [
|
|
30522
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ClockIcon, {}),
|
|
30523
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-header-icon-label", children: t2("History") })
|
|
30524
|
+
] }),
|
|
30525
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30526
|
+
"button",
|
|
30527
|
+
{
|
|
30528
|
+
type: "button",
|
|
30529
|
+
ref: mobileMenuBtnRef,
|
|
30530
|
+
className: "ps-tryon-header-mobile-menu-btn",
|
|
30531
|
+
"aria-label": t2("Menu"),
|
|
30532
|
+
"aria-expanded": mobileMenuOpen,
|
|
30533
|
+
onClick: () => setMobileMenuOpen((v2) => !v2),
|
|
30534
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "20", height: "20", children: [
|
|
30535
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
|
|
30536
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }),
|
|
30537
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })
|
|
30538
|
+
] })
|
|
30539
|
+
}
|
|
30540
|
+
),
|
|
30541
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsxRuntimeExports.jsx(XIcon, {}) })
|
|
30129
30542
|
] }),
|
|
30543
|
+
mobileMenuOpen && typeof document !== "undefined" && reactDomExports.createPortal(
|
|
30544
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
30545
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30546
|
+
"div",
|
|
30547
|
+
{
|
|
30548
|
+
className: "ps-tryon-header-mobile-backdrop",
|
|
30549
|
+
onClick: () => setMobileMenuOpen(false)
|
|
30550
|
+
}
|
|
30551
|
+
),
|
|
30552
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30553
|
+
"div",
|
|
30554
|
+
{
|
|
30555
|
+
className: "ps-tryon-header-mobile-menu",
|
|
30556
|
+
role: "menu",
|
|
30557
|
+
style: (() => {
|
|
30558
|
+
const r2 = mobileMenuBtnRef.current?.getBoundingClientRect();
|
|
30559
|
+
if (!r2) return void 0;
|
|
30560
|
+
return {
|
|
30561
|
+
top: `${Math.round(r2.bottom + 6)}px`,
|
|
30562
|
+
right: `${Math.round(window.innerWidth - r2.right)}px`
|
|
30563
|
+
};
|
|
30564
|
+
})(),
|
|
30565
|
+
children: [
|
|
30566
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30567
|
+
"button",
|
|
30568
|
+
{
|
|
30569
|
+
type: "button",
|
|
30570
|
+
className: "ps-tryon-header-mobile-menu-item",
|
|
30571
|
+
role: "menuitem",
|
|
30572
|
+
onClick: () => {
|
|
30573
|
+
setMobileMenuOpen(false);
|
|
30574
|
+
if (drawer) setDrawer(null);
|
|
30575
|
+
if (view === "profiles") {
|
|
30576
|
+
setView(prevViewRef.current || "body-profile");
|
|
30577
|
+
prevViewRef.current = null;
|
|
30578
|
+
} else {
|
|
30579
|
+
prevViewRef.current = view;
|
|
30580
|
+
setView("profiles");
|
|
30581
|
+
}
|
|
30582
|
+
},
|
|
30583
|
+
children: [
|
|
30584
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(UserIcon, {}),
|
|
30585
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("Profile") })
|
|
30586
|
+
]
|
|
30587
|
+
}
|
|
30588
|
+
),
|
|
30589
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30590
|
+
"button",
|
|
30591
|
+
{
|
|
30592
|
+
type: "button",
|
|
30593
|
+
className: "ps-tryon-header-mobile-menu-item",
|
|
30594
|
+
role: "menuitem",
|
|
30595
|
+
onClick: () => {
|
|
30596
|
+
setMobileMenuOpen(false);
|
|
30597
|
+
if (view === "profiles") {
|
|
30598
|
+
setView(prevViewRef.current || "body-profile");
|
|
30599
|
+
prevViewRef.current = null;
|
|
30600
|
+
}
|
|
30601
|
+
if (drawer === "history") {
|
|
30602
|
+
setDrawer(null);
|
|
30603
|
+
} else {
|
|
30604
|
+
prevViewRef.current = prevViewRef.current || view;
|
|
30605
|
+
setDrawer("history");
|
|
30606
|
+
}
|
|
30607
|
+
},
|
|
30608
|
+
children: [
|
|
30609
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(ClockIcon, {}),
|
|
30610
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("History") })
|
|
30611
|
+
]
|
|
30612
|
+
}
|
|
30613
|
+
),
|
|
30614
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-header-mobile-menu-lang", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LangSwitcher, { activeLocale, onSelect: (l2) => {
|
|
30615
|
+
setActiveLocale(l2);
|
|
30616
|
+
setMobileMenuOpen(false);
|
|
30617
|
+
} }) })
|
|
30618
|
+
]
|
|
30619
|
+
}
|
|
30620
|
+
)
|
|
30621
|
+
] }),
|
|
30622
|
+
document.body
|
|
30623
|
+
),
|
|
30130
30624
|
view !== "body-profile" && view !== "processing" && !(view === "size-result" && sizeGuide?.sections && Object.keys(sizeGuide.sections).length > 1) && /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper, { view, stepIndex }),
|
|
30131
30625
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
|
|
30132
30626
|
showBackButton && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-back-btn", onClick: handleBack, children: [
|