@primestyleai/tryon 5.8.57 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-client.d.ts +1 -1
- package/dist/{index-J6U0-q_3.js → index-CuIieeOy.js} +2 -1
- package/dist/primestyle-tryon.js +2 -2
- package/dist/react/index.js +243 -49
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/views/PhotoStepMobile.d.ts +3 -1
- package/dist/react/views/ProcessingView.d.ts +3 -1
- package/dist/storefront/primestyle-tryon.js +244 -49
- package/package.json +1 -4
|
@@ -9,7 +9,9 @@ interface PhotoStepMobileProps {
|
|
|
9
9
|
photoVariant?: "full-body" | "close-up";
|
|
10
10
|
photoStepHeight?: string;
|
|
11
11
|
onPhotoStepHeightChange?: (v: string) => void;
|
|
12
|
+
ageConfirmed: boolean | null;
|
|
13
|
+
onAgeConfirmedChange: (v: boolean | null) => void;
|
|
12
14
|
t: TranslateFn;
|
|
13
15
|
}
|
|
14
|
-
export declare function PhotoStepMobile({ photoPreview, handlePhotoSelect, handleRemovePhoto, onAnalyze, onSwitchToManual, error, photoVariant, photoStepHeight, onPhotoStepHeightChange, t, }: PhotoStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function PhotoStepMobile({ photoPreview, handlePhotoSelect, handleRemovePhoto, onAnalyze, onSwitchToManual, error, photoVariant, photoStepHeight, onPhotoStepHeightChange, ageConfirmed, onAgeConfirmedChange, t, }: PhotoStepMobileProps): import("react/jsx-runtime").JSX.Element;
|
|
15
17
|
export {};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { PrimeStyleClassNames } from "../../types";
|
|
2
2
|
import type { TranslateFn } from "../../i18n";
|
|
3
|
-
export declare function ProcessingView({ previewUrl, progressRef, progressBarRef, progressTextRef, progressStatusRef, cn, t, }: {
|
|
3
|
+
export declare function ProcessingView({ previewUrl, progressRef, progressBarRef, progressTextRef, progressStatusRef, progressEtaRef, progressRingRef, cn, t, }: {
|
|
4
4
|
previewUrl: string | null;
|
|
5
5
|
progressRef: React.MutableRefObject<number>;
|
|
6
6
|
progressBarRef: React.MutableRefObject<HTMLDivElement | null>;
|
|
7
7
|
progressTextRef: React.MutableRefObject<HTMLSpanElement | null>;
|
|
8
8
|
progressStatusRef: React.MutableRefObject<HTMLDivElement | null>;
|
|
9
|
+
progressEtaRef: React.MutableRefObject<HTMLSpanElement | null>;
|
|
10
|
+
progressRingRef: React.MutableRefObject<SVGCircleElement | null>;
|
|
9
11
|
cn: PrimeStyleClassNames;
|
|
10
12
|
t: TranslateFn;
|
|
11
13
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -9296,9 +9296,10 @@ class ApiClient {
|
|
|
9296
9296
|
Authorization: `Bearer ${this.apiKey}`
|
|
9297
9297
|
};
|
|
9298
9298
|
}
|
|
9299
|
-
async submitTryOn(modelImage, garmentImage, fitInfo) {
|
|
9299
|
+
async submitTryOn(modelImage, garmentImage, fitInfo, category) {
|
|
9300
9300
|
const body = { modelImage, garmentImage };
|
|
9301
9301
|
if (fitInfo && fitInfo.length > 0) body.fitInfo = fitInfo;
|
|
9302
|
+
if (category && category !== "apparel") body.category = category;
|
|
9302
9303
|
const res = await fetch(`${this.baseUrl}/api/v1/tryon`, {
|
|
9303
9304
|
method: "POST",
|
|
9304
9305
|
headers: this.headers,
|
|
@@ -11508,22 +11509,61 @@ const STYLES$1 = `
|
|
|
11508
11509
|
}
|
|
11509
11510
|
|
|
11510
11511
|
.ps-tryon-progress-section {
|
|
11511
|
-
display: flex; align-items: center; gap: 0.63vw; width: 100%; max-width:
|
|
11512
|
+
display: flex; align-items: center; gap: 0.63vw; width: 100%; max-width: 18vw; margin-bottom: 0.83vw;
|
|
11512
11513
|
}
|
|
11513
11514
|
.ps-tryon-progress-bar-wrap {
|
|
11514
11515
|
flex: 1; height: 0.31vw; background: var(--ps-border-color); border-radius: 3px; overflow: hidden;
|
|
11516
|
+
position: relative;
|
|
11517
|
+
}
|
|
11518
|
+
.ps-tryon-progress-bar-wrap::after {
|
|
11519
|
+
content: ""; position: absolute; inset: 0;
|
|
11520
|
+
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.45) 50%, transparent 100%);
|
|
11521
|
+
transform: translateX(-100%);
|
|
11522
|
+
animation: ps-progress-shimmer 2s linear infinite;
|
|
11523
|
+
pointer-events: none;
|
|
11524
|
+
}
|
|
11525
|
+
@keyframes ps-progress-shimmer {
|
|
11526
|
+
0% { transform: translateX(-100%); }
|
|
11527
|
+
100% { transform: translateX(100%); }
|
|
11515
11528
|
}
|
|
11516
11529
|
.ps-tryon-progress-bar-fill {
|
|
11517
11530
|
height: 100%; background: linear-gradient(90deg, var(--ps-accent), var(--ps-accent-light));
|
|
11518
11531
|
border-radius: 3px; transition: width 0.3s ease; width: 0%;
|
|
11532
|
+
position: relative; z-index: 1;
|
|
11519
11533
|
}
|
|
11520
11534
|
.ps-tryon-progress-pct {
|
|
11521
11535
|
font-size: 0.68vw; font-weight: 700; color: var(--ps-accent); min-width: 1.88vw; text-align: right;
|
|
11522
11536
|
font-variant-numeric: tabular-nums;
|
|
11523
11537
|
}
|
|
11524
11538
|
|
|
11539
|
+
/* Circular ETA ring — 48×48 px SVG with a track + progress circle; ETA
|
|
11540
|
+
text centered. strokeDashoffset is driven by the ticker in
|
|
11541
|
+
PrimeStyleTryonInner, so CSS only styles the appearance. */
|
|
11542
|
+
.ps-tryon-progress-ring {
|
|
11543
|
+
position: relative; width: 48px; height: 48px; flex: 0 0 48px;
|
|
11544
|
+
display: flex; align-items: center; justify-content: center;
|
|
11545
|
+
}
|
|
11546
|
+
.ps-tryon-progress-ring svg { transform: rotate(-90deg); }
|
|
11547
|
+
.ps-tryon-progress-ring-track {
|
|
11548
|
+
fill: none; stroke: var(--ps-border-color); stroke-width: 3.5;
|
|
11549
|
+
}
|
|
11550
|
+
.ps-tryon-progress-ring-fill {
|
|
11551
|
+
fill: none; stroke: var(--ps-accent); stroke-width: 3.5;
|
|
11552
|
+
stroke-linecap: round;
|
|
11553
|
+
transition: stroke-dashoffset 0.3s ease;
|
|
11554
|
+
}
|
|
11555
|
+
.ps-tryon-progress-eta {
|
|
11556
|
+
position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
11557
|
+
font-size: 10px; font-weight: 700; color: var(--ps-accent);
|
|
11558
|
+
font-variant-numeric: tabular-nums; letter-spacing: 0.01em;
|
|
11559
|
+
pointer-events: none;
|
|
11560
|
+
}
|
|
11561
|
+
|
|
11525
11562
|
@keyframes ps-scale-in { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } }
|
|
11526
|
-
.ps-tryon-processing-text {
|
|
11563
|
+
.ps-tryon-processing-text {
|
|
11564
|
+
font-size: 0.73vw; color: var(--ps-text-primary); margin: 0 0 0.21vw;
|
|
11565
|
+
opacity: 1; transition: opacity 0.18s ease;
|
|
11566
|
+
}
|
|
11527
11567
|
.ps-tryon-processing-sub { font-size: 0.63vw; color: var(--ps-text-secondary); margin: 0; }
|
|
11528
11568
|
|
|
11529
11569
|
/* Result — split layout */
|
|
@@ -18374,6 +18414,7 @@ function SizeResultView({
|
|
|
18374
18414
|
const allDone = hasPhoto ? sizingDone && tryOnDone : sizingDone;
|
|
18375
18415
|
const isMobile = useIsMobile();
|
|
18376
18416
|
const isAccessory = measurementType === "face" || measurementType === "head";
|
|
18417
|
+
const vtoExcluded = measurementType === "foot";
|
|
18377
18418
|
console.log("[PS-SDK] SizeResultView render:", {
|
|
18378
18419
|
hasPhoto,
|
|
18379
18420
|
isSnapProcessing,
|
|
@@ -18647,7 +18688,7 @@ function SizeResultView({
|
|
|
18647
18688
|
" →"
|
|
18648
18689
|
]
|
|
18649
18690
|
}
|
|
18650
|
-
) :
|
|
18691
|
+
) : vtoExcluded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
18651
18692
|
"button",
|
|
18652
18693
|
{
|
|
18653
18694
|
className: "ps-tryon-v2-cta",
|
|
@@ -18707,7 +18748,7 @@ function SizeResultView({
|
|
|
18707
18748
|
onBack: resultImageUrl ? onClose || (() => setView("body-profile")) : () => setView("body-profile"),
|
|
18708
18749
|
backLabel: t2("Back"),
|
|
18709
18750
|
internationalSizes: sizingResult?.internationalSizes,
|
|
18710
|
-
onTryOn: resultImageUrl ||
|
|
18751
|
+
onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
|
|
18711
18752
|
continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
|
|
18712
18753
|
tryOnProcessing,
|
|
18713
18754
|
productImage: resultImageUrl || productImage,
|
|
@@ -18754,7 +18795,7 @@ function SizeResultView({
|
|
|
18754
18795
|
onBack: resultImageUrl ? onClose || (() => setView("body-profile")) : () => setView("body-profile"),
|
|
18755
18796
|
backLabel: t2("Back"),
|
|
18756
18797
|
internationalSizes: sizingResult?.internationalSizes,
|
|
18757
|
-
onTryOn: resultImageUrl ||
|
|
18798
|
+
onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
|
|
18758
18799
|
continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
|
|
18759
18800
|
tryOnProcessing,
|
|
18760
18801
|
t: t2,
|
|
@@ -18764,14 +18805,14 @@ function SizeResultView({
|
|
|
18764
18805
|
] });
|
|
18765
18806
|
})()
|
|
18766
18807
|
),
|
|
18767
|
-
showPhotoGuide && !
|
|
18808
|
+
showPhotoGuide && !vtoExcluded && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-chart-overlay", children: isMobile ? (
|
|
18768
18809
|
/* ── Mobile: same layout as the AI-sizing photo step
|
|
18769
18810
|
(PhotoStepMobile) — title + subtitle, large preview,
|
|
18770
18811
|
checklist card, primary CTA + RETAKE secondary. ── */
|
|
18771
18812
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-wrapper", style: { padding: "16px 16px 0", background: "var(--ps-bg-primary)" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-root", children: [
|
|
18772
18813
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-header", children: [
|
|
18773
18814
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-pm-title", children: t2("Review your photo") }),
|
|
18774
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-pm-subtitle", children: t2("Ensure your full body is visible for the most accurate virtual try-on.") })
|
|
18815
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-pm-subtitle", children: measurementType === "face" ? t2("A clear, front-facing face photo — no glasses on — gives us the most accurate try-on.") : measurementType === "head" ? t2("Face the camera with your head and shoulders in frame, leaving space above your head.") : t2("Ensure your full body is visible for the most accurate virtual try-on.") })
|
|
18775
18816
|
] }),
|
|
18776
18817
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
18777
18818
|
"input",
|
|
@@ -18822,11 +18863,19 @@ function SizeResultView({
|
|
|
18822
18863
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-checklist-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "14", height: "14", children: /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" }) }) }),
|
|
18823
18864
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-checklist-body", children: [
|
|
18824
18865
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-checklist-title", children: t2("Checklist for accuracy") }),
|
|
18825
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
18866
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "ps-pm-checklist-items", children: measurementType === "face" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18867
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Face the camera directly at eye level") }),
|
|
18868
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Remove any glasses you're wearing") }),
|
|
18869
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Good lighting, plain background") })
|
|
18870
|
+
] }) : measurementType === "head" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18871
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Head and shoulders in frame") }),
|
|
18872
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Leave space above your head") }),
|
|
18873
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Good lighting, plain background") })
|
|
18874
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18826
18875
|
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Form-fitting clothing is recommended") }),
|
|
18827
18876
|
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Standing 2-3 meters from camera") }),
|
|
18828
18877
|
/* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: t2("Neutral background with good lighting") })
|
|
18829
|
-
] })
|
|
18878
|
+
] }) })
|
|
18830
18879
|
] })
|
|
18831
18880
|
] }),
|
|
18832
18881
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bpm-spacer" }),
|
|
@@ -18906,7 +18955,7 @@ function SizeResultView({
|
|
|
18906
18955
|
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18907
18956
|
/* @__PURE__ */ jsxRuntimeExports.jsx(UploadIcon, { size: 32 }),
|
|
18908
18957
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: "0.85vw", fontWeight: 600, color: "var(--ps-text-primary)", marginTop: "0.5vw" }, children: t2("Upload your photo") }),
|
|
18909
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: "0.6vw", color: "var(--ps-text-muted)", marginTop: "0.2vw" }, children: t2("Click or drag a full-body photo") })
|
|
18958
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: "0.6vw", color: "var(--ps-text-muted)", marginTop: "0.2vw" }, children: measurementType === "face" ? t2("Click or drag a close-up face photo") : measurementType === "head" ? t2("Click or drag a head-and-shoulders photo") : t2("Click or drag a full-body photo") })
|
|
18910
18959
|
] }),
|
|
18911
18960
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
18912
18961
|
"input",
|
|
@@ -18931,7 +18980,23 @@ function SizeResultView({
|
|
|
18931
18980
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#1c9d4c", fontSize: "0.75vw", fontWeight: 700 }, children: "✓" }),
|
|
18932
18981
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#1c9d4c", fontSize: "0.65vw", fontWeight: 600 }, children: t2("Do") })
|
|
18933
18982
|
] }),
|
|
18934
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
18983
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: "0.58vw", color: "var(--ps-text-primary)", lineHeight: 1.8 }, children: measurementType === "face" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18984
|
+
t2("Face the camera directly, centered in frame"),
|
|
18985
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18986
|
+
t2("Use natural, even lighting (e.g. near a window)"),
|
|
18987
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18988
|
+
t2("Keep hair away from your face and ears"),
|
|
18989
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18990
|
+
t2("Choose a plain, light background")
|
|
18991
|
+
] }) : measurementType === "head" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18992
|
+
t2("Face the camera with head and shoulders in frame"),
|
|
18993
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18994
|
+
t2("Leave some space above your head"),
|
|
18995
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18996
|
+
t2("Use natural, even lighting"),
|
|
18997
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18998
|
+
t2("Choose a plain, light background")
|
|
18999
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18935
19000
|
t2("Stand facing the camera with your full body in frame"),
|
|
18936
19001
|
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18937
19002
|
t2("Use natural or even lighting"),
|
|
@@ -18939,14 +19004,30 @@ function SizeResultView({
|
|
|
18939
19004
|
t2("Wear fitted, simple clothing"),
|
|
18940
19005
|
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18941
19006
|
t2("Stand straight and still, arms relaxed")
|
|
18942
|
-
] })
|
|
19007
|
+
] }) })
|
|
18943
19008
|
] }),
|
|
18944
19009
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { background: "#ffe2e2", borderRadius: "0.5vw", padding: "0.6vw 0.8vw" }, children: [
|
|
18945
19010
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.3vw", marginBottom: "0.3vw" }, children: [
|
|
18946
19011
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#e7000b", fontSize: "0.75vw", fontWeight: 700 }, children: "✗" }),
|
|
18947
19012
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "#e7000b", fontSize: "0.65vw", fontWeight: 600 }, children: t2("Don't") })
|
|
18948
19013
|
] }),
|
|
18949
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
19014
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: "0.58vw", color: "var(--ps-text-primary)", lineHeight: 1.8 }, children: measurementType === "face" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
19015
|
+
t2("Don't wear sunglasses or a hat in the photo"),
|
|
19016
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19017
|
+
t2("Don't tilt or turn your head"),
|
|
19018
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19019
|
+
t2("Don't use strong backlighting or flash"),
|
|
19020
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19021
|
+
t2("Don't apply filters or edits")
|
|
19022
|
+
] }) : measurementType === "head" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
19023
|
+
t2("Don't wear a hat in the photo"),
|
|
19024
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19025
|
+
t2("Don't crop out the top of your head"),
|
|
19026
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19027
|
+
t2("Don't use strong backlighting or flash"),
|
|
19028
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
19029
|
+
t2("Don't apply filters or edits")
|
|
19030
|
+
] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
18950
19031
|
t2("Don't wear loose or baggy clothing"),
|
|
18951
19032
|
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18952
19033
|
t2("Don't sit, pose, or bend"),
|
|
@@ -18954,14 +19035,14 @@ function SizeResultView({
|
|
|
18954
19035
|
t2("Don't take mirror photos or selfies"),
|
|
18955
19036
|
/* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
|
|
18956
19037
|
t2("Don't apply filters or edits")
|
|
18957
|
-
] })
|
|
19038
|
+
] }) })
|
|
18958
19039
|
] }),
|
|
18959
19040
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { background: "rgba(59,130,246,0.08)", border: "1px solid rgba(59,130,246,0.2)", borderRadius: "0.5vw", padding: "0.5vw 0.8vw" }, children: [
|
|
18960
19041
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.3vw", marginBottom: "0.2vw" }, children: [
|
|
18961
19042
|
/* @__PURE__ */ jsxRuntimeExports.jsx(SparkleIcon, { size: 12 }),
|
|
18962
19043
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: "var(--ps-accent)", fontSize: "0.65vw", fontWeight: 700 }, children: t2("Pro Tip") })
|
|
18963
19044
|
] }),
|
|
18964
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: "0.55vw", color: "var(--ps-text-secondary)", lineHeight: 1.7 }, children: t2("Our AI works best with front-facing, full-body photos in fitted clothing. Better photos = more accurate virtual try-on!") })
|
|
19045
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { fontSize: "0.55vw", color: "var(--ps-text-secondary)", lineHeight: 1.7 }, children: measurementType === "face" ? t2("A clear, well-lit face photo gives the most accurate eyewear try-on.") : measurementType === "head" ? t2("A clear head-and-shoulders photo with space above your head gives the most accurate headwear try-on.") : t2("Our AI works best with front-facing, full-body photos in fitted clothing. Better photos = more accurate virtual try-on!") })
|
|
18965
19046
|
] })
|
|
18966
19047
|
] })
|
|
18967
19048
|
] }),
|
|
@@ -19090,12 +19171,16 @@ function UploadView({
|
|
|
19090
19171
|
}
|
|
19091
19172
|
) });
|
|
19092
19173
|
}
|
|
19174
|
+
const RING_RADIUS = 20;
|
|
19175
|
+
const RING_CIRCUMFERENCE = 2 * Math.PI * RING_RADIUS;
|
|
19093
19176
|
function ProcessingView({
|
|
19094
19177
|
previewUrl,
|
|
19095
19178
|
progressRef,
|
|
19096
19179
|
progressBarRef,
|
|
19097
19180
|
progressTextRef,
|
|
19098
19181
|
progressStatusRef,
|
|
19182
|
+
progressEtaRef,
|
|
19183
|
+
progressRingRef,
|
|
19099
19184
|
cn,
|
|
19100
19185
|
t: t2
|
|
19101
19186
|
}) {
|
|
@@ -19110,6 +19195,16 @@ function ProcessingView({
|
|
|
19110
19195
|
const statusCb = reactExports.useCallback((el2) => {
|
|
19111
19196
|
progressStatusRef.current = el2;
|
|
19112
19197
|
}, []);
|
|
19198
|
+
const etaCb = reactExports.useCallback((el2) => {
|
|
19199
|
+
progressEtaRef.current = el2;
|
|
19200
|
+
}, []);
|
|
19201
|
+
const ringCb = reactExports.useCallback((el2) => {
|
|
19202
|
+
progressRingRef.current = el2;
|
|
19203
|
+
if (el2) {
|
|
19204
|
+
const offset = RING_CIRCUMFERENCE * (1 - Math.round(progressRef.current) / 100);
|
|
19205
|
+
el2.style.strokeDashoffset = String(offset);
|
|
19206
|
+
}
|
|
19207
|
+
}, []);
|
|
19113
19208
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing", children: [
|
|
19114
19209
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-processing-image-wrap", children: [
|
|
19115
19210
|
previewUrl && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
|
|
@@ -19120,6 +19215,32 @@ function ProcessingView({
|
|
|
19120
19215
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-scan-overlay" })
|
|
19121
19216
|
] }),
|
|
19122
19217
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-section", children: [
|
|
19218
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-progress-ring", children: [
|
|
19219
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 48 48", width: "48", height: "48", "aria-hidden": "true", children: [
|
|
19220
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19221
|
+
"circle",
|
|
19222
|
+
{
|
|
19223
|
+
cx: "24",
|
|
19224
|
+
cy: "24",
|
|
19225
|
+
r: RING_RADIUS,
|
|
19226
|
+
className: "ps-tryon-progress-ring-track"
|
|
19227
|
+
}
|
|
19228
|
+
),
|
|
19229
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
19230
|
+
"circle",
|
|
19231
|
+
{
|
|
19232
|
+
ref: ringCb,
|
|
19233
|
+
cx: "24",
|
|
19234
|
+
cy: "24",
|
|
19235
|
+
r: RING_RADIUS,
|
|
19236
|
+
className: "ps-tryon-progress-ring-fill",
|
|
19237
|
+
strokeDasharray: RING_CIRCUMFERENCE,
|
|
19238
|
+
strokeDashoffset: RING_CIRCUMFERENCE
|
|
19239
|
+
}
|
|
19240
|
+
)
|
|
19241
|
+
] }),
|
|
19242
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: etaCb, className: "ps-tryon-progress-eta", children: `~22s` })
|
|
19243
|
+
] }),
|
|
19123
19244
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: barCb, className: "ps-tryon-progress-bar-fill" }) }),
|
|
19124
19245
|
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { ref: pctCb, className: "ps-tryon-progress-pct", children: "0%" })
|
|
19125
19246
|
] }),
|
|
@@ -20785,12 +20906,13 @@ function PhotoStepMobile({
|
|
|
20785
20906
|
photoVariant = "full-body",
|
|
20786
20907
|
photoStepHeight,
|
|
20787
20908
|
onPhotoStepHeightChange,
|
|
20909
|
+
ageConfirmed,
|
|
20910
|
+
onAgeConfirmedChange,
|
|
20788
20911
|
t: t2
|
|
20789
20912
|
}) {
|
|
20790
20913
|
const isCloseUp = photoVariant === "close-up";
|
|
20791
20914
|
const fileRef = reactExports.useRef(null);
|
|
20792
20915
|
const hasPhoto = !!photoPreview;
|
|
20793
|
-
const [ageConfirmed, setAgeConfirmed] = reactExports.useState(null);
|
|
20794
20916
|
const gated = !hasPhoto && ageConfirmed !== true;
|
|
20795
20917
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-root", children: [
|
|
20796
20918
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-header", children: [
|
|
@@ -20842,14 +20964,14 @@ function PhotoStepMobile({
|
|
|
20842
20964
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-age-gate-eyebrow", children: t2("AGE VERIFICATION") }),
|
|
20843
20965
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-age-gate-question", children: t2("Is the person in this photo 18 years or older?") }),
|
|
20844
20966
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-age-gate-actions", children: [
|
|
20845
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-primary", onClick: () =>
|
|
20846
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-secondary", onClick: () =>
|
|
20967
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-primary", onClick: () => onAgeConfirmedChange(true), children: t2("Yes") }),
|
|
20968
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-secondary", onClick: () => onAgeConfirmedChange(false), children: t2("No") })
|
|
20847
20969
|
] })
|
|
20848
20970
|
] }) }),
|
|
20849
20971
|
ageConfirmed === false && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-age-gate", role: "alert", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-age-gate-card", children: [
|
|
20850
20972
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-age-gate-eyebrow ps-pm-age-gate-eyebrow-blocked", children: t2("UPLOAD NOT ALLOWED") }),
|
|
20851
20973
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-pm-age-gate-question", children: t2("For your safety, we cannot process photos of people under 18.") }),
|
|
20852
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-secondary", onClick: () =>
|
|
20974
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-pm-age-gate-btn ps-pm-age-gate-btn-secondary", onClick: () => onAgeConfirmedChange(null), children: t2("Go back") })
|
|
20853
20975
|
] }) })
|
|
20854
20976
|
] }) }),
|
|
20855
20977
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-pm-legal-notice", children: [
|
|
@@ -21317,6 +21439,11 @@ function BodyProfileView({
|
|
|
21317
21439
|
error,
|
|
21318
21440
|
photoStepHeight,
|
|
21319
21441
|
onPhotoStepHeightChange: setPhotoStepHeight,
|
|
21442
|
+
ageConfirmed,
|
|
21443
|
+
onAgeConfirmedChange: (v2) => {
|
|
21444
|
+
setAgeConfirmed(v2);
|
|
21445
|
+
if (v2 === true) setError("");
|
|
21446
|
+
},
|
|
21320
21447
|
t: t2
|
|
21321
21448
|
}
|
|
21322
21449
|
) });
|
|
@@ -22063,6 +22190,11 @@ function AccessorySizeView({
|
|
|
22063
22190
|
onSwitchToManual: () => setStep("manual"),
|
|
22064
22191
|
error,
|
|
22065
22192
|
photoVariant,
|
|
22193
|
+
ageConfirmed,
|
|
22194
|
+
onAgeConfirmedChange: (v2) => {
|
|
22195
|
+
setAgeConfirmed(v2);
|
|
22196
|
+
if (v2 === true) setError("");
|
|
22197
|
+
},
|
|
22066
22198
|
t: t2
|
|
22067
22199
|
}
|
|
22068
22200
|
) });
|
|
@@ -22473,13 +22605,26 @@ function buildFieldsFromSizeGuide$2(sizeGuide) {
|
|
|
22473
22605
|
const req = sizeGuide?.requiredFields;
|
|
22474
22606
|
if (!req || req.length === 0) return FALLBACK_FOOT_FIELDS;
|
|
22475
22607
|
const SIZE_CODE_KEYS = /* @__PURE__ */ new Set(["size", "country", "eu", "__skip__", "shoeEU", "shoeUS", "shoeUK", "shoeJP"]);
|
|
22476
|
-
const
|
|
22477
|
-
|
|
22478
|
-
|
|
22479
|
-
|
|
22480
|
-
|
|
22481
|
-
|
|
22482
|
-
}
|
|
22608
|
+
const defaultPlaceholderFor = (key, label) => {
|
|
22609
|
+
const exact = FALLBACK_FOOT_FIELDS.find((f2) => f2.key === key);
|
|
22610
|
+
if (exact) return exact.placeholder;
|
|
22611
|
+
const looksLikeFoot = /foot|length/i.test(key) || /foot|length/i.test(label);
|
|
22612
|
+
if (looksLikeFoot) return FALLBACK_FOOT_FIELDS[0].placeholder;
|
|
22613
|
+
return { cm: "", in: "" };
|
|
22614
|
+
};
|
|
22615
|
+
const out = req.filter((f2) => !SIZE_CODE_KEYS.has(f2.key) && f2.unit !== "size").map((f2) => {
|
|
22616
|
+
const fallback = defaultPlaceholderFor(f2.key, f2.label || "");
|
|
22617
|
+
return {
|
|
22618
|
+
key: f2.key,
|
|
22619
|
+
label: f2.label || f2.key,
|
|
22620
|
+
placeholder: {
|
|
22621
|
+
cm: f2.placeholder || fallback.cm,
|
|
22622
|
+
in: f2.placeholder || fallback.in
|
|
22623
|
+
},
|
|
22624
|
+
min: 0,
|
|
22625
|
+
step: 0.5
|
|
22626
|
+
};
|
|
22627
|
+
});
|
|
22483
22628
|
return out.length > 0 ? out : FALLBACK_FOOT_FIELDS;
|
|
22484
22629
|
}
|
|
22485
22630
|
function FootSizeView(props) {
|
|
@@ -22607,6 +22752,12 @@ function detectMeasurementType(title) {
|
|
|
22607
22752
|
if (/\b(sunglass|sunglasses|eyewear|eyeglasses|glasses|spectacles|optical|goggles|frames|aviator|wayfarer|lens)\b/.test(t2)) return "face";
|
|
22608
22753
|
return "body";
|
|
22609
22754
|
}
|
|
22755
|
+
function measurementTypeToVtoCategory(type) {
|
|
22756
|
+
if (type === "face") return "sunglasses";
|
|
22757
|
+
if (type === "head") return "hat";
|
|
22758
|
+
if (type === "body") return "apparel";
|
|
22759
|
+
return null;
|
|
22760
|
+
}
|
|
22610
22761
|
function PrimeStyleTryonInner({
|
|
22611
22762
|
productImage,
|
|
22612
22763
|
productTitle = "Product",
|
|
@@ -22712,15 +22863,22 @@ function PrimeStyleTryonInner({
|
|
|
22712
22863
|
if (pollingRef.current) clearInterval(pollingRef.current);
|
|
22713
22864
|
};
|
|
22714
22865
|
}, [apiUrl]);
|
|
22866
|
+
const TARGET_SECONDS = 22;
|
|
22715
22867
|
const progressRef = reactExports.useRef(0);
|
|
22716
22868
|
const progressBarRef = reactExports.useRef(null);
|
|
22717
22869
|
const progressTextRef = reactExports.useRef(null);
|
|
22718
22870
|
const progressStatusRef = reactExports.useRef(null);
|
|
22871
|
+
const progressEtaRef = reactExports.useRef(null);
|
|
22872
|
+
const progressRingRef = reactExports.useRef(null);
|
|
22873
|
+
const progressStartTsRef = reactExports.useRef(null);
|
|
22874
|
+
const progressLastStageRef = reactExports.useRef("");
|
|
22719
22875
|
const progressIntervalRef = reactExports.useRef(null);
|
|
22720
22876
|
reactExports.useEffect(() => {
|
|
22721
22877
|
if (view === "processing") {
|
|
22722
22878
|
if (progressIntervalRef.current) return;
|
|
22723
22879
|
progressRef.current = 0;
|
|
22880
|
+
progressStartTsRef.current = Date.now();
|
|
22881
|
+
progressLastStageRef.current = "";
|
|
22724
22882
|
const statuses = [
|
|
22725
22883
|
{ at: 0, text: t2("Preparing your image...") },
|
|
22726
22884
|
{ at: 15, text: t2("Analyzing body proportions...") },
|
|
@@ -22729,17 +22887,35 @@ function PrimeStyleTryonInner({
|
|
|
22729
22887
|
{ at: 75, text: t2("Refining details...") },
|
|
22730
22888
|
{ at: 90, text: t2("Almost there...") }
|
|
22731
22889
|
];
|
|
22890
|
+
const RING_CIRCUMFERENCE2 = 2 * Math.PI * 20;
|
|
22732
22891
|
progressIntervalRef.current = setInterval(() => {
|
|
22733
|
-
|
|
22734
|
-
|
|
22735
|
-
const
|
|
22736
|
-
|
|
22737
|
-
|
|
22892
|
+
if (completedRef.current) return;
|
|
22893
|
+
const startTs = progressStartTsRef.current || Date.now();
|
|
22894
|
+
const elapsed = (Date.now() - startTs) / 1e3;
|
|
22895
|
+
const target = Math.min(95, elapsed / TARGET_SECONDS * 100);
|
|
22896
|
+
progressRef.current = target;
|
|
22897
|
+
const val = Math.round(target);
|
|
22738
22898
|
if (progressBarRef.current) progressBarRef.current.style.width = `${val}%`;
|
|
22739
22899
|
if (progressTextRef.current) progressTextRef.current.textContent = `${val}%`;
|
|
22900
|
+
if (progressRingRef.current) {
|
|
22901
|
+
const offset = RING_CIRCUMFERENCE2 * (1 - target / 100);
|
|
22902
|
+
progressRingRef.current.style.strokeDashoffset = String(offset);
|
|
22903
|
+
}
|
|
22904
|
+
if (progressEtaRef.current) {
|
|
22905
|
+
const remaining = Math.max(0, TARGET_SECONDS - Math.floor(elapsed));
|
|
22906
|
+
progressEtaRef.current.textContent = elapsed >= TARGET_SECONDS ? t2("Finalizing...") : `~${remaining}s`;
|
|
22907
|
+
}
|
|
22740
22908
|
if (progressStatusRef.current) {
|
|
22741
22909
|
const status = [...statuses].reverse().find((s) => val >= s.at);
|
|
22742
|
-
if (status
|
|
22910
|
+
if (status && status.text !== progressLastStageRef.current) {
|
|
22911
|
+
const el2 = progressStatusRef.current;
|
|
22912
|
+
el2.style.opacity = "0";
|
|
22913
|
+
setTimeout(() => {
|
|
22914
|
+
el2.textContent = status.text;
|
|
22915
|
+
el2.style.opacity = "1";
|
|
22916
|
+
}, 180);
|
|
22917
|
+
progressLastStageRef.current = status.text;
|
|
22918
|
+
}
|
|
22743
22919
|
}
|
|
22744
22920
|
}, 200);
|
|
22745
22921
|
return () => {
|
|
@@ -22751,8 +22927,9 @@ function PrimeStyleTryonInner({
|
|
|
22751
22927
|
clearInterval(progressIntervalRef.current);
|
|
22752
22928
|
progressIntervalRef.current = null;
|
|
22753
22929
|
}
|
|
22930
|
+
progressStartTsRef.current = null;
|
|
22754
22931
|
}
|
|
22755
|
-
}, [view]);
|
|
22932
|
+
}, [view, t2]);
|
|
22756
22933
|
reactExports.useEffect(() => {
|
|
22757
22934
|
return () => {
|
|
22758
22935
|
if (previewUrl) URL.revokeObjectURL(previewUrl);
|
|
@@ -23079,7 +23256,16 @@ function PrimeStyleTryonInner({
|
|
|
23079
23256
|
progressRef.current = 100;
|
|
23080
23257
|
if (progressBarRef.current) progressBarRef.current.style.width = "100%";
|
|
23081
23258
|
if (progressTextRef.current) progressTextRef.current.textContent = "100%";
|
|
23082
|
-
if (
|
|
23259
|
+
if (progressRingRef.current) progressRingRef.current.style.strokeDashoffset = "0";
|
|
23260
|
+
if (progressEtaRef.current) progressEtaRef.current.textContent = t2("Done");
|
|
23261
|
+
if (progressStatusRef.current) {
|
|
23262
|
+
const el2 = progressStatusRef.current;
|
|
23263
|
+
el2.style.opacity = "0";
|
|
23264
|
+
setTimeout(() => {
|
|
23265
|
+
el2.textContent = t2("Complete!");
|
|
23266
|
+
el2.style.opacity = "1";
|
|
23267
|
+
}, 180);
|
|
23268
|
+
}
|
|
23083
23269
|
cleanupJob();
|
|
23084
23270
|
setTryOnProcessing(false);
|
|
23085
23271
|
onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
|
|
@@ -23488,25 +23674,29 @@ function PrimeStyleTryonInner({
|
|
|
23488
23674
|
}
|
|
23489
23675
|
completedRef.current = false;
|
|
23490
23676
|
setTryOnProcessing(true);
|
|
23677
|
+
const vtoCategory = measurementTypeToVtoCategory(detectMeasurementType(productTitle));
|
|
23678
|
+
const isApparel = vtoCategory === "apparel";
|
|
23491
23679
|
const previewObjUrl = (overrideFile ? null : previewUrl) || URL.createObjectURL(file);
|
|
23492
23680
|
if (overrideFile || !previewUrl) setPreviewUrl(previewObjUrl);
|
|
23493
23681
|
modelPoseRef.current = null;
|
|
23494
23682
|
setBodyLandmarks(null);
|
|
23495
|
-
|
|
23496
|
-
|
|
23497
|
-
|
|
23498
|
-
|
|
23499
|
-
|
|
23500
|
-
|
|
23501
|
-
|
|
23502
|
-
|
|
23683
|
+
if (isApparel) {
|
|
23684
|
+
detectMeasurementLines(previewObjUrl).then((lines) => {
|
|
23685
|
+
modelPoseRef.current = lines;
|
|
23686
|
+
}).catch(() => {
|
|
23687
|
+
});
|
|
23688
|
+
detectBodyLandmarks(previewObjUrl).then((lm) => {
|
|
23689
|
+
setBodyLandmarks(lm);
|
|
23690
|
+
}).catch(() => {
|
|
23691
|
+
});
|
|
23692
|
+
}
|
|
23503
23693
|
try {
|
|
23504
23694
|
const modelImage = await compressImage(file);
|
|
23505
23695
|
let fitInfo;
|
|
23506
|
-
if (sizingResult?.matchDetails?.length) {
|
|
23696
|
+
if (isApparel && sizingResult?.matchDetails?.length) {
|
|
23507
23697
|
fitInfo = buildFitInfo(sizingResult.matchDetails, modelPoseRef.current);
|
|
23508
23698
|
}
|
|
23509
|
-
const response = await apiRef.current.submitTryOn(modelImage, productImage, fitInfo);
|
|
23699
|
+
const response = await apiRef.current.submitTryOn(modelImage, productImage, fitInfo, vtoCategory ?? "apparel");
|
|
23510
23700
|
onProcessing?.(response.jobId);
|
|
23511
23701
|
unsubRef.current = sseRef.current.onJob(response.jobId, handleVtoUpdate);
|
|
23512
23702
|
let attempts = 0;
|
|
@@ -23537,11 +23727,13 @@ function PrimeStyleTryonInner({
|
|
|
23537
23727
|
setView("error");
|
|
23538
23728
|
onError?.({ message, code });
|
|
23539
23729
|
}
|
|
23540
|
-
}, [selectedFile, productImage, sizingResult, onProcessing, onError, handleVtoUpdate]);
|
|
23730
|
+
}, [selectedFile, productImage, productTitle, sizingResult, onProcessing, onError, handleVtoUpdate]);
|
|
23541
23731
|
const handleRetryWithFit = reactExports.useCallback(async (fitInfo) => {
|
|
23542
23732
|
if (!selectedFile || !apiRef.current || !sseRef.current) return;
|
|
23543
23733
|
setRetryLoading(true);
|
|
23544
|
-
|
|
23734
|
+
const vtoCategory = measurementTypeToVtoCategory(detectMeasurementType(productTitle));
|
|
23735
|
+
const isApparel = vtoCategory === "apparel";
|
|
23736
|
+
if (isApparel && modelPoseRef.current) {
|
|
23545
23737
|
const AREA_MAP = {
|
|
23546
23738
|
chest: "chest",
|
|
23547
23739
|
bust: "chest",
|
|
@@ -23567,7 +23759,8 @@ function PrimeStyleTryonInner({
|
|
|
23567
23759
|
pollingRef.current = null;
|
|
23568
23760
|
}
|
|
23569
23761
|
const modelImage = await compressImage(selectedFile);
|
|
23570
|
-
const
|
|
23762
|
+
const outboundFitInfo = isApparel ? fitInfo : void 0;
|
|
23763
|
+
const response = await apiRef.current.submitTryOn(modelImage, productImage, outboundFitInfo, vtoCategory ?? "apparel");
|
|
23571
23764
|
unsubRef.current = sseRef.current.onJob(response.jobId, (update) => {
|
|
23572
23765
|
if (update.status === "completed" && update.imageUrl) {
|
|
23573
23766
|
setResultImageUrl(update.imageUrl);
|
|
@@ -23632,7 +23825,7 @@ function PrimeStyleTryonInner({
|
|
|
23632
23825
|
} catch {
|
|
23633
23826
|
setRetryLoading(false);
|
|
23634
23827
|
}
|
|
23635
|
-
}, [selectedFile, productImage]);
|
|
23828
|
+
}, [selectedFile, productImage, productTitle]);
|
|
23636
23829
|
const handleDownload = reactExports.useCallback(() => {
|
|
23637
23830
|
if (!resultImageUrl) return;
|
|
23638
23831
|
if (resultImageUrl.startsWith("data:")) {
|
|
@@ -24074,6 +24267,8 @@ function PrimeStyleTryonInner({
|
|
|
24074
24267
|
progressBarRef,
|
|
24075
24268
|
progressTextRef,
|
|
24076
24269
|
progressStatusRef,
|
|
24270
|
+
progressEtaRef,
|
|
24271
|
+
progressRingRef,
|
|
24077
24272
|
cn,
|
|
24078
24273
|
t: t2
|
|
24079
24274
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primestyleai/tryon",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.9.0",
|
|
4
4
|
"description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/primestyle-tryon.js",
|
|
@@ -60,8 +60,5 @@
|
|
|
60
60
|
"terser": "^5.31.0",
|
|
61
61
|
"typescript": "^5.5.0",
|
|
62
62
|
"vite": "^5.4.0"
|
|
63
|
-
},
|
|
64
|
-
"dependencies": {
|
|
65
|
-
"@primestyleai/tryon": "^5.8.46"
|
|
66
63
|
}
|
|
67
64
|
}
|