@primestyleai/tryon 5.10.103 → 5.10.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/PrimeStyleTryonInner.d.ts +1 -1
- package/dist/react/index.js +4012 -3972
- package/dist/react/index.js.map +1 -1
- package/dist/react/types.d.ts +14 -3
- package/dist/react/utils/pickBestGarmentImage.d.ts +1 -0
- package/dist/storefront/primestyle-tryon.js +51 -1
- package/package.json +1 -1
package/dist/react/types.d.ts
CHANGED
|
@@ -139,10 +139,21 @@ export type ViewState = "idle" | "welcome" | "body-profile" | "estimation-review
|
|
|
139
139
|
export type DrawerType = "profiles" | "history" | null;
|
|
140
140
|
export interface PrimeStyleTryonProps {
|
|
141
141
|
productImage: string;
|
|
142
|
-
/** Optional gallery of product photos for the active color/variant.
|
|
143
|
-
*
|
|
144
|
-
*
|
|
142
|
+
/** Optional gallery of product photos for the active color/variant.
|
|
143
|
+
*
|
|
144
|
+
* - Shown as an auto-cycling carousel on the single-garment
|
|
145
|
+
* SizeResultView while the try-on image is being generated.
|
|
146
|
+
* - At try-on time the SDK runs MediaPipe BlazePose on every entry in
|
|
147
|
+
* parallel and forwards the highest-scoring "model wearing the
|
|
148
|
+
* garment" shot to Gemini as image 2. Flat-lays / close-up details
|
|
149
|
+
* score ~0 and are skipped. The first image still shows in the UI
|
|
150
|
+
* unchanged. */
|
|
145
151
|
productImages?: string[];
|
|
152
|
+
/** Optional explicit override — if you already know which image in the
|
|
153
|
+
* gallery is the model-wearing-the-garment shot, pass it here and the
|
|
154
|
+
* SDK skips the MediaPipe-based auto-pick. Falls through to auto-pick
|
|
155
|
+
* (or to `productImage`) when omitted. */
|
|
156
|
+
garmentReferenceImage?: string;
|
|
146
157
|
productTitle?: string;
|
|
147
158
|
/** Stable product identifier — used to cache size recommendations per (profile, product) */
|
|
148
159
|
productId?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function pickBestGarmentImage(images: string[] | null | undefined): Promise<string | null>;
|
|
@@ -10588,6 +10588,45 @@ function getUnitLabel(unit) {
|
|
|
10588
10588
|
if (unit === "mm") return "mm";
|
|
10589
10589
|
return "";
|
|
10590
10590
|
}
|
|
10591
|
+
const cache = /* @__PURE__ */ new Map();
|
|
10592
|
+
function scoreLandmarks(lm) {
|
|
10593
|
+
if (!lm) return 0;
|
|
10594
|
+
let joints = 0;
|
|
10595
|
+
for (const [k2, v2] of Object.entries(lm)) {
|
|
10596
|
+
if (k2 === "imageWidth" || k2 === "imageHeight") continue;
|
|
10597
|
+
if (v2 && typeof v2 === "object" && typeof v2.x === "number") joints++;
|
|
10598
|
+
}
|
|
10599
|
+
let score = joints * 10;
|
|
10600
|
+
if (lm.nose) score += 50;
|
|
10601
|
+
if (lm.leftAnkle && lm.rightAnkle) score += 5;
|
|
10602
|
+
return score;
|
|
10603
|
+
}
|
|
10604
|
+
async function scoreImage(url) {
|
|
10605
|
+
try {
|
|
10606
|
+
const lm = await detectBodyLandmarks(url);
|
|
10607
|
+
return scoreLandmarks(lm);
|
|
10608
|
+
} catch {
|
|
10609
|
+
return 0;
|
|
10610
|
+
}
|
|
10611
|
+
}
|
|
10612
|
+
async function pickBestGarmentImage(images) {
|
|
10613
|
+
if (!images || !images.length) return null;
|
|
10614
|
+
if (images.length === 1) return images[0];
|
|
10615
|
+
const cacheKey = images.join("|");
|
|
10616
|
+
const cached = cache.get(cacheKey);
|
|
10617
|
+
if (cached) return cached;
|
|
10618
|
+
const t0 = Date.now();
|
|
10619
|
+
const scored = await Promise.all(images.map(async (url) => ({
|
|
10620
|
+
url,
|
|
10621
|
+
score: await scoreImage(url)
|
|
10622
|
+
})));
|
|
10623
|
+
scored.sort((a, b) => b.score - a.score);
|
|
10624
|
+
const best = (scored[0]?.score ?? 0) > 0 ? scored[0].url : images[0];
|
|
10625
|
+
cache.set(cacheKey, best);
|
|
10626
|
+
console.log(`[ps-sdk:garment-pick] ${Date.now() - t0}ms — chose ${images.indexOf(best)}/${images.length}`);
|
|
10627
|
+
for (const s of scored) console.log(`[ps-sdk:garment-pick] ${s.score.toString().padStart(4, " ")} ${s.url}`);
|
|
10628
|
+
return best;
|
|
10629
|
+
}
|
|
10591
10630
|
function cx(base, override) {
|
|
10592
10631
|
return override ? `${base} ${override}` : base;
|
|
10593
10632
|
}
|
|
@@ -27672,6 +27711,7 @@ function measurementTypeToVtoCategory(type) {
|
|
|
27672
27711
|
function PrimeStyleTryonInner({
|
|
27673
27712
|
productImage,
|
|
27674
27713
|
productImages,
|
|
27714
|
+
garmentReferenceImage,
|
|
27675
27715
|
productTitle = "Product",
|
|
27676
27716
|
productId,
|
|
27677
27717
|
productDescription,
|
|
@@ -28837,9 +28877,19 @@ function PrimeStyleTryonInner({
|
|
|
28837
28877
|
fitInfo = buildFitInfo(effectiveMatchDetails, modelPoseRef.current, unit);
|
|
28838
28878
|
}
|
|
28839
28879
|
console.log("[ps-sdk:tryon] fitInfo built", { count: fitInfo?.length || 0, areas: fitInfo?.map((f2) => `${f2.area}(${f2.fit})`) });
|
|
28880
|
+
let garmentImage = productImage;
|
|
28881
|
+
if (garmentReferenceImage) {
|
|
28882
|
+
garmentImage = garmentReferenceImage;
|
|
28883
|
+
} else if (productImages && productImages.length > 1) {
|
|
28884
|
+
const best = await pickBestGarmentImage(productImages);
|
|
28885
|
+
if (best && best !== productImage) {
|
|
28886
|
+
console.log(`[ps-sdk:tryon] auto-picked garment reference: ${best}`);
|
|
28887
|
+
garmentImage = best;
|
|
28888
|
+
}
|
|
28889
|
+
}
|
|
28840
28890
|
const response = await apiRef.current.submitTryOn(
|
|
28841
28891
|
modelImage,
|
|
28842
|
-
|
|
28892
|
+
garmentImage,
|
|
28843
28893
|
fitInfo,
|
|
28844
28894
|
vtoCategory ?? "apparel",
|
|
28845
28895
|
{
|