@primestyleai/tryon 5.10.188 → 5.10.189
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 +4 -0
- package/dist/{index-BduSFARG.js → index-BlzviBfP.js} +57 -75
- package/dist/index-BlzviBfP.js.map +1 -0
- package/dist/primestyle-tryon.js +2 -2
- package/dist/react/PrimeStyleTryonInner.d.ts +1 -1
- package/dist/react/icons.d.ts +6 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +6613 -6024
- package/dist/react/index.js.map +1 -1
- package/dist/react/styles.d.ts +1 -1
- package/dist/react/types.d.ts +23 -0
- package/dist/react/usePrimeStyleSize.d.ts +2 -0
- package/dist/react/views/BodyProfileView.d.ts +3 -1
- package/dist/react/views/MultiSectionMobile.d.ts +3 -1
- package/dist/react/views/PhotoStepMobile.d.ts +2 -1
- package/dist/react/views/SizeResultView.d.ts +7 -1
- package/dist/storefront/primestyle-tryon.js +1003 -353
- package/package.json +1 -1
- package/dist/index-BduSFARG.js.map +0 -1
package/dist/api-client.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ export interface TryOnContext {
|
|
|
15
15
|
* — forwarded to the prompt so Gemini drapes the fabric correctly without
|
|
16
16
|
* having to guess from the image alone. */
|
|
17
17
|
productMaterial?: string;
|
|
18
|
+
/** Optional clean product/detail image. The backend sends it to Gemini as an
|
|
19
|
+
* additional design reference while `garmentImage` remains the worn/model
|
|
20
|
+
* styling reference. */
|
|
21
|
+
garmentDetailImage?: string;
|
|
18
22
|
/** Optional silhouette-prompt context forwarded to the backend Gemini try-on
|
|
19
23
|
* call. Enables doc-example-grade fit reasoning ("X tension at button
|
|
20
24
|
* because waist 54.4 exceeds size 50 drop"). All fields optional. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const f = "ps_session";
|
|
3
|
+
const A = "ps_mem_";
|
|
4
4
|
let S = null;
|
|
5
5
|
function E() {
|
|
6
6
|
try {
|
|
@@ -9,20 +9,20 @@ function E() {
|
|
|
9
9
|
return !1;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
function
|
|
12
|
+
function P() {
|
|
13
13
|
if (typeof crypto < "u" && typeof crypto.randomUUID == "function")
|
|
14
14
|
return crypto.randomUUID();
|
|
15
|
-
const
|
|
16
|
-
let e =
|
|
17
|
-
for (let o = 0; o < 32; o++) e +=
|
|
15
|
+
const r = "0123456789abcdef";
|
|
16
|
+
let e = A;
|
|
17
|
+
for (let o = 0; o < 32; o++) e += r[Math.floor(Math.random() * 16)];
|
|
18
18
|
return e;
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function I() {
|
|
21
21
|
if (!E()) return S;
|
|
22
22
|
try {
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
25
|
-
const e = JSON.parse(
|
|
23
|
+
const r = window.localStorage.getItem(f);
|
|
24
|
+
if (!r) return null;
|
|
25
|
+
const e = JSON.parse(r);
|
|
26
26
|
return typeof e.id != "string" || typeof e.issuedAt != "number" ? null : {
|
|
27
27
|
id: e.id,
|
|
28
28
|
issuedAt: e.issuedAt,
|
|
@@ -32,43 +32,43 @@ function T() {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
function g(
|
|
36
|
-
if (S =
|
|
35
|
+
function g(r) {
|
|
36
|
+
if (S = r, !!E())
|
|
37
37
|
try {
|
|
38
|
-
window.localStorage.setItem(
|
|
38
|
+
window.localStorage.setItem(f, JSON.stringify(r));
|
|
39
39
|
} catch {
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
function p() {
|
|
43
|
-
const
|
|
44
|
-
if (e &&
|
|
45
|
-
return
|
|
46
|
-
const o = { id:
|
|
43
|
+
const r = Date.now(), e = I();
|
|
44
|
+
if (e && r - e.lastSeenAt < 2592e6)
|
|
45
|
+
return r - e.lastSeenAt > 5 * 60 * 1e3 && g({ ...e, lastSeenAt: r }), e.id;
|
|
46
|
+
const o = { id: P(), issuedAt: r, lastSeenAt: r };
|
|
47
47
|
return g(o), o.id;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function y() {
|
|
50
50
|
if (typeof navigator > "u") return null;
|
|
51
|
-
const
|
|
52
|
-
return /ipad|tablet|(android(?!.*mobile))/.test(
|
|
51
|
+
const r = (navigator.userAgent || "").toLowerCase();
|
|
52
|
+
return /ipad|tablet|(android(?!.*mobile))/.test(r) ? "tablet" : /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(r) ? "mobile" : "desktop";
|
|
53
53
|
}
|
|
54
|
-
const
|
|
54
|
+
const T = "http://localhost:4000";
|
|
55
55
|
class W {
|
|
56
56
|
constructor(e, o) {
|
|
57
|
-
this.apiKey = e || void 0, this.baseUrl = (o ||
|
|
57
|
+
this.apiKey = e || void 0, this.baseUrl = (o || T).replace(/\/+$/, "");
|
|
58
58
|
}
|
|
59
59
|
get headers() {
|
|
60
60
|
return w(this.apiKey);
|
|
61
61
|
}
|
|
62
|
-
async submitTryOn(e, o, a, s,
|
|
62
|
+
async submitTryOn(e, o, a, s, t) {
|
|
63
63
|
const i = {
|
|
64
64
|
garmentImage: o,
|
|
65
65
|
// Attribution fields — backend logs these into the TryOnEvent collection
|
|
66
66
|
// so non-technical operators can answer "which products are being tried on
|
|
67
67
|
// and by how many customers". Safe fallbacks when absent.
|
|
68
68
|
sessionId: p(),
|
|
69
|
-
deviceHint:
|
|
69
|
+
deviceHint: y()
|
|
70
70
|
};
|
|
71
|
-
if (
|
|
71
|
+
if (t?.modelImageId && (i.modelImageId = t.modelImageId), e && (i.modelImage = e), a && a.length > 0 && (i.fitInfo = a), s && s !== "apparel" && (i.category = s), t?.productId && (i.productId = t.productId), t?.productTitle && (i.productTitle = t.productTitle), t?.productCategory && (i.productCategory = t.productCategory), t?.productSubcategory && (i.productSubcategory = t.productSubcategory), t?.productFitType && (i.productFitType = t.productFitType), t?.productType && (i.productType = t.productType), t?.productTags?.length && (i.productTags = t.productTags), t?.productDescription && (i.productDescription = t.productDescription), t?.productMaterial && (i.productMaterial = t.productMaterial), t?.garmentDetailImage && t.garmentDetailImage !== o && (i.garmentDetailImage = t.garmentDetailImage), t?.silhouetteContext && (i.silhouetteContext = t.silhouetteContext), t?.editFromPrevious && (i.editFromPrevious = !0), a && a.length > 0)
|
|
72
72
|
for (const n of a) {
|
|
73
73
|
const l = (n.garmentRange || "").replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((u) => !isNaN(u));
|
|
74
74
|
if (l.length && n.userValue != null) {
|
|
@@ -113,7 +113,7 @@ class W {
|
|
|
113
113
|
body: JSON.stringify({
|
|
114
114
|
...e,
|
|
115
115
|
sessionId: p(),
|
|
116
|
-
deviceHint:
|
|
116
|
+
deviceHint: y()
|
|
117
117
|
})
|
|
118
118
|
});
|
|
119
119
|
if (!o.ok) {
|
|
@@ -130,9 +130,9 @@ class W {
|
|
|
130
130
|
return this.apiKey ? `${e}?key=${encodeURIComponent(this.apiKey)}` : e;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
-
function w(
|
|
133
|
+
function w(r) {
|
|
134
134
|
const e = { "Content-Type": "application/json" };
|
|
135
|
-
return
|
|
135
|
+
return r && (e.Authorization = `Bearer ${r}`), e;
|
|
136
136
|
}
|
|
137
137
|
class h extends Error {
|
|
138
138
|
constructor(e, o) {
|
|
@@ -191,9 +191,9 @@ class Y {
|
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
const v = 512, C = 0.65;
|
|
194
|
-
function z(
|
|
194
|
+
function z(r, e = {}) {
|
|
195
195
|
const o = e.maxDimension ?? v, a = e.quality ?? C;
|
|
196
|
-
return new Promise((s,
|
|
196
|
+
return new Promise((s, t) => {
|
|
197
197
|
const i = new FileReader();
|
|
198
198
|
i.onload = () => {
|
|
199
199
|
const d = new Image();
|
|
@@ -204,25 +204,25 @@ function z(t, e = {}) {
|
|
|
204
204
|
(l > o || u > o) && (l > u ? (u = Math.round(u * o / l), l = o) : (l = Math.round(l * o / u), u = o)), n.width = l, n.height = u;
|
|
205
205
|
const m = n.getContext("2d");
|
|
206
206
|
if (!m) {
|
|
207
|
-
|
|
207
|
+
t(new Error("Canvas context not available"));
|
|
208
208
|
return;
|
|
209
209
|
}
|
|
210
210
|
m.drawImage(d, 0, 0, l, u);
|
|
211
211
|
const b = n.toDataURL("image/jpeg", a);
|
|
212
212
|
s(b);
|
|
213
213
|
} catch (n) {
|
|
214
|
-
|
|
214
|
+
t(n);
|
|
215
215
|
}
|
|
216
|
-
}, d.onerror = () =>
|
|
217
|
-
}, i.onerror = () =>
|
|
216
|
+
}, d.onerror = () => t(new Error("Failed to load image")), d.src = i.result;
|
|
217
|
+
}, i.onerror = () => t(new Error("Failed to read file")), i.readAsDataURL(r);
|
|
218
218
|
});
|
|
219
219
|
}
|
|
220
|
-
function F(
|
|
221
|
-
return ["image/jpeg", "image/png", "image/webp", "image/avif"].includes(
|
|
220
|
+
function F(r) {
|
|
221
|
+
return ["image/jpeg", "image/png", "image/webp", "image/avif"].includes(r.type);
|
|
222
222
|
}
|
|
223
|
-
async function K(
|
|
223
|
+
async function K(r, e, o) {
|
|
224
224
|
try {
|
|
225
|
-
const a = typeof
|
|
225
|
+
const a = typeof r == "string" ? r : await z(r, { maxDimension: 384, quality: 0.6 }), s = await fetch(`${e}/api/v1/sizing/age-check`, {
|
|
226
226
|
method: "POST",
|
|
227
227
|
headers: {
|
|
228
228
|
"Content-Type": "application/json",
|
|
@@ -232,24 +232,24 @@ async function K(t, e, o) {
|
|
|
232
232
|
});
|
|
233
233
|
if (!s.ok)
|
|
234
234
|
return { isAdult: !0, confidence: "low" };
|
|
235
|
-
const
|
|
235
|
+
const t = await s.json();
|
|
236
236
|
return {
|
|
237
|
-
isAdult:
|
|
237
|
+
isAdult: t?.isAdult !== !1,
|
|
238
238
|
// anything other than explicit false → allow
|
|
239
|
-
confidence:
|
|
240
|
-
detectedGender:
|
|
241
|
-
reasoning: typeof
|
|
239
|
+
confidence: t?.confidence === "high" ? "high" : "low",
|
|
240
|
+
detectedGender: t?.detectedGender === "male" || t?.detectedGender === "female" || t?.detectedGender === "unknown" ? t.detectedGender : void 0,
|
|
241
|
+
reasoning: typeof t?.reasoning == "string" ? t.reasoning : void 0
|
|
242
242
|
};
|
|
243
243
|
} catch {
|
|
244
244
|
return { isAdult: !0, confidence: "low" };
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
247
|
const c = {};
|
|
248
|
-
function U(
|
|
249
|
-
c[
|
|
248
|
+
function U(r, e) {
|
|
249
|
+
c[r] = { ...c[r] || {}, ...e };
|
|
250
250
|
}
|
|
251
|
-
function V(
|
|
252
|
-
const e =
|
|
251
|
+
function V(r) {
|
|
252
|
+
const e = r?.toLowerCase().split("-")[0] || "en";
|
|
253
253
|
return (o) => e === "en" || !c[e] ? o : c[e][o] ?? o;
|
|
254
254
|
}
|
|
255
255
|
function j() {
|
|
@@ -607,8 +607,6 @@ const J = [
|
|
|
607
607
|
Loose: "Holgado",
|
|
608
608
|
Short: "Corto",
|
|
609
609
|
Long: "Largo",
|
|
610
|
-
Perfect: "Perfecto",
|
|
611
|
-
"Perfect fit": "Ajuste perfecto",
|
|
612
610
|
"✓ Fit": "✓ Ajuste",
|
|
613
611
|
"too short": "demasiado corto",
|
|
614
612
|
"too long": "demasiado largo",
|
|
@@ -864,8 +862,6 @@ const J = [
|
|
|
864
862
|
Loose: "Lâche",
|
|
865
863
|
Short: "Court",
|
|
866
864
|
Long: "Long",
|
|
867
|
-
Perfect: "Parfait",
|
|
868
|
-
"Perfect fit": "Ajustement parfait",
|
|
869
865
|
"✓ Fit": "✓ Ajusté",
|
|
870
866
|
"too short": "trop court",
|
|
871
867
|
"too long": "trop long",
|
|
@@ -1121,8 +1117,6 @@ const J = [
|
|
|
1121
1117
|
Loose: "Locker",
|
|
1122
1118
|
Short: "Kurz",
|
|
1123
1119
|
Long: "Lang",
|
|
1124
|
-
Perfect: "Perfekt",
|
|
1125
|
-
"Perfect fit": "Perfekte Passform",
|
|
1126
1120
|
"✓ Fit": "✓ Passt",
|
|
1127
1121
|
"too short": "zu kurz",
|
|
1128
1122
|
"too long": "zu lang",
|
|
@@ -1378,8 +1372,6 @@ const J = [
|
|
|
1378
1372
|
Loose: "Largo",
|
|
1379
1373
|
Short: "Corto",
|
|
1380
1374
|
Long: "Lungo",
|
|
1381
|
-
Perfect: "Perfetto",
|
|
1382
|
-
"Perfect fit": "Vestibilità perfetta",
|
|
1383
1375
|
"✓ Fit": "✓ Adatto",
|
|
1384
1376
|
"too short": "troppo corto",
|
|
1385
1377
|
"too long": "troppo lungo",
|
|
@@ -1635,8 +1627,6 @@ const J = [
|
|
|
1635
1627
|
Loose: "Folgado",
|
|
1636
1628
|
Short: "Curto",
|
|
1637
1629
|
Long: "Longo",
|
|
1638
|
-
Perfect: "Perfeito",
|
|
1639
|
-
"Perfect fit": "Caimento perfeito",
|
|
1640
1630
|
"✓ Fit": "✓ Caimento",
|
|
1641
1631
|
"too short": "muito curto",
|
|
1642
1632
|
"too long": "muito longo",
|
|
@@ -1892,8 +1882,6 @@ const J = [
|
|
|
1892
1882
|
Loose: "ゆるい",
|
|
1893
1883
|
Short: "短い",
|
|
1894
1884
|
Long: "長い",
|
|
1895
|
-
Perfect: "ぴったり",
|
|
1896
|
-
"Perfect fit": "ぴったりフィット",
|
|
1897
1885
|
"✓ Fit": "✓ フィット",
|
|
1898
1886
|
"too short": "短すぎる",
|
|
1899
1887
|
"too long": "長すぎる",
|
|
@@ -2149,8 +2137,6 @@ const J = [
|
|
|
2149
2137
|
Loose: "松",
|
|
2150
2138
|
Short: "短",
|
|
2151
2139
|
Long: "长",
|
|
2152
|
-
Perfect: "完美",
|
|
2153
|
-
"Perfect fit": "完美合身",
|
|
2154
2140
|
"✓ Fit": "✓ 合身",
|
|
2155
2141
|
"too short": "太短",
|
|
2156
2142
|
"too long": "太长",
|
|
@@ -2406,8 +2392,6 @@ const J = [
|
|
|
2406
2392
|
Loose: "헐렁한",
|
|
2407
2393
|
Short: "짧은",
|
|
2408
2394
|
Long: "긴",
|
|
2409
|
-
Perfect: "완벽",
|
|
2410
|
-
"Perfect fit": "완벽한 핏",
|
|
2411
2395
|
"✓ Fit": "✓ 적합",
|
|
2412
2396
|
"too short": "너무 짧음",
|
|
2413
2397
|
"too long": "너무 김",
|
|
@@ -2663,8 +2647,6 @@ const J = [
|
|
|
2663
2647
|
Loose: "فضفاض",
|
|
2664
2648
|
Short: "قصير",
|
|
2665
2649
|
Long: "طويل",
|
|
2666
|
-
Perfect: "مثالي",
|
|
2667
|
-
"Perfect fit": "مقاس مثالي",
|
|
2668
2650
|
"✓ Fit": "✓ مناسب",
|
|
2669
2651
|
"too short": "قصير جداً",
|
|
2670
2652
|
"too long": "طويل جداً",
|
|
@@ -2787,23 +2769,23 @@ const J = [
|
|
|
2787
2769
|
ko: L,
|
|
2788
2770
|
ar: G
|
|
2789
2771
|
};
|
|
2790
|
-
for (const [
|
|
2791
|
-
U(
|
|
2772
|
+
for (const [r, e] of Object.entries(O))
|
|
2773
|
+
U(r, e);
|
|
2792
2774
|
export {
|
|
2793
2775
|
W as A,
|
|
2794
2776
|
q as L,
|
|
2795
2777
|
h as P,
|
|
2796
|
-
|
|
2778
|
+
J as S,
|
|
2797
2779
|
Z as T,
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2780
|
+
Y as a,
|
|
2781
|
+
z as b,
|
|
2782
|
+
K as c,
|
|
2783
|
+
V as d,
|
|
2802
2784
|
j as e,
|
|
2803
|
-
f,
|
|
2804
|
-
|
|
2785
|
+
p as f,
|
|
2786
|
+
y as g,
|
|
2805
2787
|
F as i,
|
|
2806
2788
|
w as j,
|
|
2807
2789
|
U as r
|
|
2808
2790
|
};
|
|
2809
|
-
//# sourceMappingURL=index-
|
|
2791
|
+
//# sourceMappingURL=index-BlzviBfP.js.map
|