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