@primestyleai/tryon 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/index.js +177 -134
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -60,6 +60,22 @@ function lbsToKg(lbs) {
|
|
|
60
60
|
function ftInToCm(ft, inch) {
|
|
61
61
|
return +(ft * 30.48 + inch * 2.54).toFixed(1);
|
|
62
62
|
}
|
|
63
|
+
function SvgIcon({ d, size = 18, strokeWidth = 2 }) {
|
|
64
|
+
return /* @__PURE__ */ jsx(
|
|
65
|
+
"svg",
|
|
66
|
+
{
|
|
67
|
+
width: size,
|
|
68
|
+
height: size,
|
|
69
|
+
viewBox: "0 0 24 24",
|
|
70
|
+
fill: "none",
|
|
71
|
+
stroke: "currentColor",
|
|
72
|
+
strokeWidth,
|
|
73
|
+
strokeLinecap: "round",
|
|
74
|
+
strokeLinejoin: "round",
|
|
75
|
+
children: /* @__PURE__ */ jsx("path", { d })
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
63
79
|
function CameraIcon({ size = 18 }) {
|
|
64
80
|
return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
65
81
|
/* @__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" }),
|
|
@@ -160,7 +176,9 @@ function PrimeStyleTryon({
|
|
|
160
176
|
const [resultImageUrl, setResultImageUrl] = useState(null);
|
|
161
177
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
162
178
|
const [dragOver, setDragOver] = useState(false);
|
|
163
|
-
const
|
|
179
|
+
const countdownRef = useRef(25);
|
|
180
|
+
const countdownElRef = useRef(null);
|
|
181
|
+
const countdownCircleRef = useRef(null);
|
|
164
182
|
const [sizingMethod, setSizingMethod] = useState(null);
|
|
165
183
|
const [sizingResult, setSizingResult] = useState(null);
|
|
166
184
|
const [sizeGuide, setSizeGuide] = useState(null);
|
|
@@ -169,7 +187,8 @@ function PrimeStyleTryon({
|
|
|
169
187
|
const [sizingUnit, setSizingUnit] = useState(imperial ? "in" : "cm");
|
|
170
188
|
const [heightUnit, setHeightUnit] = useState(imperial ? "ft" : "cm");
|
|
171
189
|
const [weightUnit, setWeightUnit] = useState(imperial ? "lbs" : "kg");
|
|
172
|
-
const
|
|
190
|
+
const formRef = useRef({});
|
|
191
|
+
const [formGender, setFormGender] = useState("male");
|
|
173
192
|
const [profiles, setProfiles] = useState(() => lsGet("profiles", []));
|
|
174
193
|
const [history, setHistory] = useState(() => lsGet("history", []));
|
|
175
194
|
const [activeProfileId, setActiveProfileId] = useState(null);
|
|
@@ -199,15 +218,12 @@ function PrimeStyleTryon({
|
|
|
199
218
|
}, [apiUrl]);
|
|
200
219
|
useEffect(() => {
|
|
201
220
|
if (view === "processing") {
|
|
202
|
-
|
|
221
|
+
countdownRef.current = 25;
|
|
203
222
|
const interval = setInterval(() => {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
return p - 1;
|
|
210
|
-
});
|
|
223
|
+
countdownRef.current -= 1;
|
|
224
|
+
if (countdownElRef.current) countdownElRef.current.textContent = String(Math.max(countdownRef.current, 0));
|
|
225
|
+
if (countdownCircleRef.current) countdownCircleRef.current.style.strokeDashoffset = `${Math.max(countdownRef.current, 0) / 25 * 326.73}`;
|
|
226
|
+
if (countdownRef.current <= 0) clearInterval(interval);
|
|
211
227
|
}, 1e3);
|
|
212
228
|
return () => clearInterval(interval);
|
|
213
229
|
}
|
|
@@ -275,7 +291,8 @@ function PrimeStyleTryon({
|
|
|
275
291
|
setSizingResult(null);
|
|
276
292
|
setSizeGuide(null);
|
|
277
293
|
setProfileSaved(false);
|
|
278
|
-
|
|
294
|
+
formRef.current = {};
|
|
295
|
+
setFormGender("male");
|
|
279
296
|
unsubRef.current?.();
|
|
280
297
|
unsubRef.current = null;
|
|
281
298
|
if (pollingRef.current) {
|
|
@@ -349,23 +366,23 @@ function PrimeStyleTryon({
|
|
|
349
366
|
};
|
|
350
367
|
if (sizeGuide?.found) payload.sizeGuide = sizeGuide;
|
|
351
368
|
if (sizingMethod === "exact") {
|
|
352
|
-
const m = { gender:
|
|
353
|
-
if (
|
|
354
|
-
if (
|
|
369
|
+
const m = { gender: formRef.current.gender || "male" };
|
|
370
|
+
if (formRef.current.height) m.heightCm = heightUnit === "ft" ? ftInToCm(parseFloat(formRef.current.heightFeet || "0"), parseFloat(formRef.current.heightInches || "0")) : parseFloat(formRef.current.height);
|
|
371
|
+
if (formRef.current.weight) m.weightKg = weightUnit === "lbs" ? lbsToKg(parseFloat(formRef.current.weight)) : parseFloat(formRef.current.weight);
|
|
355
372
|
const keys = ["chest", "bust", "waist", "hips", "shoulderWidth", "sleeveLength", "inseam", "neckCircumference", "footLengthCm"];
|
|
356
373
|
for (const k of keys) {
|
|
357
|
-
if (
|
|
374
|
+
if (formRef.current[k]) m[k] = sizingUnit === "in" ? inToCm(parseFloat(formRef.current[k])) : parseFloat(formRef.current[k]);
|
|
358
375
|
}
|
|
359
|
-
if (
|
|
360
|
-
if (
|
|
361
|
-
if (
|
|
362
|
-
if (
|
|
376
|
+
if (formRef.current.shoeEU) m.shoeEU = formRef.current.shoeEU;
|
|
377
|
+
if (formRef.current.shoeUS) m.shoeUS = formRef.current.shoeUS;
|
|
378
|
+
if (formRef.current.shoeUK) m.shoeUK = formRef.current.shoeUK;
|
|
379
|
+
if (formRef.current.fitPreference) m.fitPreference = formRef.current.fitPreference;
|
|
363
380
|
payload.measurements = m;
|
|
364
381
|
} else {
|
|
365
382
|
payload.quickEstimate = {
|
|
366
|
-
heightCm: heightUnit === "ft" ? ftInToCm(parseFloat(
|
|
367
|
-
weightKg: weightUnit === "lbs" ? lbsToKg(parseFloat(
|
|
368
|
-
gender:
|
|
383
|
+
heightCm: heightUnit === "ft" ? ftInToCm(parseFloat(formRef.current.heightFeet || "0"), parseFloat(formRef.current.heightInches || "0")) : parseFloat(formRef.current.height || "0"),
|
|
384
|
+
weightKg: weightUnit === "lbs" ? lbsToKg(parseFloat(formRef.current.weight || "0")) : parseFloat(formRef.current.weight || "0"),
|
|
385
|
+
gender: formRef.current.gender || "male"
|
|
369
386
|
};
|
|
370
387
|
}
|
|
371
388
|
try {
|
|
@@ -380,7 +397,7 @@ function PrimeStyleTryon({
|
|
|
380
397
|
}
|
|
381
398
|
} catch {
|
|
382
399
|
}
|
|
383
|
-
}, [apiUrl, sizingMethod, sizingCountry,
|
|
400
|
+
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle]);
|
|
384
401
|
const handleSubmit = useCallback(async () => {
|
|
385
402
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
386
403
|
const msg = !apiRef.current ? "Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY" : "No file selected";
|
|
@@ -477,29 +494,30 @@ function PrimeStyleTryon({
|
|
|
477
494
|
if (p.shoeUS) fd.shoeUS = p.shoeUS;
|
|
478
495
|
if (p.shoeUK) fd.shoeUK = p.shoeUK;
|
|
479
496
|
if (p.fitPreference) fd.fitPreference = p.fitPreference;
|
|
480
|
-
|
|
497
|
+
formRef.current = fd;
|
|
498
|
+
setFormGender(fd.gender || "male");
|
|
481
499
|
}, [profiles]);
|
|
482
500
|
const saveProfile = useCallback((name) => {
|
|
483
501
|
const id = activeProfileId || `p_${Date.now()}`;
|
|
484
502
|
const p = {
|
|
485
503
|
id,
|
|
486
504
|
name,
|
|
487
|
-
gender:
|
|
488
|
-
heightCm:
|
|
489
|
-
weightKg:
|
|
490
|
-
chest:
|
|
491
|
-
bust:
|
|
492
|
-
waist:
|
|
493
|
-
hips:
|
|
494
|
-
shoulderWidth:
|
|
495
|
-
sleeveLength:
|
|
496
|
-
inseam:
|
|
497
|
-
neckCircumference:
|
|
498
|
-
footLengthCm:
|
|
499
|
-
shoeEU:
|
|
500
|
-
shoeUS:
|
|
501
|
-
shoeUK:
|
|
502
|
-
fitPreference:
|
|
505
|
+
gender: formRef.current.gender || "male",
|
|
506
|
+
heightCm: formRef.current.height ? parseFloat(formRef.current.height) : void 0,
|
|
507
|
+
weightKg: formRef.current.weight ? parseFloat(formRef.current.weight) : void 0,
|
|
508
|
+
chest: formRef.current.chest ? parseFloat(formRef.current.chest) : void 0,
|
|
509
|
+
bust: formRef.current.bust ? parseFloat(formRef.current.bust) : void 0,
|
|
510
|
+
waist: formRef.current.waist ? parseFloat(formRef.current.waist) : void 0,
|
|
511
|
+
hips: formRef.current.hips ? parseFloat(formRef.current.hips) : void 0,
|
|
512
|
+
shoulderWidth: formRef.current.shoulderWidth ? parseFloat(formRef.current.shoulderWidth) : void 0,
|
|
513
|
+
sleeveLength: formRef.current.sleeveLength ? parseFloat(formRef.current.sleeveLength) : void 0,
|
|
514
|
+
inseam: formRef.current.inseam ? parseFloat(formRef.current.inseam) : void 0,
|
|
515
|
+
neckCircumference: formRef.current.neckCircumference ? parseFloat(formRef.current.neckCircumference) : void 0,
|
|
516
|
+
footLengthCm: formRef.current.footLengthCm ? parseFloat(formRef.current.footLengthCm) : void 0,
|
|
517
|
+
shoeEU: formRef.current.shoeEU,
|
|
518
|
+
shoeUS: formRef.current.shoeUS,
|
|
519
|
+
shoeUK: formRef.current.shoeUK,
|
|
520
|
+
fitPreference: formRef.current.fitPreference,
|
|
503
521
|
createdAt: Date.now()
|
|
504
522
|
};
|
|
505
523
|
setProfiles((prev) => {
|
|
@@ -513,7 +531,7 @@ function PrimeStyleTryon({
|
|
|
513
531
|
});
|
|
514
532
|
setActiveProfileId(id);
|
|
515
533
|
setProfileSaved(true);
|
|
516
|
-
}, [activeProfileId
|
|
534
|
+
}, [activeProfileId]);
|
|
517
535
|
const saveHistoryEntry = useCallback(() => {
|
|
518
536
|
const entry = {
|
|
519
537
|
id: `h_${Date.now()}`,
|
|
@@ -539,7 +557,7 @@ function PrimeStyleTryon({
|
|
|
539
557
|
}
|
|
540
558
|
}, [view]);
|
|
541
559
|
const updateField = useCallback((key, val) => {
|
|
542
|
-
|
|
560
|
+
formRef.current[key] = val;
|
|
543
561
|
}, []);
|
|
544
562
|
const shoeField = useMemo(() => {
|
|
545
563
|
const map = {
|
|
@@ -604,8 +622,8 @@ function PrimeStyleTryon({
|
|
|
604
622
|
{
|
|
605
623
|
type,
|
|
606
624
|
placeholder,
|
|
607
|
-
|
|
608
|
-
|
|
625
|
+
defaultValue: formRef.current[fieldKey] || "",
|
|
626
|
+
onInput: (e) => updateField(fieldKey, e.target.value)
|
|
609
627
|
}
|
|
610
628
|
),
|
|
611
629
|
unit && /* @__PURE__ */ jsx("span", { className: "ps-tryon-input-unit", children: unit })
|
|
@@ -709,76 +727,92 @@ function PrimeStyleTryon({
|
|
|
709
727
|
setView("sizing-form");
|
|
710
728
|
}, children: [
|
|
711
729
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 24 }) }),
|
|
712
|
-
/* @__PURE__ */
|
|
713
|
-
|
|
714
|
-
|
|
730
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
731
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Enter my measurements" }),
|
|
732
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Chest, waist, hips, shoes & more" })
|
|
733
|
+
] }),
|
|
734
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: "Best accuracy" })
|
|
715
735
|
] }),
|
|
716
736
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
|
|
717
737
|
setSizingMethod("quick");
|
|
718
738
|
setView("sizing-form");
|
|
719
739
|
}, children: [
|
|
720
740
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 24 }) }),
|
|
721
|
-
/* @__PURE__ */
|
|
722
|
-
|
|
741
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
742
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Just height & weight" }),
|
|
743
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Quick estimate in seconds" })
|
|
744
|
+
] })
|
|
745
|
+
] }),
|
|
746
|
+
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
|
|
747
|
+
setSizingMethod(null);
|
|
748
|
+
handleSubmit();
|
|
749
|
+
}, children: [
|
|
750
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SvgIcon, { d: "M13 5H1M13 9H1M13 13H1M5 17l4 4 8-8", size: 24, strokeWidth: 1.5 }) }),
|
|
751
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
|
|
752
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Skip sizing" }),
|
|
753
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Just show me the try-on" })
|
|
754
|
+
] })
|
|
723
755
|
] })
|
|
724
|
-
] })
|
|
725
|
-
/* @__PURE__ */ jsx("button", { className: "ps-tryon-skip-btn", onClick: () => {
|
|
726
|
-
setSizingMethod(null);
|
|
727
|
-
handleSubmit();
|
|
728
|
-
}, children: "Skip sizing — just try it on" })
|
|
756
|
+
] })
|
|
729
757
|
] });
|
|
730
758
|
}
|
|
731
759
|
function SizingFormView() {
|
|
732
|
-
const isFemale =
|
|
760
|
+
const isFemale = formGender === "female";
|
|
761
|
+
const isCm = sizingUnit === "cm";
|
|
733
762
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
|
|
734
763
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
735
|
-
/* @__PURE__ */ jsx("label", { children: "
|
|
736
|
-
/* @__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)) })
|
|
737
|
-
] }),
|
|
738
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
739
|
-
/* @__PURE__ */ jsx("label", { children: "Gender" }),
|
|
764
|
+
/* @__PURE__ */ jsx("label", { children: "I'm shopping for" }),
|
|
740
765
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-toggle", children: [
|
|
741
|
-
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${
|
|
742
|
-
|
|
766
|
+
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${!isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
767
|
+
updateField("gender", "male");
|
|
768
|
+
setFormGender("male");
|
|
769
|
+
}, children: "Men's" }),
|
|
770
|
+
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
771
|
+
updateField("gender", "female");
|
|
772
|
+
setFormGender("female");
|
|
773
|
+
}, children: "Women's" })
|
|
743
774
|
] })
|
|
744
775
|
] }),
|
|
745
776
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
746
|
-
/* @__PURE__ */ jsx("label", { children: "
|
|
747
|
-
/* @__PURE__ */ jsx(
|
|
777
|
+
/* @__PURE__ */ jsx("label", { children: "Sizing region" }),
|
|
778
|
+
/* @__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)) })
|
|
748
779
|
] }),
|
|
749
|
-
|
|
750
|
-
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "ft", value: formData.heightFeet || "", onChange: (e) => updateField("heightFeet", e.target.value) }),
|
|
751
|
-
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "in", value: formData.heightInches || "", onChange: (e) => updateField("heightInches", e.target.value) })
|
|
752
|
-
] }) : /* @__PURE__ */ jsx(InputRow, { label: "", fieldKey: "height", placeholder: "e.g. 175", type: "number", unit: "cm" }),
|
|
780
|
+
sizingMethod === "exact" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: setSizingUnit }) }),
|
|
753
781
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
754
|
-
/* @__PURE__ */ jsx("label", { children: "
|
|
755
|
-
/* @__PURE__ */
|
|
782
|
+
/* @__PURE__ */ jsx("label", { children: "Height" }),
|
|
783
|
+
heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-height-ft", children: [
|
|
784
|
+
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", defaultValue: formRef.current.heightFeet || "", onInput: (e) => updateField("heightFeet", e.target.value) }),
|
|
785
|
+
/* @__PURE__ */ jsx("span", { children: "ft" }),
|
|
786
|
+
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "4", defaultValue: formRef.current.heightInches || "", onInput: (e) => updateField("heightInches", e.target.value) }),
|
|
787
|
+
/* @__PURE__ */ jsx("span", { children: "in" })
|
|
788
|
+
] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175", defaultValue: formRef.current.height || "", onInput: (e) => updateField("height", e.target.value) }),
|
|
789
|
+
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "ft", value: "ft" }], value: heightUnit, onChange: setHeightUnit })
|
|
756
790
|
] }),
|
|
757
|
-
|
|
758
|
-
sizingMethod === "exact" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
759
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
760
|
-
/* @__PURE__ */ jsx("label", { children: "Measurements" }),
|
|
761
|
-
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: setSizingUnit })
|
|
762
|
-
] }),
|
|
791
|
+
sizingMethod === "exact" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
763
792
|
isFemale ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
764
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Bust", fieldKey: "bust", placeholder: "e.g.
|
|
765
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g. 70", type: "number", unit: sizingUnit }),
|
|
766
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Hips", fieldKey: "hips", placeholder: "e.g.
|
|
793
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Bust *", fieldKey: "bust", placeholder: isCm ? "e.g. 88" : "e.g. 35", type: "number", unit: sizingUnit }),
|
|
794
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Waist *", fieldKey: "waist", placeholder: isCm ? "e.g. 70" : "e.g. 28", type: "number", unit: sizingUnit }),
|
|
795
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Hips *", fieldKey: "hips", placeholder: isCm ? "e.g. 96" : "e.g. 38", type: "number", unit: sizingUnit }),
|
|
796
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Shoulders", fieldKey: "shoulderWidth", placeholder: isCm ? "e.g. 39" : "e.g. 15", type: "number", unit: sizingUnit }),
|
|
797
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: isCm ? "e.g. 76" : "e.g. 30", type: "number", unit: sizingUnit })
|
|
767
798
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
768
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Chest", fieldKey: "chest", placeholder: "e.g.
|
|
769
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g.
|
|
770
|
-
/* @__PURE__ */ jsx(InputRow, { label: "
|
|
799
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Chest *", fieldKey: "chest", placeholder: isCm ? "e.g. 104" : "e.g. 41", type: "number", unit: sizingUnit }),
|
|
800
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Waist *", fieldKey: "waist", placeholder: isCm ? "e.g. 84" : "e.g. 33", type: "number", unit: sizingUnit }),
|
|
801
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Shoulders", fieldKey: "shoulderWidth", placeholder: isCm ? "e.g. 46" : "e.g. 18", type: "number", unit: sizingUnit }),
|
|
802
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Sleeve", fieldKey: "sleeveLength", placeholder: isCm ? "e.g. 64" : "e.g. 25", type: "number", unit: sizingUnit }),
|
|
803
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: isCm ? "e.g. 81" : "e.g. 32", type: "number", unit: sizingUnit })
|
|
771
804
|
] }),
|
|
772
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Shoulder Width", fieldKey: "shoulderWidth", placeholder: "e.g. 45", type: "number", unit: sizingUnit }),
|
|
773
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Sleeve Length", fieldKey: "sleeveLength", placeholder: "e.g. 65", type: "number", unit: sizingUnit }),
|
|
774
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: "e.g. 80", type: "number", unit: sizingUnit }),
|
|
775
805
|
isFemale && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
776
|
-
/* @__PURE__ */ jsx("label", { children: "Fit
|
|
806
|
+
/* @__PURE__ */ jsx("label", { children: "Fit type" }),
|
|
777
807
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: ["petite", "standard", "tall", "plus"].map((fp) => /* @__PURE__ */ jsx(
|
|
778
808
|
"button",
|
|
779
809
|
{
|
|
780
|
-
className: `ps-tryon-unit-btn${(
|
|
781
|
-
onClick: () =>
|
|
810
|
+
className: `ps-tryon-unit-btn${(formRef.current.fitPreference || "standard") === fp ? " ps-active" : ""}`,
|
|
811
|
+
onClick: (e) => {
|
|
812
|
+
updateField("fitPreference", fp);
|
|
813
|
+
const btns = e.target.parentElement.querySelectorAll(".ps-tryon-unit-btn");
|
|
814
|
+
btns.forEach((b) => b.classList.toggle("ps-active", b.textContent?.toLowerCase() === fp));
|
|
815
|
+
},
|
|
782
816
|
children: fp.charAt(0).toUpperCase() + fp.slice(1)
|
|
783
817
|
},
|
|
784
818
|
fp
|
|
@@ -786,28 +820,32 @@ function PrimeStyleTryon({
|
|
|
786
820
|
] }),
|
|
787
821
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-shoe-section", children: [
|
|
788
822
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-shoe-title", children: "Shoe sizing (optional)" }),
|
|
789
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Foot length", fieldKey: "footLengthCm", placeholder:
|
|
823
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Foot length", fieldKey: "footLengthCm", placeholder: isCm ? "e.g. 27" : "e.g. 10.5", type: "number", unit: sizingUnit }),
|
|
790
824
|
/* @__PURE__ */ jsx(InputRow, { label: shoeField.label, fieldKey: shoeField.key, placeholder: shoeField.ph })
|
|
791
825
|
] })
|
|
792
|
-
] }),
|
|
826
|
+
] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
827
|
+
/* @__PURE__ */ jsx("label", { children: "Weight" }),
|
|
828
|
+
/* @__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) }),
|
|
829
|
+
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "kg", value: "kg" }, { label: "lbs", value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
|
|
830
|
+
] }) }),
|
|
793
831
|
/* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
|
|
794
832
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: handleSubmit, children: [
|
|
795
833
|
"Get My Size & Try On ",
|
|
796
834
|
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
797
835
|
] })
|
|
798
|
-
] });
|
|
836
|
+
] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}`);
|
|
799
837
|
}
|
|
800
838
|
function ProcessingView() {
|
|
801
839
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
|
|
802
|
-
|
|
840
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-countdown-ring", children: [
|
|
803
841
|
/* @__PURE__ */ jsxs("svg", { viewBox: "0 0 120 120", children: [
|
|
804
842
|
/* @__PURE__ */ jsx("circle", { className: "ps-tryon-countdown-track", cx: "60", cy: "60", r: "52" }),
|
|
805
|
-
/* @__PURE__ */ jsx("circle", { className: "ps-tryon-countdown-progress", cx: "60", cy: "60", r: "52", style: { strokeDashoffset: `${
|
|
843
|
+
/* @__PURE__ */ jsx("circle", { ref: countdownCircleRef, className: "ps-tryon-countdown-progress", cx: "60", cy: "60", r: "52", style: { strokeDashoffset: `${25 / 25 * 326.73}` } })
|
|
806
844
|
] }),
|
|
807
|
-
/* @__PURE__ */ jsx("span", { className: "ps-tryon-countdown-number", children:
|
|
808
|
-
] })
|
|
809
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-text", cn.processingText), children:
|
|
810
|
-
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-sub", cn.processingSubText), children:
|
|
845
|
+
/* @__PURE__ */ jsx("span", { ref: countdownElRef, className: "ps-tryon-countdown-number", children: "25" })
|
|
846
|
+
] }),
|
|
847
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-text", cn.processingText), children: "Generating your try-on..." }),
|
|
848
|
+
/* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-sub", cn.processingSubText), children: "This usually takes 15-25 seconds" })
|
|
811
849
|
] });
|
|
812
850
|
}
|
|
813
851
|
function ResultView() {
|
|
@@ -851,14 +889,17 @@ function PrimeStyleTryon({
|
|
|
851
889
|
/* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-btn-retry", cn.retryButton), children: "Try Another" })
|
|
852
890
|
] }),
|
|
853
891
|
sizingMethod && !profileSaved && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-prompt", children: [
|
|
854
|
-
/* @__PURE__ */ jsx("
|
|
855
|
-
/* @__PURE__ */
|
|
856
|
-
|
|
857
|
-
|
|
892
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-save-label", children: "Save your measurements for next time" }),
|
|
893
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-row", children: [
|
|
894
|
+
/* @__PURE__ */ jsx("input", { type: "text", placeholder: "Name this profile (e.g. John, Sarah)", value: profileName, onChange: (e) => setProfileName(e.target.value) }),
|
|
895
|
+
/* @__PURE__ */ jsx("button", { onClick: () => {
|
|
896
|
+
if (profileName.trim()) saveProfile(profileName.trim());
|
|
897
|
+
}, children: "Save" })
|
|
898
|
+
] })
|
|
858
899
|
] }),
|
|
859
900
|
profileSaved && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-done", children: [
|
|
860
901
|
/* @__PURE__ */ jsx(CheckIcon, {}),
|
|
861
|
-
"
|
|
902
|
+
" Measurements saved to profile"
|
|
862
903
|
] })
|
|
863
904
|
] })
|
|
864
905
|
] });
|
|
@@ -966,19 +1007,19 @@ function PrimeStyleTryon({
|
|
|
966
1007
|
function renderBody() {
|
|
967
1008
|
switch (view) {
|
|
968
1009
|
case "welcome":
|
|
969
|
-
return /* @__PURE__ */ jsx(WelcomeView, {});
|
|
1010
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(WelcomeView, {}) }, "v-welcome");
|
|
970
1011
|
case "upload":
|
|
971
|
-
return /* @__PURE__ */ jsx(UploadView, {});
|
|
1012
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(UploadView, {}) }, "v-upload");
|
|
972
1013
|
case "sizing-choice":
|
|
973
|
-
return /* @__PURE__ */ jsx(SizingChoiceView, {});
|
|
1014
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingChoiceView, {}) }, "v-choice");
|
|
974
1015
|
case "sizing-form":
|
|
975
|
-
return /* @__PURE__ */ jsx(SizingFormView, {});
|
|
1016
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingFormView, {}) }, "v-form");
|
|
976
1017
|
case "processing":
|
|
977
|
-
return /* @__PURE__ */ jsx(ProcessingView, {});
|
|
1018
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ProcessingView, {}) }, "v-proc");
|
|
978
1019
|
case "result":
|
|
979
|
-
return /* @__PURE__ */ jsx(ResultView, {});
|
|
1020
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ResultView, {}) }, "v-result");
|
|
980
1021
|
case "error":
|
|
981
|
-
return /* @__PURE__ */ jsx(ErrorView, {});
|
|
1022
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ErrorView, {}) }, "v-error");
|
|
982
1023
|
default:
|
|
983
1024
|
return null;
|
|
984
1025
|
}
|
|
@@ -1095,8 +1136,8 @@ const STYLES = `
|
|
|
1095
1136
|
|
|
1096
1137
|
/* Body */
|
|
1097
1138
|
.ps-tryon-body { padding: 24px; min-height: 300px; }
|
|
1098
|
-
.ps-tryon-body > * { animation: ps-fade-up 0.35s ease both; }
|
|
1099
1139
|
@keyframes ps-fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
|
|
1140
|
+
.ps-tryon-view-enter { animation: ps-fade-up 0.35s ease both; }
|
|
1100
1141
|
|
|
1101
1142
|
/* Welcome */
|
|
1102
1143
|
.ps-tryon-welcome { text-align: center; }
|
|
@@ -1168,28 +1209,25 @@ const STYLES = `
|
|
|
1168
1209
|
|
|
1169
1210
|
/* Sizing choice */
|
|
1170
1211
|
.ps-tryon-sizing-choice { text-align: center; }
|
|
1171
|
-
.ps-tryon-section-title { font-size: 16px; font-weight: 600; color: #fff; margin: 0 0
|
|
1172
|
-
.ps-tryon-choice-cards { display: flex; flex-direction: column; gap:
|
|
1212
|
+
.ps-tryon-section-title { font-size: 16px; font-weight: 600; color: #fff; margin: 0 0 16px; }
|
|
1213
|
+
.ps-tryon-choice-cards { display: flex; flex-direction: column; gap: 10px; }
|
|
1173
1214
|
.ps-tryon-choice-card {
|
|
1174
|
-
|
|
1215
|
+
display: flex; align-items: center; gap: 14px; padding: 16px;
|
|
1216
|
+
border: 1.5px solid #333; border-radius: 12px;
|
|
1175
1217
|
background: #1a1b1a; cursor: pointer; transition: all 0.25s; text-align: left;
|
|
1176
|
-
|
|
1218
|
+
width: 100%; font-family: inherit; position: relative; overflow: hidden;
|
|
1177
1219
|
}
|
|
1178
|
-
.ps-tryon-choice-card:hover { border-color: #bb945c; box-shadow: 0
|
|
1179
|
-
.ps-tryon-choice-
|
|
1220
|
+
.ps-tryon-choice-card:hover { border-color: #bb945c; transform: translateY(-1px); box-shadow: 0 6px 20px rgba(187,148,92,0.08); }
|
|
1221
|
+
.ps-tryon-choice-card:hover::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #bb945c; }
|
|
1222
|
+
.ps-tryon-choice-icon { color: #bb945c; flex-shrink: 0; }
|
|
1180
1223
|
.ps-tryon-choice-icon svg { stroke: currentColor; fill: none; }
|
|
1181
|
-
.ps-tryon-choice-
|
|
1182
|
-
.ps-tryon-choice-
|
|
1224
|
+
.ps-tryon-choice-info { flex: 1; min-width: 0; }
|
|
1225
|
+
.ps-tryon-choice-title { font-size: 14px; font-weight: 600; color: #fff; }
|
|
1226
|
+
.ps-tryon-choice-desc { font-size: 12px; color: #999; margin-top: 2px; }
|
|
1183
1227
|
.ps-tryon-choice-badge {
|
|
1184
|
-
|
|
1185
|
-
background: rgba(187,148,92,0.12); color: #bb945c; font-size:
|
|
1186
|
-
}
|
|
1187
|
-
.ps-tryon-skip-btn {
|
|
1188
|
-
margin-top: 16px; padding: 10px; background: none; border: 1px solid #333;
|
|
1189
|
-
border-radius: 10px; color: #999; font-size: 13px; cursor: pointer; transition: all 0.2s;
|
|
1190
|
-
width: 100%; font-family: inherit;
|
|
1228
|
+
padding: 3px 10px; border-radius: 20px; flex-shrink: 0;
|
|
1229
|
+
background: rgba(187,148,92,0.12); color: #bb945c; font-size: 10px; font-weight: 600;
|
|
1191
1230
|
}
|
|
1192
|
-
.ps-tryon-skip-btn:hover { border-color: #666; color: #ccc; }
|
|
1193
1231
|
|
|
1194
1232
|
/* Sizing form */
|
|
1195
1233
|
.ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 12px; }
|
|
@@ -1204,8 +1242,11 @@ const STYLES = `
|
|
|
1204
1242
|
.ps-tryon-input-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
|
1205
1243
|
.ps-tryon-input-row input:focus { border-color: #bb945c; }
|
|
1206
1244
|
.ps-tryon-input-unit { font-size: 12px; color: #666; flex-shrink: 0; }
|
|
1207
|
-
.ps-tryon-
|
|
1208
|
-
.ps-tryon-
|
|
1245
|
+
.ps-tryon-height-ft { display: flex; align-items: center; gap: 6px; flex: 1; }
|
|
1246
|
+
.ps-tryon-height-ft input { width: 60px; padding: 10px 10px; border: 1.5px solid #333; border-radius: 10px; background: #1a1b1a; color: #fff; font-size: 14px; font-family: inherit; outline: none; text-align: center; -moz-appearance: textfield; }
|
|
1247
|
+
.ps-tryon-height-ft input::-webkit-outer-spin-button, .ps-tryon-height-ft input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
|
1248
|
+
.ps-tryon-height-ft input:focus { border-color: #bb945c; }
|
|
1249
|
+
.ps-tryon-height-ft span { font-size: 12px; color: #666; }
|
|
1209
1250
|
.ps-tryon-country-select {
|
|
1210
1251
|
flex: 1; padding: 10px 36px 10px 14px; border: 1.5px solid #333; border-radius: 10px;
|
|
1211
1252
|
background: #1a1b1a; color: #fff; font-size: 13px; font-family: inherit;
|
|
@@ -1280,17 +1321,19 @@ const STYLES = `
|
|
|
1280
1321
|
.ps-fit-good { color: #4ade80; } .ps-fit-tight { color: #f59e0b; } .ps-fit-loose { color: #60a5fa; }
|
|
1281
1322
|
|
|
1282
1323
|
/* Save profile prompt */
|
|
1283
|
-
.ps-tryon-save-prompt {
|
|
1284
|
-
.ps-tryon-save-
|
|
1324
|
+
.ps-tryon-save-prompt { margin-top: 14px; padding: 14px; border: 1px solid #333; border-radius: 12px; background: #1a1b1a; }
|
|
1325
|
+
.ps-tryon-save-label { font-size: 12px; color: #999; margin-bottom: 10px; }
|
|
1326
|
+
.ps-tryon-save-row { display: flex; gap: 8px; }
|
|
1327
|
+
.ps-tryon-save-row input {
|
|
1285
1328
|
flex: 1; padding: 10px 14px; border: 1.5px solid #333; border-radius: 10px;
|
|
1286
|
-
background: #
|
|
1329
|
+
background: #111211; color: #fff; font-size: 13px; font-family: inherit; outline: none;
|
|
1287
1330
|
}
|
|
1288
|
-
.ps-tryon-save-
|
|
1289
|
-
.ps-tryon-save-
|
|
1331
|
+
.ps-tryon-save-row input:focus { border-color: #bb945c; }
|
|
1332
|
+
.ps-tryon-save-row button {
|
|
1290
1333
|
padding: 10px 20px; background: #bb945c; color: #111; border: none; border-radius: 10px;
|
|
1291
1334
|
font-size: 13px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; font-family: inherit;
|
|
1292
1335
|
}
|
|
1293
|
-
.ps-tryon-save-
|
|
1336
|
+
.ps-tryon-save-row button:hover { opacity: 0.9; }
|
|
1294
1337
|
.ps-tryon-save-done { font-size: 12px; color: #4ade80; margin-top: 10px; display: flex; align-items: center; gap: 6px; justify-content: center; }
|
|
1295
1338
|
.ps-tryon-save-done svg { stroke: currentColor; }
|
|
1296
1339
|
|