@primestyleai/tryon 2.0.2 → 2.0.4
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 +125 -81
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -182,12 +182,15 @@ function PrimeStyleTryon({
|
|
|
182
182
|
const [sizingMethod, setSizingMethod] = useState(null);
|
|
183
183
|
const [sizingResult, setSizingResult] = useState(null);
|
|
184
184
|
const [sizeGuide, setSizeGuide] = useState(null);
|
|
185
|
+
const [sizeGuideFetching, setSizeGuideFetching] = useState(false);
|
|
186
|
+
const sizeGuideFetchedRef = useRef(false);
|
|
185
187
|
const [sizingCountry, setSizingCountry] = useState(detectLocale);
|
|
186
188
|
const imperial = isImperial(sizingCountry);
|
|
187
189
|
const [sizingUnit, setSizingUnit] = useState(imperial ? "in" : "cm");
|
|
188
190
|
const [heightUnit, setHeightUnit] = useState(imperial ? "ft" : "cm");
|
|
189
191
|
const [weightUnit, setWeightUnit] = useState(imperial ? "lbs" : "kg");
|
|
190
|
-
const
|
|
192
|
+
const formRef = useRef({});
|
|
193
|
+
const [formGender, setFormGender] = useState("male");
|
|
191
194
|
const [profiles, setProfiles] = useState(() => lsGet("profiles", []));
|
|
192
195
|
const [history, setHistory] = useState(() => lsGet("history", []));
|
|
193
196
|
const [activeProfileId, setActiveProfileId] = useState(null);
|
|
@@ -256,6 +259,21 @@ function PrimeStyleTryon({
|
|
|
256
259
|
useEffect(() => {
|
|
257
260
|
lsSet("history", history);
|
|
258
261
|
}, [history]);
|
|
262
|
+
useEffect(() => {
|
|
263
|
+
if (view !== "sizing-choice" || sizeGuideFetchedRef.current || !apiRef.current) return;
|
|
264
|
+
sizeGuideFetchedRef.current = true;
|
|
265
|
+
setSizeGuideFetching(true);
|
|
266
|
+
const baseUrl = getApiUrl(apiUrl);
|
|
267
|
+
const key = getApiKey();
|
|
268
|
+
fetch(`${baseUrl}/api/v1/sizing/sizeguide`, {
|
|
269
|
+
method: "POST",
|
|
270
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
271
|
+
body: JSON.stringify({ product: { title: productTitle, variants: [] } })
|
|
272
|
+
}).then((r) => r.ok ? r.json() : null).then((data) => {
|
|
273
|
+
if (data) setSizeGuide(data);
|
|
274
|
+
else setSizeGuide({ found: false });
|
|
275
|
+
}).catch(() => setSizeGuide({ found: false })).finally(() => setSizeGuideFetching(false));
|
|
276
|
+
}, [view, apiUrl, productTitle]);
|
|
259
277
|
const stepIndex = useMemo(() => {
|
|
260
278
|
switch (view) {
|
|
261
279
|
case "welcome":
|
|
@@ -290,7 +308,10 @@ function PrimeStyleTryon({
|
|
|
290
308
|
setSizingResult(null);
|
|
291
309
|
setSizeGuide(null);
|
|
292
310
|
setProfileSaved(false);
|
|
293
|
-
|
|
311
|
+
formRef.current = {};
|
|
312
|
+
setFormGender("male");
|
|
313
|
+
sizeGuideFetchedRef.current = false;
|
|
314
|
+
setSizeGuideFetching(false);
|
|
294
315
|
unsubRef.current?.();
|
|
295
316
|
unsubRef.current = null;
|
|
296
317
|
if (pollingRef.current) {
|
|
@@ -364,23 +385,23 @@ function PrimeStyleTryon({
|
|
|
364
385
|
};
|
|
365
386
|
if (sizeGuide?.found) payload.sizeGuide = sizeGuide;
|
|
366
387
|
if (sizingMethod === "exact") {
|
|
367
|
-
const m = { gender:
|
|
368
|
-
if (
|
|
369
|
-
if (
|
|
388
|
+
const m = { gender: formRef.current.gender || "male" };
|
|
389
|
+
if (formRef.current.height) m.heightCm = heightUnit === "ft" ? ftInToCm(parseFloat(formRef.current.heightFeet || "0"), parseFloat(formRef.current.heightInches || "0")) : parseFloat(formRef.current.height);
|
|
390
|
+
if (formRef.current.weight) m.weightKg = weightUnit === "lbs" ? lbsToKg(parseFloat(formRef.current.weight)) : parseFloat(formRef.current.weight);
|
|
370
391
|
const keys = ["chest", "bust", "waist", "hips", "shoulderWidth", "sleeveLength", "inseam", "neckCircumference", "footLengthCm"];
|
|
371
392
|
for (const k of keys) {
|
|
372
|
-
if (
|
|
393
|
+
if (formRef.current[k]) m[k] = sizingUnit === "in" ? inToCm(parseFloat(formRef.current[k])) : parseFloat(formRef.current[k]);
|
|
373
394
|
}
|
|
374
|
-
if (
|
|
375
|
-
if (
|
|
376
|
-
if (
|
|
377
|
-
if (
|
|
395
|
+
if (formRef.current.shoeEU) m.shoeEU = formRef.current.shoeEU;
|
|
396
|
+
if (formRef.current.shoeUS) m.shoeUS = formRef.current.shoeUS;
|
|
397
|
+
if (formRef.current.shoeUK) m.shoeUK = formRef.current.shoeUK;
|
|
398
|
+
if (formRef.current.fitPreference) m.fitPreference = formRef.current.fitPreference;
|
|
378
399
|
payload.measurements = m;
|
|
379
400
|
} else {
|
|
380
401
|
payload.quickEstimate = {
|
|
381
|
-
heightCm: heightUnit === "ft" ? ftInToCm(parseFloat(
|
|
382
|
-
weightKg: weightUnit === "lbs" ? lbsToKg(parseFloat(
|
|
383
|
-
gender:
|
|
402
|
+
heightCm: heightUnit === "ft" ? ftInToCm(parseFloat(formRef.current.heightFeet || "0"), parseFloat(formRef.current.heightInches || "0")) : parseFloat(formRef.current.height || "0"),
|
|
403
|
+
weightKg: weightUnit === "lbs" ? lbsToKg(parseFloat(formRef.current.weight || "0")) : parseFloat(formRef.current.weight || "0"),
|
|
404
|
+
gender: formRef.current.gender || "male"
|
|
384
405
|
};
|
|
385
406
|
}
|
|
386
407
|
try {
|
|
@@ -395,7 +416,7 @@ function PrimeStyleTryon({
|
|
|
395
416
|
}
|
|
396
417
|
} catch {
|
|
397
418
|
}
|
|
398
|
-
}, [apiUrl, sizingMethod, sizingCountry,
|
|
419
|
+
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle]);
|
|
399
420
|
const handleSubmit = useCallback(async () => {
|
|
400
421
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
401
422
|
const msg = !apiRef.current ? "Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY" : "No file selected";
|
|
@@ -492,29 +513,30 @@ function PrimeStyleTryon({
|
|
|
492
513
|
if (p.shoeUS) fd.shoeUS = p.shoeUS;
|
|
493
514
|
if (p.shoeUK) fd.shoeUK = p.shoeUK;
|
|
494
515
|
if (p.fitPreference) fd.fitPreference = p.fitPreference;
|
|
495
|
-
|
|
516
|
+
formRef.current = fd;
|
|
517
|
+
setFormGender(fd.gender || "male");
|
|
496
518
|
}, [profiles]);
|
|
497
519
|
const saveProfile = useCallback((name) => {
|
|
498
520
|
const id = activeProfileId || `p_${Date.now()}`;
|
|
499
521
|
const p = {
|
|
500
522
|
id,
|
|
501
523
|
name,
|
|
502
|
-
gender:
|
|
503
|
-
heightCm:
|
|
504
|
-
weightKg:
|
|
505
|
-
chest:
|
|
506
|
-
bust:
|
|
507
|
-
waist:
|
|
508
|
-
hips:
|
|
509
|
-
shoulderWidth:
|
|
510
|
-
sleeveLength:
|
|
511
|
-
inseam:
|
|
512
|
-
neckCircumference:
|
|
513
|
-
footLengthCm:
|
|
514
|
-
shoeEU:
|
|
515
|
-
shoeUS:
|
|
516
|
-
shoeUK:
|
|
517
|
-
fitPreference:
|
|
524
|
+
gender: formRef.current.gender || "male",
|
|
525
|
+
heightCm: formRef.current.height ? parseFloat(formRef.current.height) : void 0,
|
|
526
|
+
weightKg: formRef.current.weight ? parseFloat(formRef.current.weight) : void 0,
|
|
527
|
+
chest: formRef.current.chest ? parseFloat(formRef.current.chest) : void 0,
|
|
528
|
+
bust: formRef.current.bust ? parseFloat(formRef.current.bust) : void 0,
|
|
529
|
+
waist: formRef.current.waist ? parseFloat(formRef.current.waist) : void 0,
|
|
530
|
+
hips: formRef.current.hips ? parseFloat(formRef.current.hips) : void 0,
|
|
531
|
+
shoulderWidth: formRef.current.shoulderWidth ? parseFloat(formRef.current.shoulderWidth) : void 0,
|
|
532
|
+
sleeveLength: formRef.current.sleeveLength ? parseFloat(formRef.current.sleeveLength) : void 0,
|
|
533
|
+
inseam: formRef.current.inseam ? parseFloat(formRef.current.inseam) : void 0,
|
|
534
|
+
neckCircumference: formRef.current.neckCircumference ? parseFloat(formRef.current.neckCircumference) : void 0,
|
|
535
|
+
footLengthCm: formRef.current.footLengthCm ? parseFloat(formRef.current.footLengthCm) : void 0,
|
|
536
|
+
shoeEU: formRef.current.shoeEU,
|
|
537
|
+
shoeUS: formRef.current.shoeUS,
|
|
538
|
+
shoeUK: formRef.current.shoeUK,
|
|
539
|
+
fitPreference: formRef.current.fitPreference,
|
|
518
540
|
createdAt: Date.now()
|
|
519
541
|
};
|
|
520
542
|
setProfiles((prev) => {
|
|
@@ -528,7 +550,7 @@ function PrimeStyleTryon({
|
|
|
528
550
|
});
|
|
529
551
|
setActiveProfileId(id);
|
|
530
552
|
setProfileSaved(true);
|
|
531
|
-
}, [activeProfileId
|
|
553
|
+
}, [activeProfileId]);
|
|
532
554
|
const saveHistoryEntry = useCallback(() => {
|
|
533
555
|
const entry = {
|
|
534
556
|
id: `h_${Date.now()}`,
|
|
@@ -554,7 +576,7 @@ function PrimeStyleTryon({
|
|
|
554
576
|
}
|
|
555
577
|
}, [view]);
|
|
556
578
|
const updateField = useCallback((key, val) => {
|
|
557
|
-
|
|
579
|
+
formRef.current[key] = val;
|
|
558
580
|
}, []);
|
|
559
581
|
const shoeField = useMemo(() => {
|
|
560
582
|
const map = {
|
|
@@ -619,8 +641,8 @@ function PrimeStyleTryon({
|
|
|
619
641
|
{
|
|
620
642
|
type,
|
|
621
643
|
placeholder,
|
|
622
|
-
|
|
623
|
-
|
|
644
|
+
defaultValue: formRef.current[fieldKey] || "",
|
|
645
|
+
onInput: (e) => updateField(fieldKey, e.target.value)
|
|
624
646
|
}
|
|
625
647
|
),
|
|
626
648
|
unit && /* @__PURE__ */ jsx("span", { className: "ps-tryon-input-unit", children: unit })
|
|
@@ -716,10 +738,15 @@ function PrimeStyleTryon({
|
|
|
716
738
|
] });
|
|
717
739
|
}
|
|
718
740
|
function SizingChoiceView() {
|
|
741
|
+
const sgAvailable = sizeGuide?.found === true;
|
|
742
|
+
const sgDisabled = !sizeGuideFetching && !sgAvailable;
|
|
743
|
+
const disabledClass = sgDisabled ? " ps-tryon-choice-disabled" : sizeGuideFetching ? " ps-tryon-choice-loading" : "";
|
|
719
744
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-choice", children: [
|
|
720
745
|
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "How would you like to find your size?" }),
|
|
746
|
+
sgDisabled && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice", children: "Size guide is not available for this product" }),
|
|
747
|
+
sizeGuideFetching && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice ps-tryon-sg-loading", children: "Checking size guide availability..." }),
|
|
721
748
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-cards", children: [
|
|
722
|
-
/* @__PURE__ */ jsxs("button", { className:
|
|
749
|
+
/* @__PURE__ */ jsxs("button", { className: `ps-tryon-choice-card${disabledClass}`, disabled: sgDisabled || sizeGuideFetching, onClick: () => {
|
|
723
750
|
setSizingMethod("exact");
|
|
724
751
|
setView("sizing-form");
|
|
725
752
|
}, children: [
|
|
@@ -730,7 +757,7 @@ function PrimeStyleTryon({
|
|
|
730
757
|
] }),
|
|
731
758
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: "Best accuracy" })
|
|
732
759
|
] }),
|
|
733
|
-
/* @__PURE__ */ jsxs("button", { className:
|
|
760
|
+
/* @__PURE__ */ jsxs("button", { className: `ps-tryon-choice-card${disabledClass}`, disabled: sgDisabled || sizeGuideFetching, onClick: () => {
|
|
734
761
|
setSizingMethod("quick");
|
|
735
762
|
setView("sizing-form");
|
|
736
763
|
}, children: [
|
|
@@ -754,58 +781,62 @@ function PrimeStyleTryon({
|
|
|
754
781
|
] });
|
|
755
782
|
}
|
|
756
783
|
function SizingFormView() {
|
|
757
|
-
const isFemale =
|
|
784
|
+
const isFemale = formGender === "female";
|
|
785
|
+
const isCm = sizingUnit === "cm";
|
|
758
786
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
|
|
759
787
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
760
|
-
/* @__PURE__ */ jsx("label", { children: "
|
|
761
|
-
/* @__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)) })
|
|
762
|
-
] }),
|
|
763
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
764
|
-
/* @__PURE__ */ jsx("label", { children: "Gender" }),
|
|
788
|
+
/* @__PURE__ */ jsx("label", { children: "I'm shopping for" }),
|
|
765
789
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-toggle", children: [
|
|
766
|
-
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${
|
|
767
|
-
|
|
790
|
+
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${!isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
791
|
+
updateField("gender", "male");
|
|
792
|
+
setFormGender("male");
|
|
793
|
+
}, children: "Men's" }),
|
|
794
|
+
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${isFemale ? " ps-active" : ""}`, onClick: () => {
|
|
795
|
+
updateField("gender", "female");
|
|
796
|
+
setFormGender("female");
|
|
797
|
+
}, children: "Women's" })
|
|
768
798
|
] })
|
|
769
799
|
] }),
|
|
800
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
801
|
+
/* @__PURE__ */ jsx("label", { children: "Sizing region" }),
|
|
802
|
+
/* @__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)) })
|
|
803
|
+
] }),
|
|
804
|
+
sizingMethod === "exact" && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: setSizingUnit }) }),
|
|
770
805
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
771
806
|
/* @__PURE__ */ jsx("label", { children: "Height" }),
|
|
772
807
|
heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-height-ft", children: [
|
|
773
|
-
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "5",
|
|
808
|
+
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", defaultValue: formRef.current.heightFeet || "", onInput: (e) => updateField("heightFeet", e.target.value) }),
|
|
774
809
|
/* @__PURE__ */ jsx("span", { children: "ft" }),
|
|
775
|
-
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "4",
|
|
810
|
+
/* @__PURE__ */ jsx("input", { type: "number", placeholder: "4", defaultValue: formRef.current.heightInches || "", onInput: (e) => updateField("heightInches", e.target.value) }),
|
|
776
811
|
/* @__PURE__ */ jsx("span", { children: "in" })
|
|
777
|
-
] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175",
|
|
812
|
+
] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175", defaultValue: formRef.current.height || "", onInput: (e) => updateField("height", e.target.value) }),
|
|
778
813
|
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "ft", value: "ft" }], value: heightUnit, onChange: setHeightUnit })
|
|
779
814
|
] }),
|
|
780
|
-
/* @__PURE__ */ jsxs(
|
|
781
|
-
/* @__PURE__ */ jsx("label", { children: "Weight" }),
|
|
782
|
-
/* @__PURE__ */ jsx("input", { type: "number", placeholder: weightUnit === "lbs" ? "e.g. 170" : "e.g. 75", value: formData.weight || "", onChange: (e) => updateField("weight", e.target.value) }),
|
|
783
|
-
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "kg", value: "kg" }, { label: "lbs", value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
|
|
784
|
-
] }),
|
|
785
|
-
sizingMethod === "exact" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
786
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
787
|
-
/* @__PURE__ */ jsx("label", { children: "Measurements" }),
|
|
788
|
-
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: setSizingUnit })
|
|
789
|
-
] }),
|
|
815
|
+
sizingMethod === "exact" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
790
816
|
isFemale ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
791
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Bust", fieldKey: "bust", placeholder: "e.g.
|
|
792
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g. 70", type: "number", unit: sizingUnit }),
|
|
793
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Hips", fieldKey: "hips", placeholder: "e.g.
|
|
817
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Bust *", fieldKey: "bust", placeholder: isCm ? "e.g. 88" : "e.g. 35", type: "number", unit: sizingUnit }),
|
|
818
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Waist *", fieldKey: "waist", placeholder: isCm ? "e.g. 70" : "e.g. 28", type: "number", unit: sizingUnit }),
|
|
819
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Hips *", fieldKey: "hips", placeholder: isCm ? "e.g. 96" : "e.g. 38", type: "number", unit: sizingUnit }),
|
|
820
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Shoulders", fieldKey: "shoulderWidth", placeholder: isCm ? "e.g. 39" : "e.g. 15", type: "number", unit: sizingUnit }),
|
|
821
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: isCm ? "e.g. 76" : "e.g. 30", type: "number", unit: sizingUnit })
|
|
794
822
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
795
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Chest", fieldKey: "chest", placeholder: "e.g.
|
|
796
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g.
|
|
797
|
-
/* @__PURE__ */ jsx(InputRow, { label: "
|
|
823
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Chest *", fieldKey: "chest", placeholder: isCm ? "e.g. 104" : "e.g. 41", type: "number", unit: sizingUnit }),
|
|
824
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Waist *", fieldKey: "waist", placeholder: isCm ? "e.g. 84" : "e.g. 33", type: "number", unit: sizingUnit }),
|
|
825
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Shoulders", fieldKey: "shoulderWidth", placeholder: isCm ? "e.g. 46" : "e.g. 18", type: "number", unit: sizingUnit }),
|
|
826
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Sleeve", fieldKey: "sleeveLength", placeholder: isCm ? "e.g. 64" : "e.g. 25", type: "number", unit: sizingUnit }),
|
|
827
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: isCm ? "e.g. 81" : "e.g. 32", type: "number", unit: sizingUnit })
|
|
798
828
|
] }),
|
|
799
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Shoulder Width", fieldKey: "shoulderWidth", placeholder: "e.g. 45", type: "number", unit: sizingUnit }),
|
|
800
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Sleeve Length", fieldKey: "sleeveLength", placeholder: "e.g. 65", type: "number", unit: sizingUnit }),
|
|
801
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: "e.g. 80", type: "number", unit: sizingUnit }),
|
|
802
829
|
isFemale && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
803
|
-
/* @__PURE__ */ jsx("label", { children: "Fit
|
|
830
|
+
/* @__PURE__ */ jsx("label", { children: "Fit type" }),
|
|
804
831
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: ["petite", "standard", "tall", "plus"].map((fp) => /* @__PURE__ */ jsx(
|
|
805
832
|
"button",
|
|
806
833
|
{
|
|
807
|
-
className: `ps-tryon-unit-btn${(
|
|
808
|
-
onClick: () =>
|
|
834
|
+
className: `ps-tryon-unit-btn${(formRef.current.fitPreference || "standard") === fp ? " ps-active" : ""}`,
|
|
835
|
+
onClick: (e) => {
|
|
836
|
+
updateField("fitPreference", fp);
|
|
837
|
+
const btns = e.target.parentElement.querySelectorAll(".ps-tryon-unit-btn");
|
|
838
|
+
btns.forEach((b) => b.classList.toggle("ps-active", b.textContent?.toLowerCase() === fp));
|
|
839
|
+
},
|
|
809
840
|
children: fp.charAt(0).toUpperCase() + fp.slice(1)
|
|
810
841
|
},
|
|
811
842
|
fp
|
|
@@ -813,16 +844,20 @@ function PrimeStyleTryon({
|
|
|
813
844
|
] }),
|
|
814
845
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-shoe-section", children: [
|
|
815
846
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-shoe-title", children: "Shoe sizing (optional)" }),
|
|
816
|
-
/* @__PURE__ */ jsx(InputRow, { label: "Foot length", fieldKey: "footLengthCm", placeholder:
|
|
847
|
+
/* @__PURE__ */ jsx(InputRow, { label: "Foot length", fieldKey: "footLengthCm", placeholder: isCm ? "e.g. 27" : "e.g. 10.5", type: "number", unit: sizingUnit }),
|
|
817
848
|
/* @__PURE__ */ jsx(InputRow, { label: shoeField.label, fieldKey: shoeField.key, placeholder: shoeField.ph })
|
|
818
849
|
] })
|
|
819
|
-
] }),
|
|
850
|
+
] }) : /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
851
|
+
/* @__PURE__ */ jsx("label", { children: "Weight" }),
|
|
852
|
+
/* @__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) }),
|
|
853
|
+
/* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "kg", value: "kg" }, { label: "lbs", value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
|
|
854
|
+
] }) }),
|
|
820
855
|
/* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
|
|
821
856
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: handleSubmit, children: [
|
|
822
857
|
"Get My Size & Try On ",
|
|
823
858
|
/* @__PURE__ */ jsx(ArrowRightIcon, {})
|
|
824
859
|
] })
|
|
825
|
-
] });
|
|
860
|
+
] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}`);
|
|
826
861
|
}
|
|
827
862
|
function ProcessingView() {
|
|
828
863
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
|
|
@@ -996,19 +1031,19 @@ function PrimeStyleTryon({
|
|
|
996
1031
|
function renderBody() {
|
|
997
1032
|
switch (view) {
|
|
998
1033
|
case "welcome":
|
|
999
|
-
return /* @__PURE__ */ jsx(WelcomeView, {});
|
|
1034
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(WelcomeView, {}) }, "v-welcome");
|
|
1000
1035
|
case "upload":
|
|
1001
|
-
return /* @__PURE__ */ jsx(UploadView, {});
|
|
1036
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(UploadView, {}) }, "v-upload");
|
|
1002
1037
|
case "sizing-choice":
|
|
1003
|
-
return /* @__PURE__ */ jsx(SizingChoiceView, {});
|
|
1038
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingChoiceView, {}) }, "v-choice");
|
|
1004
1039
|
case "sizing-form":
|
|
1005
|
-
return /* @__PURE__ */ jsx(SizingFormView, {});
|
|
1040
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(SizingFormView, {}) }, "v-form");
|
|
1006
1041
|
case "processing":
|
|
1007
|
-
return /* @__PURE__ */ jsx(ProcessingView, {});
|
|
1042
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ProcessingView, {}) }, "v-proc");
|
|
1008
1043
|
case "result":
|
|
1009
|
-
return /* @__PURE__ */ jsx(ResultView, {});
|
|
1044
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ResultView, {}) }, "v-result");
|
|
1010
1045
|
case "error":
|
|
1011
|
-
return /* @__PURE__ */ jsx(ErrorView, {});
|
|
1046
|
+
return /* @__PURE__ */ jsx("div", { className: "ps-tryon-view-enter", children: /* @__PURE__ */ jsx(ErrorView, {}) }, "v-error");
|
|
1012
1047
|
default:
|
|
1013
1048
|
return null;
|
|
1014
1049
|
}
|
|
@@ -1125,8 +1160,8 @@ const STYLES = `
|
|
|
1125
1160
|
|
|
1126
1161
|
/* Body */
|
|
1127
1162
|
.ps-tryon-body { padding: 24px; min-height: 300px; }
|
|
1128
|
-
.ps-tryon-body > * { animation: ps-fade-up 0.35s ease both; }
|
|
1129
1163
|
@keyframes ps-fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
|
|
1164
|
+
.ps-tryon-view-enter { animation: ps-fade-up 0.35s ease both; }
|
|
1130
1165
|
|
|
1131
1166
|
/* Welcome */
|
|
1132
1167
|
.ps-tryon-welcome { text-align: center; }
|
|
@@ -1217,6 +1252,15 @@ const STYLES = `
|
|
|
1217
1252
|
padding: 3px 10px; border-radius: 20px; flex-shrink: 0;
|
|
1218
1253
|
background: rgba(187,148,92,0.12); color: #bb945c; font-size: 10px; font-weight: 600;
|
|
1219
1254
|
}
|
|
1255
|
+
.ps-tryon-choice-disabled { opacity: 0.4; cursor: not-allowed !important; pointer-events: none; }
|
|
1256
|
+
.ps-tryon-choice-disabled:hover { border-color: #333; transform: none; box-shadow: none; }
|
|
1257
|
+
.ps-tryon-choice-disabled::before { display: none; }
|
|
1258
|
+
.ps-tryon-choice-loading { opacity: 0.5; cursor: wait !important; pointer-events: none; }
|
|
1259
|
+
.ps-tryon-sg-notice {
|
|
1260
|
+
font-size: 12px; color: #999; text-align: center; padding: 10px 14px;
|
|
1261
|
+
margin-bottom: 12px; border: 1px solid #333; border-radius: 10px; background: #1a1b1a;
|
|
1262
|
+
}
|
|
1263
|
+
.ps-tryon-sg-loading { border-style: dashed; }
|
|
1220
1264
|
|
|
1221
1265
|
/* Sizing form */
|
|
1222
1266
|
.ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 12px; }
|