@primestyleai/tryon 3.7.0 → 3.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/PrimeStyleTryon.d.ts +1 -0
- package/dist/i18n/cs.d.ts +5 -0
- package/dist/i18n/da.d.ts +5 -0
- package/dist/i18n/de.d.ts +5 -0
- package/dist/i18n/en.d.ts +9 -0
- package/dist/i18n/es.d.ts +5 -0
- package/dist/i18n/fi.d.ts +5 -0
- package/dist/i18n/fr.d.ts +5 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/i18n/it.d.ts +5 -0
- package/dist/i18n/ja.d.ts +5 -0
- package/dist/i18n/ko.d.ts +5 -0
- package/dist/i18n/nb.d.ts +5 -0
- package/dist/i18n/nl.d.ts +5 -0
- package/dist/i18n/pl.d.ts +5 -0
- package/dist/i18n/pt-br.d.ts +5 -0
- package/dist/i18n/pt-pt.d.ts +5 -0
- package/dist/i18n/sv.d.ts +5 -0
- package/dist/i18n/th.d.ts +5 -0
- package/dist/i18n/tr.d.ts +5 -0
- package/dist/i18n/zh-cn.d.ts +5 -0
- package/dist/i18n/zh-tw.d.ts +5 -0
- package/dist/index-B0KE3c8S.js +2951 -0
- package/dist/index.d.ts +2 -0
- package/dist/primestyle-tryon.js +35 -24
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.js +618 -221
- package/dist/sizing/constants.d.ts +13 -0
- package/dist/sizing/normalizer.d.ts +35 -0
- package/dist/types.d.ts +47 -0
- package/package.json +1 -1
- package/dist/image-utils-C9bJ1zKO.js +0 -186
package/dist/react/index.js
CHANGED
|
@@ -1,7 +1,366 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect,
|
|
4
|
-
import { A as ApiClient, S as SseClient, i as isValidImageFile,
|
|
3
|
+
import { useState, useEffect, useMemo, useRef, useCallback } from "react";
|
|
4
|
+
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError } from "../index-B0KE3c8S.js";
|
|
5
|
+
const HEADER_ALIASES = {
|
|
6
|
+
// ── Size label columns (skipped during field derivation) ──
|
|
7
|
+
size: "__size__",
|
|
8
|
+
sizes: "__size__",
|
|
9
|
+
label: "__size__",
|
|
10
|
+
taglia: "__size__",
|
|
11
|
+
// IT
|
|
12
|
+
taille: "__size__",
|
|
13
|
+
// FR
|
|
14
|
+
größe: "__size__",
|
|
15
|
+
// DE
|
|
16
|
+
groesse: "__size__",
|
|
17
|
+
tamaño: "__size__",
|
|
18
|
+
// ES
|
|
19
|
+
サイズ: "__size__",
|
|
20
|
+
// JP
|
|
21
|
+
// ── Chest / Bust ──
|
|
22
|
+
chest: "chest",
|
|
23
|
+
"chest (cm)": "chest",
|
|
24
|
+
"chest(cm)": "chest",
|
|
25
|
+
"chest (in)": "chest",
|
|
26
|
+
bust: "bust",
|
|
27
|
+
"bust (cm)": "bust",
|
|
28
|
+
"bust(cm)": "bust",
|
|
29
|
+
"bust (in)": "bust",
|
|
30
|
+
"chest/bust": "chest",
|
|
31
|
+
"chest / bust": "chest",
|
|
32
|
+
petto: "chest",
|
|
33
|
+
// IT
|
|
34
|
+
poitrine: "bust",
|
|
35
|
+
// FR
|
|
36
|
+
brust: "chest",
|
|
37
|
+
// DE
|
|
38
|
+
// ── Waist ──
|
|
39
|
+
waist: "waist",
|
|
40
|
+
"waist (cm)": "waist",
|
|
41
|
+
"waist(cm)": "waist",
|
|
42
|
+
"waist (in)": "waist",
|
|
43
|
+
vita: "waist",
|
|
44
|
+
// IT
|
|
45
|
+
taille_mesure: "waist",
|
|
46
|
+
// FR (disambiguation from size label)
|
|
47
|
+
"tour de taille": "waist",
|
|
48
|
+
taille_cm: "waist",
|
|
49
|
+
// ── Hips ──
|
|
50
|
+
hips: "hips",
|
|
51
|
+
hip: "hips",
|
|
52
|
+
"hips (cm)": "hips",
|
|
53
|
+
"hip (cm)": "hips",
|
|
54
|
+
"hips(cm)": "hips",
|
|
55
|
+
"hips (in)": "hips",
|
|
56
|
+
fianchi: "hips",
|
|
57
|
+
// IT
|
|
58
|
+
hanches: "hips",
|
|
59
|
+
// FR
|
|
60
|
+
hüfte: "hips",
|
|
61
|
+
// DE
|
|
62
|
+
// ── Shoulder ──
|
|
63
|
+
shoulder: "shoulderWidth",
|
|
64
|
+
shoulders: "shoulderWidth",
|
|
65
|
+
"shoulder width": "shoulderWidth",
|
|
66
|
+
"shoulder (cm)": "shoulderWidth",
|
|
67
|
+
"shoulders (cm)": "shoulderWidth",
|
|
68
|
+
"shoulder width (cm)": "shoulderWidth",
|
|
69
|
+
spalle: "shoulderWidth",
|
|
70
|
+
// IT
|
|
71
|
+
épaules: "shoulderWidth",
|
|
72
|
+
// FR
|
|
73
|
+
schulter: "shoulderWidth",
|
|
74
|
+
// DE
|
|
75
|
+
// ── Sleeve ──
|
|
76
|
+
sleeve: "sleeveLength",
|
|
77
|
+
"sleeve length": "sleeveLength",
|
|
78
|
+
"sleeve (cm)": "sleeveLength",
|
|
79
|
+
"sleeve length (cm)": "sleeveLength",
|
|
80
|
+
manica: "sleeveLength",
|
|
81
|
+
// IT
|
|
82
|
+
manche: "sleeveLength",
|
|
83
|
+
// FR
|
|
84
|
+
ärmel: "sleeveLength",
|
|
85
|
+
// DE
|
|
86
|
+
// ── Inseam ──
|
|
87
|
+
inseam: "inseam",
|
|
88
|
+
"inseam (cm)": "inseam",
|
|
89
|
+
"inseam(cm)": "inseam",
|
|
90
|
+
"inseam (in)": "inseam",
|
|
91
|
+
"inside leg": "inseam",
|
|
92
|
+
"inside leg (cm)": "inseam",
|
|
93
|
+
cavallo: "inseam",
|
|
94
|
+
// IT
|
|
95
|
+
entrejambe: "inseam",
|
|
96
|
+
// FR
|
|
97
|
+
// ── Neck ──
|
|
98
|
+
neck: "neckCircumference",
|
|
99
|
+
collar: "neckCircumference",
|
|
100
|
+
"neck (cm)": "neckCircumference",
|
|
101
|
+
"collar (cm)": "neckCircumference",
|
|
102
|
+
collo: "neckCircumference",
|
|
103
|
+
// IT
|
|
104
|
+
col: "neckCircumference",
|
|
105
|
+
// FR
|
|
106
|
+
// ── Length (body/garment) ──
|
|
107
|
+
length: "length",
|
|
108
|
+
"body length": "length",
|
|
109
|
+
"length (cm)": "length",
|
|
110
|
+
"body length (cm)": "length",
|
|
111
|
+
lunghezza: "length",
|
|
112
|
+
// IT
|
|
113
|
+
longueur: "length",
|
|
114
|
+
// FR
|
|
115
|
+
// ── Thigh ──
|
|
116
|
+
thigh: "thighCircumference",
|
|
117
|
+
"thigh (cm)": "thighCircumference",
|
|
118
|
+
coscia: "thighCircumference",
|
|
119
|
+
// IT
|
|
120
|
+
// ── Foot / Shoe ──
|
|
121
|
+
"foot length": "footLengthCm",
|
|
122
|
+
"foot length (cm)": "footLengthCm",
|
|
123
|
+
"foot (cm)": "footLengthCm",
|
|
124
|
+
cm: "footLengthCm",
|
|
125
|
+
eu: "shoeEU",
|
|
126
|
+
"eu size": "shoeEU",
|
|
127
|
+
eur: "shoeEU",
|
|
128
|
+
us: "shoeUS",
|
|
129
|
+
"us size": "shoeUS",
|
|
130
|
+
uk: "shoeUK",
|
|
131
|
+
"uk size": "shoeUK"
|
|
132
|
+
};
|
|
133
|
+
const FIELD_LABELS = {
|
|
134
|
+
chest: "Chest",
|
|
135
|
+
bust: "Bust",
|
|
136
|
+
waist: "Waist",
|
|
137
|
+
hips: "Hips",
|
|
138
|
+
shoulderWidth: "Shoulders",
|
|
139
|
+
sleeveLength: "Sleeve Length",
|
|
140
|
+
inseam: "Inseam",
|
|
141
|
+
neckCircumference: "Neck",
|
|
142
|
+
length: "Length",
|
|
143
|
+
thighCircumference: "Thigh",
|
|
144
|
+
footLengthCm: "Foot Length",
|
|
145
|
+
shoeEU: "Shoe Size (EU)",
|
|
146
|
+
shoeUS: "Shoe Size (US)",
|
|
147
|
+
shoeUK: "Shoe Size (UK)"
|
|
148
|
+
};
|
|
149
|
+
const FIELD_PLACEHOLDERS = {
|
|
150
|
+
chest: "e.g. 104",
|
|
151
|
+
bust: "e.g. 88",
|
|
152
|
+
waist: "e.g. 84",
|
|
153
|
+
hips: "e.g. 96",
|
|
154
|
+
shoulderWidth: "e.g. 46",
|
|
155
|
+
sleeveLength: "e.g. 64",
|
|
156
|
+
inseam: "e.g. 81",
|
|
157
|
+
neckCircumference: "e.g. 40",
|
|
158
|
+
length: "e.g. 72",
|
|
159
|
+
thighCircumference: "e.g. 58",
|
|
160
|
+
footLengthCm: "e.g. 27",
|
|
161
|
+
shoeEU: "e.g. 42",
|
|
162
|
+
shoeUS: "e.g. 9",
|
|
163
|
+
shoeUK: "e.g. 8"
|
|
164
|
+
};
|
|
165
|
+
const SIZE_LABEL_PATTERN = /^(XXS|XS|S|M|L|XL|XXL|XXXL|2XL|3XL|4XL|5XL|\d{2,3}(\/\d{2,3})?(R|S|L)?|ONE\s*SIZE)$/i;
|
|
166
|
+
const SHOE_FIELD_KEYS = /* @__PURE__ */ new Set(["shoeEU", "shoeUS", "shoeUK", "footLengthCm"]);
|
|
167
|
+
function resolveHeaderKey(header) {
|
|
168
|
+
const cleaned = header.toLowerCase().trim().replace(/\(.*?\)/g, "").trim();
|
|
169
|
+
return HEADER_ALIASES[cleaned] ?? HEADER_ALIASES[header.toLowerCase().trim()] ?? null;
|
|
170
|
+
}
|
|
171
|
+
function deriveRequiredFields(headers) {
|
|
172
|
+
const fields = [];
|
|
173
|
+
const seen = /* @__PURE__ */ new Set();
|
|
174
|
+
for (const h of headers) {
|
|
175
|
+
const fieldKey = resolveHeaderKey(h);
|
|
176
|
+
if (!fieldKey || fieldKey === "__size__" || seen.has(fieldKey)) continue;
|
|
177
|
+
seen.add(fieldKey);
|
|
178
|
+
const isShoe = SHOE_FIELD_KEYS.has(fieldKey);
|
|
179
|
+
fields.push({
|
|
180
|
+
key: fieldKey,
|
|
181
|
+
label: FIELD_LABELS[fieldKey] || h,
|
|
182
|
+
required: true,
|
|
183
|
+
unit: isShoe && fieldKey !== "footLengthCm" ? "size" : "cm",
|
|
184
|
+
placeholder: FIELD_PLACEHOLDERS[fieldKey] || "",
|
|
185
|
+
category: isShoe ? "shoe" : "body"
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
fields.sort((a, b) => {
|
|
189
|
+
if (a.category !== b.category) return a.category === "body" ? -1 : 1;
|
|
190
|
+
return 0;
|
|
191
|
+
});
|
|
192
|
+
return fields;
|
|
193
|
+
}
|
|
194
|
+
function isObject(v) {
|
|
195
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
196
|
+
}
|
|
197
|
+
function isSizeLabel(key) {
|
|
198
|
+
return SIZE_LABEL_PATTERN.test(key.trim());
|
|
199
|
+
}
|
|
200
|
+
function allKeysAreSizeLabels(obj) {
|
|
201
|
+
const keys = Object.keys(obj);
|
|
202
|
+
if (keys.length === 0) return false;
|
|
203
|
+
return keys.every((k) => isSizeLabel(k));
|
|
204
|
+
}
|
|
205
|
+
function allKeysAreSectionNames(obj) {
|
|
206
|
+
const keys = Object.keys(obj);
|
|
207
|
+
if (keys.length < 2) return false;
|
|
208
|
+
return keys.every((k) => {
|
|
209
|
+
const val = obj[k];
|
|
210
|
+
const isContainer = Array.isArray(val) || isObject(val);
|
|
211
|
+
const isNotSizeLabel = !isSizeLabel(k);
|
|
212
|
+
const isNotMeasurement = !HEADER_ALIASES[k.toLowerCase().trim()];
|
|
213
|
+
return isContainer && isNotSizeLabel && isNotMeasurement;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function tryPreNormalized(input) {
|
|
217
|
+
if (!isObject(input)) return null;
|
|
218
|
+
const obj = input;
|
|
219
|
+
if (obj.found === true && Array.isArray(obj.headers) && Array.isArray(obj.rows) && obj.headers.length > 0 && obj.rows.length > 0) {
|
|
220
|
+
const headers = obj.headers;
|
|
221
|
+
const rows = obj.rows.map((r) => r.map(String));
|
|
222
|
+
return {
|
|
223
|
+
found: true,
|
|
224
|
+
title: typeof obj.title === "string" ? obj.title : void 0,
|
|
225
|
+
headers,
|
|
226
|
+
rows,
|
|
227
|
+
requiredFields: Array.isArray(obj.requiredFields) && obj.requiredFields.length > 0 ? obj.requiredFields : deriveRequiredFields(headers)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
function tryKeyValueObject(input) {
|
|
233
|
+
if (!isObject(input)) return null;
|
|
234
|
+
const obj = input;
|
|
235
|
+
if (!allKeysAreSizeLabels(obj)) return null;
|
|
236
|
+
const sizeLabels = Object.keys(obj);
|
|
237
|
+
const firstVal = obj[sizeLabels[0]];
|
|
238
|
+
if (!isObject(firstVal)) return null;
|
|
239
|
+
const measureKeySet = /* @__PURE__ */ new Set();
|
|
240
|
+
for (const label of sizeLabels) {
|
|
241
|
+
const sizeObj = obj[label];
|
|
242
|
+
if (!isObject(sizeObj)) return null;
|
|
243
|
+
for (const k of Object.keys(sizeObj)) {
|
|
244
|
+
measureKeySet.add(k);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const measureKeys = Array.from(measureKeySet);
|
|
248
|
+
const headers = ["Size", ...measureKeys];
|
|
249
|
+
const rows = sizeLabels.map((label) => {
|
|
250
|
+
const sizeObj = obj[label];
|
|
251
|
+
return [label, ...measureKeys.map((k) => String(sizeObj[k] ?? ""))];
|
|
252
|
+
});
|
|
253
|
+
return { found: true, headers, rows, requiredFields: deriveRequiredFields(headers) };
|
|
254
|
+
}
|
|
255
|
+
function tryArrayOfObjects(input) {
|
|
256
|
+
if (!Array.isArray(input) || input.length === 0) return null;
|
|
257
|
+
if (!isObject(input[0])) return null;
|
|
258
|
+
const first = input[0];
|
|
259
|
+
const sizeKey = Object.keys(first).find((k) => {
|
|
260
|
+
const alias = HEADER_ALIASES[k.toLowerCase().trim()];
|
|
261
|
+
return alias === "__size__";
|
|
262
|
+
}) || Object.keys(first).find((k) => k.toLowerCase() === "size" || k.toLowerCase() === "label");
|
|
263
|
+
if (!sizeKey) return null;
|
|
264
|
+
const allKeys = /* @__PURE__ */ new Set();
|
|
265
|
+
for (const row of input) {
|
|
266
|
+
if (!isObject(row)) return null;
|
|
267
|
+
for (const k of Object.keys(row)) {
|
|
268
|
+
allKeys.add(k);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const measureKeys = Array.from(allKeys).filter((k) => k !== sizeKey);
|
|
272
|
+
const headers = [sizeKey, ...measureKeys];
|
|
273
|
+
const rows = input.map((row) => {
|
|
274
|
+
const obj = row;
|
|
275
|
+
return headers.map((h) => String(obj[h] ?? ""));
|
|
276
|
+
});
|
|
277
|
+
const displayHeaders = headers.map((h) => h.charAt(0).toUpperCase() + h.slice(1));
|
|
278
|
+
return { found: true, headers: displayHeaders, rows, requiredFields: deriveRequiredFields(displayHeaders) };
|
|
279
|
+
}
|
|
280
|
+
function tryArrayOfArrays(input) {
|
|
281
|
+
if (!Array.isArray(input) || input.length < 2) return null;
|
|
282
|
+
if (!Array.isArray(input[0])) return null;
|
|
283
|
+
const headers = input[0].map(String);
|
|
284
|
+
const rows = input.slice(1).map((r) => r.map(String));
|
|
285
|
+
if (headers.length < 2) return null;
|
|
286
|
+
return { found: true, headers, rows, requiredFields: deriveRequiredFields(headers) };
|
|
287
|
+
}
|
|
288
|
+
function tryWrapperObject(input) {
|
|
289
|
+
if (!isObject(input)) return null;
|
|
290
|
+
const obj = input;
|
|
291
|
+
const arrayKey = ["sizes", "data", "sizeChart", "size_chart", "sizeGuide", "size_guide", "chart"].find(
|
|
292
|
+
(k) => Array.isArray(obj[k])
|
|
293
|
+
);
|
|
294
|
+
if (!arrayKey) return null;
|
|
295
|
+
const inner = obj[arrayKey];
|
|
296
|
+
return tryArrayOfObjects(inner) ?? tryArrayOfArrays(inner);
|
|
297
|
+
}
|
|
298
|
+
function tryMultiSection(input) {
|
|
299
|
+
if (!isObject(input)) return null;
|
|
300
|
+
const obj = input;
|
|
301
|
+
if (!allKeysAreSectionNames(obj)) return null;
|
|
302
|
+
const sections = {};
|
|
303
|
+
let primaryHeaders = [];
|
|
304
|
+
let primaryRows = [];
|
|
305
|
+
const allFieldKeys = /* @__PURE__ */ new Set();
|
|
306
|
+
const allFields = [];
|
|
307
|
+
for (const [sectionName, sectionData] of Object.entries(obj)) {
|
|
308
|
+
const normalized = tryArrayOfObjects(sectionData) ?? tryArrayOfArrays(sectionData) ?? tryKeyValueObject(sectionData) ?? tryWrapperObject(sectionData);
|
|
309
|
+
if (!normalized) return null;
|
|
310
|
+
sections[sectionName] = {
|
|
311
|
+
headers: normalized.headers,
|
|
312
|
+
rows: normalized.rows,
|
|
313
|
+
requiredFields: normalized.requiredFields
|
|
314
|
+
};
|
|
315
|
+
if (primaryHeaders.length === 0) {
|
|
316
|
+
primaryHeaders = normalized.headers;
|
|
317
|
+
primaryRows = normalized.rows;
|
|
318
|
+
}
|
|
319
|
+
for (const f of normalized.requiredFields) {
|
|
320
|
+
if (!allFieldKeys.has(f.key)) {
|
|
321
|
+
allFieldKeys.add(f.key);
|
|
322
|
+
allFields.push(f);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (Object.keys(sections).length === 0) return null;
|
|
327
|
+
return {
|
|
328
|
+
found: true,
|
|
329
|
+
headers: primaryHeaders,
|
|
330
|
+
rows: primaryRows,
|
|
331
|
+
requiredFields: allFields,
|
|
332
|
+
sections
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function tryJsonString(input) {
|
|
336
|
+
if (typeof input !== "string") return null;
|
|
337
|
+
const trimmed = input.trim();
|
|
338
|
+
if (trimmed.startsWith("<") || trimmed.includes("<table") || trimmed.includes("<tr")) {
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
const parsed = JSON.parse(trimmed);
|
|
343
|
+
return normalizeSizeGuide(parsed).success ? normalizeSizeGuide(parsed).data : null;
|
|
344
|
+
} catch {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function normalizeSizeGuide(input) {
|
|
349
|
+
if (input === null || input === void 0) {
|
|
350
|
+
return { success: false, reason: "no data provided" };
|
|
351
|
+
}
|
|
352
|
+
const result = tryPreNormalized(input) ?? tryMultiSection(input) ?? tryKeyValueObject(input) ?? tryArrayOfObjects(input) ?? tryArrayOfArrays(input) ?? tryWrapperObject(input) ?? tryJsonString(input);
|
|
353
|
+
if (result && result.requiredFields.length > 0) {
|
|
354
|
+
return { success: true, data: result };
|
|
355
|
+
}
|
|
356
|
+
if (result && result.requiredFields.length === 0 && result.rows.length > 0) {
|
|
357
|
+
return { success: true, data: result };
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
success: false,
|
|
361
|
+
reason: typeof input === "string" ? "unstructured string" : "unrecognised format"
|
|
362
|
+
};
|
|
363
|
+
}
|
|
5
364
|
function cx(base, override) {
|
|
6
365
|
return override ? `${base} ${override}` : base;
|
|
7
366
|
}
|
|
@@ -51,8 +410,8 @@ const SIZING_COUNTRIES = [
|
|
|
51
410
|
{ code: "AU", label: "Australia" },
|
|
52
411
|
{ code: "BR", label: "Brazil" }
|
|
53
412
|
];
|
|
54
|
-
const STEP_LABELS = ["", "Welcome", "
|
|
55
|
-
const TOTAL_STEPS =
|
|
413
|
+
const STEP_LABELS = ["", "Welcome", "Size", "Your Fit", "Try On"];
|
|
414
|
+
const TOTAL_STEPS = 4;
|
|
56
415
|
function detectLocale() {
|
|
57
416
|
if (typeof window === "undefined") return "US";
|
|
58
417
|
const l = (navigator.language || "en-US").toLowerCase();
|
|
@@ -78,22 +437,6 @@ function lbsToKg(lbs) {
|
|
|
78
437
|
function ftInToCm(ft, inch) {
|
|
79
438
|
return +(ft * 30.48 + inch * 2.54).toFixed(1);
|
|
80
439
|
}
|
|
81
|
-
function SvgIcon({ d, size = 18, strokeWidth = 2 }) {
|
|
82
|
-
return /* @__PURE__ */ jsx(
|
|
83
|
-
"svg",
|
|
84
|
-
{
|
|
85
|
-
width: size,
|
|
86
|
-
height: size,
|
|
87
|
-
viewBox: "0 0 24 24",
|
|
88
|
-
fill: "none",
|
|
89
|
-
stroke: "currentColor",
|
|
90
|
-
strokeWidth,
|
|
91
|
-
strokeLinecap: "round",
|
|
92
|
-
strokeLinejoin: "round",
|
|
93
|
-
children: /* @__PURE__ */ jsx("path", { d })
|
|
94
|
-
}
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
440
|
function CameraIcon({ size = 18 }) {
|
|
98
441
|
return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
99
442
|
/* @__PURE__ */ jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
|
|
@@ -181,11 +524,12 @@ function PrimeStyleTryon(props) {
|
|
|
181
524
|
function PrimeStyleTryonInner({
|
|
182
525
|
productImage,
|
|
183
526
|
productTitle = "Product",
|
|
184
|
-
buttonText
|
|
527
|
+
buttonText,
|
|
185
528
|
apiUrl,
|
|
186
529
|
showPoweredBy = true,
|
|
187
530
|
showIcon = true,
|
|
188
531
|
buttonIcon,
|
|
532
|
+
locale,
|
|
189
533
|
buttonStyles: btnS = {},
|
|
190
534
|
modalStyles: mdlS = {},
|
|
191
535
|
classNames: cn = {},
|
|
@@ -199,6 +543,8 @@ function PrimeStyleTryonInner({
|
|
|
199
543
|
onError,
|
|
200
544
|
sizeGuideData
|
|
201
545
|
}) {
|
|
546
|
+
const t = useMemo(() => createT(locale), [locale]);
|
|
547
|
+
const resolvedButtonText = buttonText ?? t("Virtual Try-On");
|
|
202
548
|
const [view, setView] = useState("idle");
|
|
203
549
|
const [selectedFile, setSelectedFile] = useState(null);
|
|
204
550
|
const [previewUrl, setPreviewUrl] = useState(null);
|
|
@@ -267,12 +613,12 @@ function PrimeStyleTryonInner({
|
|
|
267
613
|
if (progressIntervalRef.current) return;
|
|
268
614
|
progressRef.current = 0;
|
|
269
615
|
const statuses = [
|
|
270
|
-
{ at: 0, text: "Preparing your image..." },
|
|
271
|
-
{ at: 15, text: "Analyzing body proportions..." },
|
|
272
|
-
{ at: 30, text: "Matching garment to your photo..." },
|
|
273
|
-
{ at: 50, text: "Generating virtual try-on..." },
|
|
274
|
-
{ at: 75, text: "Refining details..." },
|
|
275
|
-
{ at: 90, text: "Almost there..." }
|
|
616
|
+
{ at: 0, text: t("Preparing your image...") },
|
|
617
|
+
{ at: 15, text: t("Analyzing body proportions...") },
|
|
618
|
+
{ at: 30, text: t("Matching garment to your photo...") },
|
|
619
|
+
{ at: 50, text: t("Generating virtual try-on...") },
|
|
620
|
+
{ at: 75, text: t("Refining details...") },
|
|
621
|
+
{ at: 90, text: t("Almost there...") }
|
|
276
622
|
];
|
|
277
623
|
progressIntervalRef.current = setInterval(() => {
|
|
278
624
|
const p = progressRef.current;
|
|
@@ -327,13 +673,25 @@ function PrimeStyleTryonInner({
|
|
|
327
673
|
useEffect(() => {
|
|
328
674
|
lsSet("history", history);
|
|
329
675
|
}, [history]);
|
|
676
|
+
const normalizedGuide = useMemo(() => {
|
|
677
|
+
if (!sizeGuideData) return null;
|
|
678
|
+
return normalizeSizeGuide(sizeGuideData);
|
|
679
|
+
}, [sizeGuideData]);
|
|
330
680
|
useEffect(() => {
|
|
331
|
-
if (view !== "sizing-choice" || sizeGuideFetchedRef.current
|
|
681
|
+
if (view !== "sizing-choice" || sizeGuideFetchedRef.current) return;
|
|
332
682
|
sizeGuideFetchedRef.current = true;
|
|
333
683
|
if (!sizeGuideData) {
|
|
334
684
|
setSizeGuide({ found: false });
|
|
335
685
|
return;
|
|
336
686
|
}
|
|
687
|
+
if (normalizedGuide?.success) {
|
|
688
|
+
setSizeGuide(normalizedGuide.data);
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
if (!apiRef.current) {
|
|
692
|
+
setSizeGuide({ found: false });
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
337
695
|
setSizeGuideFetching(true);
|
|
338
696
|
const baseUrl = getApiUrl(apiUrl);
|
|
339
697
|
const key = getApiKey();
|
|
@@ -345,20 +703,20 @@ function PrimeStyleTryonInner({
|
|
|
345
703
|
if (data) setSizeGuide(data);
|
|
346
704
|
else setSizeGuide({ found: false });
|
|
347
705
|
}).catch(() => setSizeGuide({ found: false })).finally(() => setSizeGuideFetching(false));
|
|
348
|
-
}, [view, apiUrl, productTitle, sizeGuideData]);
|
|
706
|
+
}, [view, apiUrl, productTitle, sizeGuideData, normalizedGuide]);
|
|
349
707
|
const stepIndex = useMemo(() => {
|
|
350
708
|
switch (view) {
|
|
351
709
|
case "welcome":
|
|
352
710
|
return 1;
|
|
353
|
-
case "upload":
|
|
354
|
-
return 2;
|
|
355
711
|
case "sizing-choice":
|
|
356
712
|
case "sizing-form":
|
|
713
|
+
return 2;
|
|
714
|
+
case "size-result":
|
|
357
715
|
return 3;
|
|
716
|
+
case "upload":
|
|
358
717
|
case "processing":
|
|
359
|
-
return 4;
|
|
360
718
|
case "result":
|
|
361
|
-
return
|
|
719
|
+
return 4;
|
|
362
720
|
default:
|
|
363
721
|
return 1;
|
|
364
722
|
}
|
|
@@ -385,6 +743,7 @@ function PrimeStyleTryonInner({
|
|
|
385
743
|
setFormGender("male");
|
|
386
744
|
sizeGuideFetchedRef.current = false;
|
|
387
745
|
setSizeGuideFetching(false);
|
|
746
|
+
historySavedRef.current = false;
|
|
388
747
|
unsubRef.current?.();
|
|
389
748
|
unsubRef.current = null;
|
|
390
749
|
if (pollingRef.current) {
|
|
@@ -395,13 +754,13 @@ function PrimeStyleTryonInner({
|
|
|
395
754
|
}, [onClose, previewUrl]);
|
|
396
755
|
const handleFileSelect = useCallback((file) => {
|
|
397
756
|
if (!isValidImageFile(file)) {
|
|
398
|
-
setErrorMessage("Please upload a JPEG, PNG, or WebP image.");
|
|
757
|
+
setErrorMessage(t("Please upload a JPEG, PNG, or WebP image."));
|
|
399
758
|
setView("error");
|
|
400
759
|
onError?.({ message: "Invalid file type", code: "INVALID_FILE" });
|
|
401
760
|
return;
|
|
402
761
|
}
|
|
403
762
|
if (file.size > 10 * 1024 * 1024) {
|
|
404
|
-
setErrorMessage("Image must be under 10MB.");
|
|
763
|
+
setErrorMessage(t("Image must be under 10MB."));
|
|
405
764
|
setView("error");
|
|
406
765
|
onError?.({ message: "File too large", code: "FILE_TOO_LARGE" });
|
|
407
766
|
return;
|
|
@@ -435,7 +794,7 @@ function PrimeStyleTryonInner({
|
|
|
435
794
|
progressRef.current = 100;
|
|
436
795
|
if (progressBarRef.current) progressBarRef.current.style.width = "100%";
|
|
437
796
|
if (progressTextRef.current) progressTextRef.current.textContent = "100%";
|
|
438
|
-
if (progressStatusRef.current) progressStatusRef.current.textContent = "Complete!";
|
|
797
|
+
if (progressStatusRef.current) progressStatusRef.current.textContent = t("Complete!");
|
|
439
798
|
cleanupJob();
|
|
440
799
|
setTimeout(() => setView("result"), 400);
|
|
441
800
|
onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
|
|
@@ -444,7 +803,7 @@ function PrimeStyleTryonInner({
|
|
|
444
803
|
if (!completedRef.current) {
|
|
445
804
|
completedRef.current = true;
|
|
446
805
|
cleanupJob();
|
|
447
|
-
const msg = update.error || "Try-on generation failed";
|
|
806
|
+
const msg = update.error || t("Try-on generation failed");
|
|
448
807
|
setErrorMessage(msg);
|
|
449
808
|
setView("error");
|
|
450
809
|
onError?.({ message: msg });
|
|
@@ -466,7 +825,10 @@ function PrimeStyleTryonInner({
|
|
|
466
825
|
locale: sizingCountry,
|
|
467
826
|
product: { title: productTitle, description: "", variants: [] }
|
|
468
827
|
};
|
|
469
|
-
if (sizeGuide?.found)
|
|
828
|
+
if (sizeGuide?.found) {
|
|
829
|
+
payload.sizeGuide = sizeGuide;
|
|
830
|
+
if (sizeGuide.sections) payload.sizeGuide = { ...sizeGuide, sections: sizeGuide.sections };
|
|
831
|
+
}
|
|
470
832
|
payload.sizingUnit = sizingUnit;
|
|
471
833
|
if (sizingMethod === "exact") {
|
|
472
834
|
const m = { gender: formRef.current.gender || "male", sizingUnit };
|
|
@@ -514,9 +876,9 @@ function PrimeStyleTryonInner({
|
|
|
514
876
|
setSizingLoading(false);
|
|
515
877
|
}
|
|
516
878
|
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle, dynamicFields]);
|
|
517
|
-
const
|
|
879
|
+
const handleTryOnSubmit = useCallback(async () => {
|
|
518
880
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
519
|
-
const msg = !apiRef.current ? "
|
|
881
|
+
const msg = !apiRef.current ? t("SDK not configured. Please provide an API key.") : t("Something went wrong");
|
|
520
882
|
setErrorMessage(msg);
|
|
521
883
|
setView("error");
|
|
522
884
|
onError?.({ message: msg, code: "SDK_NOT_CONFIGURED" });
|
|
@@ -524,10 +886,6 @@ function PrimeStyleTryonInner({
|
|
|
524
886
|
}
|
|
525
887
|
completedRef.current = false;
|
|
526
888
|
setView("processing");
|
|
527
|
-
if (sizingMethod) {
|
|
528
|
-
setSizingLoading(true);
|
|
529
|
-
submitSizing();
|
|
530
|
-
}
|
|
531
889
|
try {
|
|
532
890
|
const modelImage = await compressImage(selectedFile);
|
|
533
891
|
const response = await apiRef.current.submitTryOn(modelImage, productImage);
|
|
@@ -555,13 +913,13 @@ function PrimeStyleTryonInner({
|
|
|
555
913
|
}
|
|
556
914
|
}, 3e3);
|
|
557
915
|
} catch (err) {
|
|
558
|
-
const message = err instanceof Error ? err.message : "Failed to start try-on";
|
|
916
|
+
const message = err instanceof Error ? err.message : t("Failed to start try-on");
|
|
559
917
|
const code = err instanceof PrimeStyleError ? err.code : void 0;
|
|
560
918
|
setErrorMessage(message);
|
|
561
919
|
setView("error");
|
|
562
920
|
onError?.({ message, code });
|
|
563
921
|
}
|
|
564
|
-
}, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate
|
|
922
|
+
}, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate]);
|
|
565
923
|
const handleDownload = useCallback(() => {
|
|
566
924
|
if (!resultImageUrl) return;
|
|
567
925
|
if (resultImageUrl.startsWith("data:")) {
|
|
@@ -592,7 +950,7 @@ function PrimeStyleTryonInner({
|
|
|
592
950
|
setSizingResult(null);
|
|
593
951
|
setSizingLoading(false);
|
|
594
952
|
setProfileSaved(false);
|
|
595
|
-
setView("
|
|
953
|
+
setView("sizing-choice");
|
|
596
954
|
}, [previewUrl, cleanupJob]);
|
|
597
955
|
const applyProfile = useCallback((id) => {
|
|
598
956
|
const p = profiles.find((pr) => pr.id === id);
|
|
@@ -712,22 +1070,30 @@ function PrimeStyleTryonInner({
|
|
|
712
1070
|
}
|
|
713
1071
|
setHistory((prev) => [entry, ...prev].slice(0, 50));
|
|
714
1072
|
}, [productTitle, productImage, resultImageUrl, sizingResult, activeProfileId, profiles]);
|
|
1073
|
+
const historySavedRef = useRef(false);
|
|
715
1074
|
useEffect(() => {
|
|
716
|
-
if (view === "result" &&
|
|
1075
|
+
if (view === "size-result" && sizingResult && !historySavedRef.current) {
|
|
1076
|
+
historySavedRef.current = true;
|
|
1077
|
+
saveHistoryEntry();
|
|
1078
|
+
} else if (view === "result" && resultImageUrl && !historySavedRef.current) {
|
|
1079
|
+
historySavedRef.current = true;
|
|
717
1080
|
saveHistoryEntry();
|
|
1081
|
+
} else if (view === "welcome" || view === "sizing-choice") {
|
|
1082
|
+
historySavedRef.current = false;
|
|
718
1083
|
}
|
|
719
|
-
}, [view]);
|
|
1084
|
+
}, [view, sizingResult, resultImageUrl]);
|
|
720
1085
|
const updateField = useCallback((key, val) => {
|
|
721
1086
|
formRef.current[key] = val;
|
|
722
1087
|
}, []);
|
|
723
1088
|
const shoeField = useMemo(() => {
|
|
724
1089
|
const map = {
|
|
725
|
-
US: { key: "shoeUS",
|
|
726
|
-
UK: { key: "shoeUK",
|
|
727
|
-
AU: { key: "shoeUK",
|
|
1090
|
+
US: { key: "shoeUS", labelKey: "Shoe size (US)", ph: "e.g. 10" },
|
|
1091
|
+
UK: { key: "shoeUK", labelKey: "Shoe size (UK)", ph: "e.g. 9" },
|
|
1092
|
+
AU: { key: "shoeUK", labelKey: "Shoe size (UK)", ph: "e.g. 9" }
|
|
728
1093
|
};
|
|
729
|
-
|
|
730
|
-
|
|
1094
|
+
const raw = map[sizingCountry] || { key: "shoeEU", labelKey: "Shoe size (EU)", ph: "e.g. 43" };
|
|
1095
|
+
return { key: raw.key, label: t(raw.labelKey), ph: raw.ph };
|
|
1096
|
+
}, [sizingCountry, t]);
|
|
731
1097
|
const rootVars = {
|
|
732
1098
|
"--ps-btn-bg": btnS.backgroundColor,
|
|
733
1099
|
"--ps-btn-color": btnS.textColor,
|
|
@@ -771,7 +1137,7 @@ function PrimeStyleTryonInner({
|
|
|
771
1137
|
i > 1 && /* @__PURE__ */ jsx("div", { className: `ps-tryon-stepper-line${i <= stepIndex ? " ps-done" : ""}` }),
|
|
772
1138
|
/* @__PURE__ */ jsxs("div", { className: `ps-tryon-stepper-step${i < stepIndex ? " ps-done" : i === stepIndex ? " ps-active" : ""}`, children: [
|
|
773
1139
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-circle", children: i < stepIndex ? /* @__PURE__ */ jsx(CheckIcon, {}) : i }),
|
|
774
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-label", children: STEP_LABELS[i] })
|
|
1140
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-label", children: t(STEP_LABELS[i]) })
|
|
775
1141
|
] })
|
|
776
1142
|
] }, i)) }) });
|
|
777
1143
|
}
|
|
@@ -800,34 +1166,35 @@ function PrimeStyleTryonInner({
|
|
|
800
1166
|
/* @__PURE__ */ jsx("img", { src: productImage, alt: "Product", className: "ps-tryon-welcome-product" }),
|
|
801
1167
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-welcome-sparkle", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 20 }) })
|
|
802
1168
|
] }),
|
|
803
|
-
/* @__PURE__ */ jsx("h2", { className: "ps-tryon-welcome-title", children: "
|
|
804
|
-
/* @__PURE__ */ jsx("p", { className: "ps-tryon-welcome-sub", children: "
|
|
1169
|
+
/* @__PURE__ */ jsx("h2", { className: "ps-tryon-welcome-title", children: t("Find Your Perfect Size") }),
|
|
1170
|
+
/* @__PURE__ */ jsx("p", { className: "ps-tryon-welcome-sub", children: t("Get your size instantly, then try it on") })
|
|
805
1171
|
] }),
|
|
806
1172
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-features", children: [
|
|
807
|
-
{ icon: /* @__PURE__ */ jsx(
|
|
808
|
-
{ icon: /* @__PURE__ */ jsx(
|
|
809
|
-
{ icon: /* @__PURE__ */ jsx(SparkleIcon, {}), title: "See Results", desc: "Try-on in seconds" }
|
|
1173
|
+
{ icon: /* @__PURE__ */ jsx(RulerIcon, {}), title: t("Get Your Size"), desc: t("Instant fit recommendation") },
|
|
1174
|
+
{ icon: /* @__PURE__ */ jsx(CameraIcon, {}), title: t("Try It On"), desc: t("See how it looks on you") }
|
|
810
1175
|
].map((f, i) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-feature", children: [
|
|
811
1176
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-icon", children: f.icon }),
|
|
812
1177
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-title", children: f.title }),
|
|
813
1178
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-desc", children: f.desc })
|
|
814
1179
|
] }, i)) }),
|
|
815
|
-
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-cta", onClick: () => setView("
|
|
816
|
-
"
|
|
1180
|
+
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-cta", onClick: () => setView("sizing-choice"), children: [
|
|
1181
|
+
t("Find My Size"),
|
|
1182
|
+
" ",
|
|
817
1183
|
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
818
1184
|
] }),
|
|
819
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-welcome-note", children: "Takes less than a minute" })
|
|
1185
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-welcome-note", children: t("Takes less than a minute") })
|
|
820
1186
|
] });
|
|
821
1187
|
}
|
|
822
1188
|
function UploadView() {
|
|
823
1189
|
return /* @__PURE__ */ jsx(Fragment, { children: selectedFile && previewUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
824
1190
|
/* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-preview", cn.preview), children: [
|
|
825
1191
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-preview-blur", style: { backgroundImage: `url(${previewUrl})` } }),
|
|
826
|
-
/* @__PURE__ */ jsx("img", { src: previewUrl, alt: "Your photo", className: cn.previewImage }),
|
|
1192
|
+
/* @__PURE__ */ jsx("img", { src: previewUrl, alt: t("Your photo"), className: cn.previewImage }),
|
|
827
1193
|
/* @__PURE__ */ jsx("button", { onClick: handleRemovePreview, className: cx("ps-tryon-preview-remove", cn.removeButton), children: "×" })
|
|
828
1194
|
] }),
|
|
829
|
-
/* @__PURE__ */ jsxs("button", { onClick:
|
|
830
|
-
"
|
|
1195
|
+
/* @__PURE__ */ jsxs("button", { onClick: handleTryOnSubmit, className: cx("ps-tryon-submit", cn.submitButton), children: [
|
|
1196
|
+
t("Try It On"),
|
|
1197
|
+
" ",
|
|
831
1198
|
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
832
1199
|
] })
|
|
833
1200
|
] }) : /* @__PURE__ */ jsxs(
|
|
@@ -861,8 +1228,8 @@ function PrimeStyleTryonInner({
|
|
|
861
1228
|
}
|
|
862
1229
|
),
|
|
863
1230
|
/* @__PURE__ */ jsx(UploadIcon, {}),
|
|
864
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: "
|
|
865
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-hint", cn.uploadHint), children: "JPEG, PNG or WebP (max 10MB)" })
|
|
1231
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: t("Upload a full body photo") }),
|
|
1232
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-hint", cn.uploadHint), children: t("JPEG, PNG or WebP (max 10MB)") })
|
|
866
1233
|
]
|
|
867
1234
|
}
|
|
868
1235
|
) });
|
|
@@ -874,16 +1241,17 @@ function PrimeStyleTryonInner({
|
|
|
874
1241
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-sizing-choice", children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sg-checking", children: [
|
|
875
1242
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 32 }) }),
|
|
876
1243
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar-wrap", children: /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar" }) }),
|
|
877
|
-
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "Checking size guide..." }),
|
|
878
|
-
/* @__PURE__ */ jsx("p", { className: "ps-tryon-sg-checking-sub", children: "Looking for size chart data for this product" })
|
|
1244
|
+
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: t("Checking size guide...") }),
|
|
1245
|
+
/* @__PURE__ */ jsx("p", { className: "ps-tryon-sg-checking-sub", children: t("Looking for size chart data for this product") })
|
|
879
1246
|
] }) });
|
|
880
1247
|
}
|
|
881
1248
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-choice", children: [
|
|
882
|
-
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "How would you like to find your size?" }),
|
|
883
|
-
sgChecked && !sgAvailable && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice", children: "Size guide is not available for this product — sizing will use standard measurements" }),
|
|
1249
|
+
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: t("How would you like to find your size?") }),
|
|
1250
|
+
sgChecked && !sgAvailable && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice", children: t("Size guide is not available for this product — sizing will use standard measurements") }),
|
|
884
1251
|
sgChecked && sgAvailable && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sg-notice ps-tryon-sg-found", children: [
|
|
885
1252
|
/* @__PURE__ */ jsx(CheckIcon, { size: 14 }),
|
|
886
|
-
"
|
|
1253
|
+
" ",
|
|
1254
|
+
t("Size guide found for this product")
|
|
887
1255
|
] }),
|
|
888
1256
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-cards", children: [
|
|
889
1257
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
|
|
@@ -892,10 +1260,10 @@ function PrimeStyleTryonInner({
|
|
|
892
1260
|
}, children: [
|
|
893
1261
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 24 }) }),
|
|
894
1262
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
895
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Enter my measurements" }),
|
|
896
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: sizeGuide?.requiredFields?.length ? sizeGuide.requiredFields.filter((f) => f.required).slice(0, 3).map((f) => f.label).join(", ") + (sizeGuide.requiredFields.length > 3 ? "
|
|
1263
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Enter my measurements") }),
|
|
1264
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: sizeGuide?.requiredFields?.length ? sizeGuide.requiredFields.filter((f) => f.required).slice(0, 3).map((f) => t(f.label)).join(", ") + (sizeGuide.requiredFields.length > 3 ? ` ${t("& more")}` : "") : t("Chest, waist, hips, shoes & more") })
|
|
897
1265
|
] }),
|
|
898
|
-
/* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: "Best accuracy" })
|
|
1266
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: t("Best accuracy") })
|
|
899
1267
|
] }),
|
|
900
1268
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
|
|
901
1269
|
setSizingMethod("quick");
|
|
@@ -903,18 +1271,18 @@ function PrimeStyleTryonInner({
|
|
|
903
1271
|
}, children: [
|
|
904
1272
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 24 }) }),
|
|
905
1273
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
906
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Just height & weight" }),
|
|
907
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Quick estimate in seconds" })
|
|
1274
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Just height & weight") }),
|
|
1275
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: t("Quick estimate in seconds") })
|
|
908
1276
|
] })
|
|
909
1277
|
] }),
|
|
910
1278
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
|
|
911
1279
|
setSizingMethod(null);
|
|
912
|
-
|
|
1280
|
+
setView("upload");
|
|
913
1281
|
}, children: [
|
|
914
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(
|
|
1282
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(CameraIcon, { size: 24 }) }),
|
|
915
1283
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
916
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Skip
|
|
917
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "
|
|
1284
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Skip, just try it on") }),
|
|
1285
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: t("Upload a photo to see how it looks") })
|
|
918
1286
|
] })
|
|
919
1287
|
] })
|
|
920
1288
|
] })
|
|
@@ -928,37 +1296,38 @@ function PrimeStyleTryonInner({
|
|
|
928
1296
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
|
|
929
1297
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-back", onClick: () => setView("sizing-choice"), children: [
|
|
930
1298
|
/* @__PURE__ */ jsx(ArrowLeftIcon, {}),
|
|
931
|
-
"
|
|
1299
|
+
" ",
|
|
1300
|
+
t("Back")
|
|
932
1301
|
] }),
|
|
933
1302
|
sizingMethod === "exact" && profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-profile-select", value: activeProfileId || "", onChange: (e) => {
|
|
934
1303
|
if (e.target.value) applyProfile(e.target.value);
|
|
935
1304
|
}, children: [
|
|
936
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "Auto-fill from saved profile..." }),
|
|
1305
|
+
/* @__PURE__ */ jsx("option", { value: "", children: t("Auto-fill from saved profile...") }),
|
|
937
1306
|
profiles.map((p) => /* @__PURE__ */ jsxs("option", { value: p.id, children: [
|
|
938
1307
|
p.name,
|
|
939
1308
|
" (",
|
|
940
|
-
p.gender === "female" ? "Women's" : "Men's",
|
|
1309
|
+
p.gender === "female" ? t("Women's") : t("Men's"),
|
|
941
1310
|
")"
|
|
942
1311
|
] }, p.id))
|
|
943
1312
|
] }) }),
|
|
944
1313
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
945
|
-
/* @__PURE__ */ jsx("label", { children: "I'm shopping for" }),
|
|
1314
|
+
/* @__PURE__ */ jsx("label", { children: t("I'm shopping for") }),
|
|
946
1315
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-toggle", children: [
|
|
947
1316
|
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${!isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
948
1317
|
updateField("gender", "male");
|
|
949
1318
|
setFormGender("male");
|
|
950
|
-
}, children: "Men's" }),
|
|
1319
|
+
}, children: t("Men's") }),
|
|
951
1320
|
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
952
1321
|
updateField("gender", "female");
|
|
953
1322
|
setFormGender("female");
|
|
954
|
-
}, children: "Women's" })
|
|
1323
|
+
}, children: t("Women's") })
|
|
955
1324
|
] })
|
|
956
1325
|
] }),
|
|
957
1326
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
958
|
-
/* @__PURE__ */ jsx("label", { children: "Sizing region" }),
|
|
959
|
-
/* @__PURE__ */ jsx("select", { className: "ps-tryon-country-select", value: sizingCountry, onChange: (e) => setSizingCountry(e.target.value), children: SIZING_COUNTRIES.map((c) => /* @__PURE__ */ jsx("option", { value: c.code, children: c.label }, c.code)) })
|
|
1327
|
+
/* @__PURE__ */ jsx("label", { children: t("Sizing region") }),
|
|
1328
|
+
/* @__PURE__ */ jsx("select", { className: "ps-tryon-country-select", value: sizingCountry, onChange: (e) => setSizingCountry(e.target.value), children: SIZING_COUNTRIES.map((c) => /* @__PURE__ */ jsx("option", { value: c.code, children: t(c.label) }, c.code)) })
|
|
960
1329
|
] }),
|
|
961
|
-
sizingMethod === "exact" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: (v) => {
|
|
1330
|
+
sizingMethod === "exact" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: t("cm"), value: "cm" }, { label: t("in"), value: "in" }], value: sizingUnit, onChange: (v) => {
|
|
962
1331
|
setSizingUnit(v);
|
|
963
1332
|
setHeightUnit(v === "cm" ? "cm" : "ft");
|
|
964
1333
|
setWeightUnit(v === "cm" ? "kg" : "lbs");
|
|
@@ -975,7 +1344,7 @@ function PrimeStyleTryonInner({
|
|
|
975
1344
|
const showOriginal = field.key !== key;
|
|
976
1345
|
return /* @__PURE__ */ jsxs("span", { children: [
|
|
977
1346
|
/* @__PURE__ */ jsx(InputRow, { label: `${regionField.label}${field.required ? " *" : ""}`, fieldKey: key, placeholder: regionField.ph }),
|
|
978
|
-
showOriginal && /* @__PURE__ */ jsx(InputRow, { label: field.label, fieldKey: field.key, placeholder: field.placeholder })
|
|
1347
|
+
showOriginal && /* @__PURE__ */ jsx(InputRow, { label: t(field.label), fieldKey: field.key, placeholder: field.placeholder })
|
|
979
1348
|
] }, field.key);
|
|
980
1349
|
}
|
|
981
1350
|
const phNum = parseFloat(field.placeholder?.replace(/[^0-9.]/g, "") || "");
|
|
@@ -984,7 +1353,7 @@ function PrimeStyleTryonInner({
|
|
|
984
1353
|
return /* @__PURE__ */ jsx(
|
|
985
1354
|
InputRow,
|
|
986
1355
|
{
|
|
987
|
-
label: `${field.label}${field.required ? " *" : ""}`,
|
|
1356
|
+
label: `${t(field.label)}${field.required ? " *" : ""}`,
|
|
988
1357
|
fieldKey: field.key,
|
|
989
1358
|
placeholder,
|
|
990
1359
|
type: "number",
|
|
@@ -1009,11 +1378,11 @@ function PrimeStyleTryonInner({
|
|
|
1009
1378
|
const allOptFields = [...optFields, ...profileExtras];
|
|
1010
1379
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1011
1380
|
reqFields.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1012
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-section-label", children: "Required for this product" }),
|
|
1381
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-section-label", children: t("Required for this product") }),
|
|
1013
1382
|
reqFields.map(renderField)
|
|
1014
1383
|
] }),
|
|
1015
1384
|
isFemale && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
1016
|
-
/* @__PURE__ */ jsx("label", { children: "Fit type" }),
|
|
1385
|
+
/* @__PURE__ */ jsx("label", { children: t("Fit type") }),
|
|
1017
1386
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: ["petite", "standard", "tall", "plus"].map((fp) => /* @__PURE__ */ jsx(
|
|
1018
1387
|
"button",
|
|
1019
1388
|
{
|
|
@@ -1021,9 +1390,10 @@ function PrimeStyleTryonInner({
|
|
|
1021
1390
|
onClick: (e) => {
|
|
1022
1391
|
updateField("fitPreference", fp);
|
|
1023
1392
|
const btns = e.target.parentElement.querySelectorAll(".ps-tryon-unit-btn");
|
|
1024
|
-
btns.forEach((b) => b.classList.toggle("ps-active", b.
|
|
1393
|
+
btns.forEach((b) => b.classList.toggle("ps-active", b.dataset.fp === fp));
|
|
1025
1394
|
},
|
|
1026
|
-
|
|
1395
|
+
"data-fp": fp,
|
|
1396
|
+
children: t(fp.charAt(0).toUpperCase() + fp.slice(1))
|
|
1027
1397
|
},
|
|
1028
1398
|
fp
|
|
1029
1399
|
)) })
|
|
@@ -1038,7 +1408,7 @@ function PrimeStyleTryonInner({
|
|
|
1038
1408
|
if (arrow) arrow.style.transform = open ? "rotate(0deg)" : "rotate(180deg)";
|
|
1039
1409
|
}
|
|
1040
1410
|
}, children: [
|
|
1041
|
-
/* @__PURE__ */ jsx("span", { children: "Optional — improve accuracy & save to profile" }),
|
|
1411
|
+
/* @__PURE__ */ jsx("span", { children: t("Optional — improve accuracy & save to profile") }),
|
|
1042
1412
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-chevron", children: "▾" })
|
|
1043
1413
|
] }),
|
|
1044
1414
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-optional-fields", style: { display: "none" }, children: allOptFields.map(renderField) })
|
|
@@ -1046,33 +1416,39 @@ function PrimeStyleTryonInner({
|
|
|
1046
1416
|
] });
|
|
1047
1417
|
})() }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1048
1418
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
1049
|
-
/* @__PURE__ */
|
|
1419
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1420
|
+
t("Height"),
|
|
1421
|
+
" *"
|
|
1422
|
+
] }),
|
|
1050
1423
|
heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-height-ft", children: [
|
|
1051
1424
|
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", defaultValue: formRef.current.heightFeet || "", onInput: (e) => updateField("heightFeet", e.target.value) }),
|
|
1052
|
-
/* @__PURE__ */ jsx("span", { children: "ft" }),
|
|
1425
|
+
/* @__PURE__ */ jsx("span", { children: t("ft") }),
|
|
1053
1426
|
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "4", defaultValue: formRef.current.heightInches || "", onInput: (e) => updateField("heightInches", e.target.value) }),
|
|
1054
|
-
/* @__PURE__ */ jsx("span", { children: "in" })
|
|
1427
|
+
/* @__PURE__ */ jsx("span", { children: t("in") })
|
|
1055
1428
|
] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175", defaultValue: formRef.current.height || "", onInput: (e) => updateField("height", e.target.value) }),
|
|
1056
|
-
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "ft", value: "ft" }], value: heightUnit, onChange: setHeightUnit })
|
|
1429
|
+
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: t("cm"), value: "cm" }, { label: t("ft"), value: "ft" }], value: heightUnit, onChange: setHeightUnit })
|
|
1057
1430
|
] }),
|
|
1058
1431
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
1059
|
-
/* @__PURE__ */
|
|
1432
|
+
/* @__PURE__ */ jsxs("label", { children: [
|
|
1433
|
+
t("Weight"),
|
|
1434
|
+
" *"
|
|
1435
|
+
] }),
|
|
1060
1436
|
/* @__PURE__ */ jsx("input", { type: "number", placeholder: weightUnit === "lbs" ? "e.g. 170" : "e.g. 75", defaultValue: formRef.current.weight || "", onInput: (e) => updateField("weight", e.target.value) }),
|
|
1061
|
-
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "kg", value: "kg" }, { label: "lbs", value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
|
|
1437
|
+
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: t("kg"), value: "kg" }, { label: t("lbs"), value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
|
|
1062
1438
|
] })
|
|
1063
1439
|
] }),
|
|
1064
|
-
/* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
|
|
1440
|
+
/* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: t("Fill in what you know — more measurements = better accuracy.") }),
|
|
1065
1441
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-form-save-toggle", children: [
|
|
1066
1442
|
/* @__PURE__ */ jsxs("label", { className: "ps-tryon-form-save-check", children: [
|
|
1067
1443
|
/* @__PURE__ */ jsx("input", { type: "checkbox", checked: saveToggle, onChange: (e) => setSaveToggle(e.target.checked) }),
|
|
1068
|
-
/* @__PURE__ */ jsx("span", { children: "Save as profile" })
|
|
1444
|
+
/* @__PURE__ */ jsx("span", { children: t("Save as profile") })
|
|
1069
1445
|
] }),
|
|
1070
1446
|
saveToggle && /* @__PURE__ */ jsx(
|
|
1071
1447
|
"input",
|
|
1072
1448
|
{
|
|
1073
1449
|
type: "text",
|
|
1074
1450
|
className: "ps-tryon-form-save-name",
|
|
1075
|
-
placeholder: "Profile name (e.g. John, Sarah)",
|
|
1451
|
+
placeholder: t("Profile name (e.g. John, Sarah)"),
|
|
1076
1452
|
value: saveFormName,
|
|
1077
1453
|
onChange: (e) => setSaveFormName(e.target.value)
|
|
1078
1454
|
}
|
|
@@ -1082,78 +1458,55 @@ function PrimeStyleTryonInner({
|
|
|
1082
1458
|
if (saveToggle && saveFormName.trim()) {
|
|
1083
1459
|
saveProfile(saveFormName.trim());
|
|
1084
1460
|
}
|
|
1085
|
-
|
|
1461
|
+
setSizingLoading(true);
|
|
1462
|
+
submitSizing();
|
|
1463
|
+
setView("size-result");
|
|
1086
1464
|
}, children: [
|
|
1087
|
-
"Get My Size
|
|
1465
|
+
t("Get My Size"),
|
|
1466
|
+
" ",
|
|
1088
1467
|
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
1089
1468
|
] })
|
|
1090
1469
|
] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}-${formKey}`);
|
|
1091
1470
|
}
|
|
1092
|
-
function
|
|
1093
|
-
const barCb = useCallback((el) => {
|
|
1094
|
-
progressBarRef.current = el;
|
|
1095
|
-
if (el) el.style.width = `${Math.round(progressRef.current)}%`;
|
|
1096
|
-
}, []);
|
|
1097
|
-
const pctCb = useCallback((el) => {
|
|
1098
|
-
progressTextRef.current = el;
|
|
1099
|
-
if (el) el.textContent = `${Math.round(progressRef.current)}%`;
|
|
1100
|
-
}, []);
|
|
1101
|
-
const statusCb = useCallback((el) => {
|
|
1102
|
-
progressStatusRef.current = el;
|
|
1103
|
-
}, []);
|
|
1104
|
-
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
|
|
1105
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing-image-wrap", children: [
|
|
1106
|
-
previewUrl && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1107
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-processing-blur", style: { backgroundImage: `url(${previewUrl})` } }),
|
|
1108
|
-
/* @__PURE__ */ jsx("img", { src: previewUrl, alt: "Your photo", className: "ps-tryon-processing-model" })
|
|
1109
|
-
] }),
|
|
1110
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-scan-line" }),
|
|
1111
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-scan-overlay" })
|
|
1112
|
-
] }),
|
|
1113
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-progress-section", children: [
|
|
1114
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsx("div", { ref: barCb, className: "ps-tryon-progress-bar-fill" }) }),
|
|
1115
|
-
/* @__PURE__ */ jsx("span", { ref: pctCb, className: "ps-tryon-progress-pct", children: "0%" })
|
|
1116
|
-
] }),
|
|
1117
|
-
/* @__PURE__ */ jsx("div", { ref: statusCb, className: cx("ps-tryon-processing-text", cn.processingText), children: "Preparing your image..." }),
|
|
1118
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-sub", cn.processingSubText), children: "This usually takes 15-25 seconds" })
|
|
1119
|
-
] });
|
|
1120
|
-
}
|
|
1121
|
-
function ResultView() {
|
|
1122
|
-
const hasSizing = !!sizingResult || sizingLoading;
|
|
1123
|
-
const hasBoth = !!resultImageUrl && hasSizing;
|
|
1124
|
-
const [profileName, setProfileName] = useState("");
|
|
1471
|
+
function SizeResultView() {
|
|
1125
1472
|
const [showFitDetails, setShowFitDetails] = useState(false);
|
|
1126
|
-
const confidenceLabel = sizingResult?.confidence === "high" ? "High Confidence" : sizingResult?.confidence === "medium" ? "Medium Confidence" : sizingResult?.confidence === "low" ? "Low Confidence" : "";
|
|
1127
|
-
return /* @__PURE__ */ jsxs("div", { className:
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-size-title", children: "Recommended Size" }),
|
|
1473
|
+
const confidenceLabel = sizingResult?.confidence === "high" ? t("High Confidence") : sizingResult?.confidence === "medium" ? t("Medium Confidence") : sizingResult?.confidence === "low" ? t("Low Confidence") : "";
|
|
1474
|
+
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-result-view", children: [
|
|
1475
|
+
sizingLoading && !sizingResult && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-recommend ps-tryon-sizing-loading", children: [
|
|
1476
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-size-loading-spinner" }),
|
|
1477
|
+
/* @__PURE__ */ jsx("p", { className: "ps-tryon-size-reasoning", children: t("Analyzing your size...") })
|
|
1478
|
+
] }),
|
|
1479
|
+
sizingResult && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1480
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-recommend", children: [
|
|
1481
|
+
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-size-title", children: t("Your Size") }),
|
|
1136
1482
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-hero-row", children: [
|
|
1137
1483
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-size-badge", children: sizingResult.recommendedSize }),
|
|
1138
1484
|
/* @__PURE__ */ jsx("span", { className: `ps-tryon-size-conf-label ps-conf-${sizingResult.confidence}`, children: confidenceLabel })
|
|
1139
1485
|
] }),
|
|
1486
|
+
sizingResult.sections && Object.keys(sizingResult.sections).length > 1 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-multi-section", children: [
|
|
1487
|
+
/* @__PURE__ */ jsx("h4", { className: "ps-tryon-fit-summary-title", children: t("Sizing by Garment") }),
|
|
1488
|
+
Object.entries(sizingResult.sections).map(([name, sec]) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-section-row", children: [
|
|
1489
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-section-name", children: name }),
|
|
1490
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-size-badge ps-tryon-section-badge", children: sec.recommendedSize })
|
|
1491
|
+
] }, name))
|
|
1492
|
+
] }),
|
|
1140
1493
|
sizingResult.matchDetails && sizingResult.matchDetails.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-fit-summary", children: [
|
|
1141
|
-
/* @__PURE__ */ jsx("h4", { className: "ps-tryon-fit-summary-title", children: "Fit Summary" }),
|
|
1494
|
+
/* @__PURE__ */ jsx("h4", { className: "ps-tryon-fit-summary-title", children: t("Fit Summary") }),
|
|
1142
1495
|
sizingResult.matchDetails.map((m, i) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-fit-row", children: [
|
|
1143
1496
|
/* @__PURE__ */ jsx("span", { className: `ps-tryon-fit-icon ps-fit-icon-${m.fit}`, children: m.fit === "good" ? "✓" : m.fit === "tight" ? "↑" : "↓" }),
|
|
1144
1497
|
/* @__PURE__ */ jsxs("span", { className: "ps-tryon-fit-text", children: [
|
|
1145
1498
|
/* @__PURE__ */ jsx("strong", { children: m.measurement }),
|
|
1146
1499
|
" ",
|
|
1147
|
-
m.fit === "good" ? "within range" : m.fit === "tight" ? "may be snug" : "may be loose"
|
|
1500
|
+
m.fit === "good" ? t("within range") : m.fit === "tight" ? t("may be snug") : t("may be loose")
|
|
1148
1501
|
] })
|
|
1149
1502
|
] }, i)),
|
|
1150
|
-
/* @__PURE__ */ jsx("button", { className: "ps-tryon-fit-details-toggle", onClick: () => setShowFitDetails(!showFitDetails), children: showFitDetails ? "Hide
|
|
1503
|
+
/* @__PURE__ */ jsx("button", { className: "ps-tryon-fit-details-toggle", onClick: () => setShowFitDetails(!showFitDetails), children: showFitDetails ? `${t("Hide details")} ↑` : `${t("See details")} ↓` }),
|
|
1151
1504
|
showFitDetails && /* @__PURE__ */ jsxs("table", { className: "ps-tryon-fit-table", children: [
|
|
1152
1505
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
1153
|
-
/* @__PURE__ */ jsx("th", { children: "Area" }),
|
|
1154
|
-
/* @__PURE__ */ jsx("th", { children: "You" }),
|
|
1155
|
-
/* @__PURE__ */ jsx("th", { children: "Chart" }),
|
|
1156
|
-
/* @__PURE__ */ jsx("th", { children: "Fit" })
|
|
1506
|
+
/* @__PURE__ */ jsx("th", { children: t("Area") }),
|
|
1507
|
+
/* @__PURE__ */ jsx("th", { children: t("You") }),
|
|
1508
|
+
/* @__PURE__ */ jsx("th", { children: t("Chart") }),
|
|
1509
|
+
/* @__PURE__ */ jsx("th", { children: t("Fit") })
|
|
1157
1510
|
] }) }),
|
|
1158
1511
|
/* @__PURE__ */ jsx("tbody", { children: sizingResult.matchDetails.map((m, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
1159
1512
|
/* @__PURE__ */ jsx("td", { children: m.measurement }),
|
|
@@ -1164,7 +1517,7 @@ function PrimeStyleTryonInner({
|
|
|
1164
1517
|
] })
|
|
1165
1518
|
] }),
|
|
1166
1519
|
sizingResult.internationalSizes && Object.keys(sizingResult.internationalSizes).length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-equiv-section", children: [
|
|
1167
|
-
/* @__PURE__ */ jsx("h4", { className: "ps-tryon-equiv-title", children: "Equivalent Sizes" }),
|
|
1520
|
+
/* @__PURE__ */ jsx("h4", { className: "ps-tryon-equiv-title", children: t("Equivalent Sizes") }),
|
|
1168
1521
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-equiv-chips", children: Object.entries(sizingResult.internationalSizes).map(([k, v]) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-equiv-chip", children: [
|
|
1169
1522
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-equiv-region", children: k }),
|
|
1170
1523
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-equiv-value", children: v })
|
|
@@ -1172,35 +1525,57 @@ function PrimeStyleTryonInner({
|
|
|
1172
1525
|
] }),
|
|
1173
1526
|
(!sizingResult.matchDetails || sizingResult.matchDetails.length === 0) && sizingResult.reasoning && /* @__PURE__ */ jsx("p", { className: "ps-tryon-size-reasoning", children: sizingResult.reasoning })
|
|
1174
1527
|
] }),
|
|
1175
|
-
/* @__PURE__ */ jsxs("div", { className:
|
|
1176
|
-
/* @__PURE__ */
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
/* @__PURE__ */
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1528
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-tryon-cta", children: [
|
|
1529
|
+
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-cta", onClick: () => setView("upload"), children: [
|
|
1530
|
+
t("See how it looks on you"),
|
|
1531
|
+
" ",
|
|
1532
|
+
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
1533
|
+
] }),
|
|
1534
|
+
/* @__PURE__ */ jsx("button", { className: "ps-tryon-btn-secondary", onClick: handleClose, children: t("Done") })
|
|
1535
|
+
] })
|
|
1536
|
+
] })
|
|
1537
|
+
] });
|
|
1538
|
+
}
|
|
1539
|
+
function ProcessingView() {
|
|
1540
|
+
const barCb = useCallback((el) => {
|
|
1541
|
+
progressBarRef.current = el;
|
|
1542
|
+
if (el) el.style.width = `${Math.round(progressRef.current)}%`;
|
|
1543
|
+
}, []);
|
|
1544
|
+
const pctCb = useCallback((el) => {
|
|
1545
|
+
progressTextRef.current = el;
|
|
1546
|
+
if (el) el.textContent = `${Math.round(progressRef.current)}%`;
|
|
1547
|
+
}, []);
|
|
1548
|
+
const statusCb = useCallback((el) => {
|
|
1549
|
+
progressStatusRef.current = el;
|
|
1550
|
+
}, []);
|
|
1551
|
+
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
|
|
1552
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing-image-wrap", children: [
|
|
1553
|
+
previewUrl && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1554
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-processing-blur", style: { backgroundImage: `url(${previewUrl})` } }),
|
|
1555
|
+
/* @__PURE__ */ jsx("img", { src: previewUrl, alt: t("Your photo"), className: "ps-tryon-processing-model" })
|
|
1200
1556
|
] }),
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1557
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-scan-line" }),
|
|
1558
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-scan-overlay" })
|
|
1559
|
+
] }),
|
|
1560
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-progress-section", children: [
|
|
1561
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsx("div", { ref: barCb, className: "ps-tryon-progress-bar-fill" }) }),
|
|
1562
|
+
/* @__PURE__ */ jsx("span", { ref: pctCb, className: "ps-tryon-progress-pct", children: "0%" })
|
|
1563
|
+
] }),
|
|
1564
|
+
/* @__PURE__ */ jsx("div", { ref: statusCb, className: cx("ps-tryon-processing-text", cn.processingText), children: t("Preparing your image...") }),
|
|
1565
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-sub", cn.processingSubText), children: t("This usually takes 15-25 seconds") })
|
|
1566
|
+
] });
|
|
1567
|
+
}
|
|
1568
|
+
function ResultView() {
|
|
1569
|
+
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-result-layout", children: [
|
|
1570
|
+
resultImageUrl && /* @__PURE__ */ jsx("div", { className: "ps-tryon-result-image-col", children: /* @__PURE__ */ jsx("img", { src: resultImageUrl, alt: t("Try-on result"), className: cn.resultImage }) }),
|
|
1571
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-result-info-col", children: [
|
|
1572
|
+
sizingResult && /* @__PURE__ */ jsx("div", { className: "ps-tryon-size-recommend ps-tryon-size-compact", children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-hero-row", children: [
|
|
1573
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-size-compact-label", children: t("Your size:") }),
|
|
1574
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-size-badge", children: sizingResult.recommendedSize })
|
|
1575
|
+
] }) }),
|
|
1576
|
+
/* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-result-actions", cn.resultActions), children: [
|
|
1577
|
+
/* @__PURE__ */ jsx("button", { onClick: handleDownload, className: cx("ps-tryon-btn-download", cn.downloadButton), children: t("Download") }),
|
|
1578
|
+
/* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-btn-retry", cn.retryButton), children: t("Start Over") })
|
|
1204
1579
|
] })
|
|
1205
1580
|
] })
|
|
1206
1581
|
] });
|
|
@@ -1208,8 +1583,8 @@ function PrimeStyleTryonInner({
|
|
|
1208
1583
|
function ErrorView() {
|
|
1209
1584
|
return /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-error", cn.error), children: [
|
|
1210
1585
|
/* @__PURE__ */ jsx(AlertIcon, {}),
|
|
1211
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-error-text", cn.errorText), children: errorMessage || "Something went wrong" }),
|
|
1212
|
-
/* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-submit", cn.submitButton), children: "Try Again" })
|
|
1586
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-error-text", cn.errorText), children: errorMessage || t("Something went wrong") }),
|
|
1587
|
+
/* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-submit", cn.submitButton), children: t("Try Again") })
|
|
1213
1588
|
] });
|
|
1214
1589
|
}
|
|
1215
1590
|
function DrawerPanel() {
|
|
@@ -1217,9 +1592,9 @@ function PrimeStyleTryonInner({
|
|
|
1217
1592
|
return /* @__PURE__ */ jsxs("div", { className: `ps-tryon-drawer${drawer ? " ps-tryon-drawer-open" : ""}`, children: [
|
|
1218
1593
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-drawer-header", children: [
|
|
1219
1594
|
/* @__PURE__ */ jsx("button", { className: "ps-tryon-drawer-back", onClick: () => setDrawer(null), children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
|
|
1220
|
-
/* @__PURE__ */ jsx("span", { className: "ps-tryon-drawer-title", children: drawer === "profiles" ? "My Profiles" : "History" })
|
|
1595
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-drawer-title", children: drawer === "profiles" ? t("My Profiles") : t("History") })
|
|
1221
1596
|
] }),
|
|
1222
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-list", children: drawer === "profiles" ? profiles.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: "No saved profiles yet." }) : profiles.map((p) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-item", onClick: () => {
|
|
1597
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-list", children: drawer === "profiles" ? profiles.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: t("No saved profiles yet.") }) : profiles.map((p) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-item", onClick: () => {
|
|
1223
1598
|
setProfileDetail(p);
|
|
1224
1599
|
setDrawer(null);
|
|
1225
1600
|
}, children: [
|
|
@@ -1227,18 +1602,18 @@ function PrimeStyleTryonInner({
|
|
|
1227
1602
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-info", children: [
|
|
1228
1603
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-name", children: p.name }),
|
|
1229
1604
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-detail", children: [
|
|
1230
|
-
p.gender === "female" ? "Women's" : "Men's",
|
|
1231
|
-
p.heightCm ? ` · ${Math.round(p.heightCm)}cm` : ""
|
|
1605
|
+
p.gender === "female" ? t("Women's") : t("Men's"),
|
|
1606
|
+
p.heightCm ? ` · ${Math.round(p.heightCm)}${t("cm")}` : ""
|
|
1232
1607
|
] })
|
|
1233
1608
|
] }),
|
|
1234
1609
|
/* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
1235
|
-
] }, p.id)) : history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: "No history yet." }) : history.map((entry, idx) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-item", children: [
|
|
1610
|
+
] }, p.id)) : history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: t("No history yet.") }) : history.map((entry, idx) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-item", children: [
|
|
1236
1611
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-images", children: [
|
|
1237
1612
|
entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
|
|
1238
1613
|
entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" })
|
|
1239
1614
|
] }),
|
|
1240
1615
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-info", children: [
|
|
1241
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-history-product", children: entry.productTitle || "Product" }),
|
|
1616
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-history-product", children: entry.productTitle || t("Product") }),
|
|
1242
1617
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-meta", children: [
|
|
1243
1618
|
entry.profileName ? `${entry.profileName} · ` : "",
|
|
1244
1619
|
new Date(entry.date).toLocaleDateString()
|
|
@@ -1259,20 +1634,20 @@ function PrimeStyleTryonInner({
|
|
|
1259
1634
|
if (!profileDetail) return null;
|
|
1260
1635
|
const p = profileDetail;
|
|
1261
1636
|
const measurements = [
|
|
1262
|
-
{ label: "Height", value: p.heightCm, unit: "cm" },
|
|
1263
|
-
{ label: "Weight", value: p.weightKg, unit: "kg" },
|
|
1264
|
-
{ label: "Chest", value: p.chest, unit: "cm" },
|
|
1265
|
-
{ label: "Bust", value: p.bust, unit: "cm" },
|
|
1266
|
-
{ label: "Waist", value: p.waist, unit: "cm" },
|
|
1267
|
-
{ label: "Hips", value: p.hips, unit: "cm" },
|
|
1268
|
-
{ label: "Shoulders", value: p.shoulderWidth, unit: "cm" },
|
|
1269
|
-
{ label: "Sleeve", value: p.sleeveLength, unit: "cm" },
|
|
1270
|
-
{ label: "Inseam", value: p.inseam, unit: "cm" },
|
|
1271
|
-
{ label: "Neck", value: p.neckCircumference, unit: "cm" },
|
|
1272
|
-
{ label: "Foot", value: p.footLengthCm, unit: "cm" },
|
|
1273
|
-
{ label: "Shoe EU", value: p.shoeEU ? Number(p.shoeEU) : void 0, unit: "" },
|
|
1274
|
-
{ label: "Shoe US", value: p.shoeUS ? Number(p.shoeUS) : void 0, unit: "" },
|
|
1275
|
-
{ label: "Shoe UK", value: p.shoeUK ? Number(p.shoeUK) : void 0, unit: "" }
|
|
1637
|
+
{ label: t("Height"), value: p.heightCm, unit: t("cm") },
|
|
1638
|
+
{ label: t("Weight"), value: p.weightKg, unit: t("kg") },
|
|
1639
|
+
{ label: t("Chest"), value: p.chest, unit: t("cm") },
|
|
1640
|
+
{ label: t("Bust"), value: p.bust, unit: t("cm") },
|
|
1641
|
+
{ label: t("Waist"), value: p.waist, unit: t("cm") },
|
|
1642
|
+
{ label: t("Hips"), value: p.hips, unit: t("cm") },
|
|
1643
|
+
{ label: t("Shoulders"), value: p.shoulderWidth, unit: t("cm") },
|
|
1644
|
+
{ label: t("Sleeve"), value: p.sleeveLength, unit: t("cm") },
|
|
1645
|
+
{ label: t("Inseam"), value: p.inseam, unit: t("cm") },
|
|
1646
|
+
{ label: t("Neck"), value: p.neckCircumference, unit: t("cm") },
|
|
1647
|
+
{ label: t("Foot"), value: p.footLengthCm, unit: t("cm") },
|
|
1648
|
+
{ label: t("Shoe EU"), value: p.shoeEU ? Number(p.shoeEU) : void 0, unit: "" },
|
|
1649
|
+
{ label: t("Shoe US"), value: p.shoeUS ? Number(p.shoeUS) : void 0, unit: "" },
|
|
1650
|
+
{ label: t("Shoe UK"), value: p.shoeUK ? Number(p.shoeUK) : void 0, unit: "" }
|
|
1276
1651
|
].filter((m) => m.value);
|
|
1277
1652
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-overlay", onClick: (e) => {
|
|
1278
1653
|
if (e.target === e.currentTarget) setProfileDetail(null);
|
|
@@ -1285,8 +1660,7 @@ function PrimeStyleTryonInner({
|
|
|
1285
1660
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-gender", children: [
|
|
1286
1661
|
/* @__PURE__ */ jsx(UserIcon, { size: 18 }),
|
|
1287
1662
|
" ",
|
|
1288
|
-
p.gender === "female" ? "Women's" : "Men's"
|
|
1289
|
-
" Profile"
|
|
1663
|
+
p.gender === "female" ? t("Women's Profile") : t("Men's Profile")
|
|
1290
1664
|
] }),
|
|
1291
1665
|
measurements.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-grid", children: measurements.map((m) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell", children: [
|
|
1292
1666
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-cell-label", children: m.label }),
|
|
@@ -1296,7 +1670,8 @@ function PrimeStyleTryonInner({
|
|
|
1296
1670
|
] })
|
|
1297
1671
|
] }, m.label)) }),
|
|
1298
1672
|
p.createdAt && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-date", children: [
|
|
1299
|
-
"Saved
|
|
1673
|
+
t("Saved"),
|
|
1674
|
+
" ",
|
|
1300
1675
|
new Date(p.createdAt).toLocaleDateString()
|
|
1301
1676
|
] }),
|
|
1302
1677
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-detail-delete", onClick: () => {
|
|
@@ -1305,7 +1680,8 @@ function PrimeStyleTryonInner({
|
|
|
1305
1680
|
setProfileDetail(null);
|
|
1306
1681
|
}, children: [
|
|
1307
1682
|
/* @__PURE__ */ jsx(TrashIcon, {}),
|
|
1308
|
-
"
|
|
1683
|
+
" ",
|
|
1684
|
+
t("Delete Profile")
|
|
1309
1685
|
] })
|
|
1310
1686
|
] })
|
|
1311
1687
|
] }) });
|
|
@@ -1314,12 +1690,14 @@ function PrimeStyleTryonInner({
|
|
|
1314
1690
|
switch (view) {
|
|
1315
1691
|
case "welcome":
|
|
1316
1692
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(WelcomeView, {}) }, "v-welcome");
|
|
1317
|
-
case "upload":
|
|
1318
|
-
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(UploadView, {}) }, "v-upload");
|
|
1319
1693
|
case "sizing-choice":
|
|
1320
1694
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingChoiceView, {}) }, "v-choice");
|
|
1321
1695
|
case "sizing-form":
|
|
1322
1696
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingFormView, {}) }, "v-form");
|
|
1697
|
+
case "size-result":
|
|
1698
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizeResultView, {}) }, "v-sizeresult");
|
|
1699
|
+
case "upload":
|
|
1700
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(UploadView, {}) }, "v-upload");
|
|
1323
1701
|
case "processing":
|
|
1324
1702
|
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ProcessingView, {}) }, "v-proc");
|
|
1325
1703
|
case "result":
|
|
@@ -1333,16 +1711,16 @@ function PrimeStyleTryonInner({
|
|
|
1333
1711
|
return /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { ...cssVars, ...style }, "data-ps-tryon": true, children: [
|
|
1334
1712
|
/* @__PURE__ */ jsxs("button", { onClick: handleOpen, className: cx("ps-tryon-btn", cn.button), children: [
|
|
1335
1713
|
showIcon !== false && (buttonIcon || /* @__PURE__ */ jsx(CameraIcon, {})),
|
|
1336
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
1714
|
+
/* @__PURE__ */ jsx("span", { children: resolvedButtonText })
|
|
1337
1715
|
] }),
|
|
1338
1716
|
view !== "idle" && /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), onClick: (e) => {
|
|
1339
1717
|
if (e.target === e.currentTarget) handleClose();
|
|
1340
1718
|
}, children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
|
|
1341
1719
|
/* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header", cn.header), children: [
|
|
1342
|
-
/* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: "Virtual Try-On" }),
|
|
1720
|
+
/* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: t("Virtual Try-On") }),
|
|
1343
1721
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-header-actions", children: [
|
|
1344
|
-
profiles.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: "Profiles", onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
|
|
1345
|
-
history.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: "History", onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
|
|
1722
|
+
profiles.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("Profiles"), onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
|
|
1723
|
+
history.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("History"), onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
|
|
1346
1724
|
/* @__PURE__ */ jsx("button", { onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsx(XIcon, {}) })
|
|
1347
1725
|
] })
|
|
1348
1726
|
] }),
|
|
@@ -1352,7 +1730,7 @@ function PrimeStyleTryonInner({
|
|
|
1352
1730
|
/* @__PURE__ */ jsx(DrawerPanel, {})
|
|
1353
1731
|
] }),
|
|
1354
1732
|
showPoweredBy && /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-powered", cn.poweredBy), children: [
|
|
1355
|
-
"Powered by",
|
|
1733
|
+
t("Powered by"),
|
|
1356
1734
|
" ",
|
|
1357
1735
|
/* @__PURE__ */ jsx("a", { href: "https://myaifitting.com", target: "_blank", rel: "noopener noreferrer", children: "PrimeStyle AI" })
|
|
1358
1736
|
] })
|
|
@@ -1753,8 +2131,27 @@ const STYLES = `
|
|
|
1753
2131
|
.ps-tryon-equiv-region { padding: clamp(4px, 0.36vw, 7px) clamp(6px, 0.52vw, 10px); font-size: clamp(9px, 0.63vw, 12px); color: #999; font-weight: 600; background: rgba(255,255,255,0.03); }
|
|
1754
2132
|
.ps-tryon-equiv-value { padding: clamp(4px, 0.36vw, 7px) clamp(7px, 0.63vw, 12px); font-size: clamp(10px, 0.73vw, 14px); color: #fff; font-weight: 700; }
|
|
1755
2133
|
|
|
2134
|
+
/* Multi-section garment sizing (tuxedo/set) */
|
|
2135
|
+
.ps-tryon-multi-section { margin-bottom: clamp(10px, 0.83vw, 16px); }
|
|
2136
|
+
.ps-tryon-section-row { display: flex; align-items: center; justify-content: space-between; padding: clamp(6px, 0.52vw, 10px) 0; border-bottom: 1px solid #222; }
|
|
2137
|
+
.ps-tryon-section-row:last-child { border-bottom: none; }
|
|
2138
|
+
.ps-tryon-section-name { font-size: clamp(11px, 0.78vw, 15px); color: #ccc; font-weight: 500; }
|
|
2139
|
+
.ps-tryon-section-badge { font-size: clamp(12px, 0.83vw, 16px); min-width: auto; padding: clamp(3px, 0.26vw, 5px) clamp(10px, 0.83vw, 16px); }
|
|
2140
|
+
|
|
1756
2141
|
.ps-tryon-size-reasoning { font-size: clamp(10px, 0.73vw, 14px); color: #ccc; line-height: 1.6; margin-bottom: clamp(8px, 0.73vw, 14px); }
|
|
1757
2142
|
|
|
2143
|
+
/* Size Result View (standalone sizing result before try-on) */
|
|
2144
|
+
.ps-tryon-size-result-view { display: flex; flex-direction: column; gap: clamp(12px, 1vw, 20px); }
|
|
2145
|
+
.ps-tryon-tryon-cta { display: flex; flex-direction: column; gap: clamp(8px, 0.7vw, 12px); margin-top: clamp(8px, 0.7vw, 14px); }
|
|
2146
|
+
.ps-tryon-btn-secondary {
|
|
2147
|
+
background: transparent; border: 1.5px solid #444; color: #999; font-size: clamp(11px, 0.83vw, 15px);
|
|
2148
|
+
font-weight: 600; padding: clamp(8px, 0.7vw, 12px) clamp(16px, 1.3vw, 24px); border-radius: clamp(6px, 0.52vw, 10px);
|
|
2149
|
+
cursor: pointer; transition: all 0.2s;
|
|
2150
|
+
}
|
|
2151
|
+
.ps-tryon-btn-secondary:hover { border-color: #666; color: #ccc; }
|
|
2152
|
+
.ps-tryon-size-compact { padding: clamp(6px, 0.5vw, 10px) 0; }
|
|
2153
|
+
.ps-tryon-size-compact-label { font-size: clamp(11px, 0.78vw, 14px); color: #999; font-weight: 500; }
|
|
2154
|
+
|
|
1758
2155
|
/* Save profile prompt */
|
|
1759
2156
|
.ps-tryon-save-prompt { margin-top: clamp(8px, 0.73vw, 14px); padding: clamp(8px, 0.73vw, 14px); border: 1px solid #333; border-radius: clamp(8px, 0.63vw, 12px); background: #1a1b1a; }
|
|
1760
2157
|
.ps-tryon-save-label { font-size: clamp(9px, 0.63vw, 12px); color: #999; margin-bottom: clamp(6px, 0.52vw, 10px); }
|