@primestyleai/tryon 2.0.3 → 2.0.5
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 +49 -4
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -7,6 +7,7 @@ function cx(base, override) {
|
|
|
7
7
|
}
|
|
8
8
|
const LS_PREFIX = "primestyle_";
|
|
9
9
|
function lsGet(key, fallback) {
|
|
10
|
+
if (typeof window === "undefined") return fallback;
|
|
10
11
|
try {
|
|
11
12
|
const raw = localStorage.getItem(LS_PREFIX + key);
|
|
12
13
|
return raw ? JSON.parse(raw) : fallback;
|
|
@@ -37,6 +38,7 @@ const SIZING_COUNTRIES = [
|
|
|
37
38
|
const STEP_LABELS = ["", "Welcome", "Photo", "Size", "Generate", "Results"];
|
|
38
39
|
const TOTAL_STEPS = 5;
|
|
39
40
|
function detectLocale() {
|
|
41
|
+
if (typeof window === "undefined") return "US";
|
|
40
42
|
const l = (navigator.language || "en-US").toLowerCase();
|
|
41
43
|
if (l.includes("en-gb") || l.includes("en-au")) return "UK";
|
|
42
44
|
if (l.includes("en")) return "US";
|
|
@@ -182,6 +184,8 @@ function PrimeStyleTryon({
|
|
|
182
184
|
const [sizingMethod, setSizingMethod] = useState(null);
|
|
183
185
|
const [sizingResult, setSizingResult] = useState(null);
|
|
184
186
|
const [sizeGuide, setSizeGuide] = useState(null);
|
|
187
|
+
const [sizeGuideFetching, setSizeGuideFetching] = useState(false);
|
|
188
|
+
const sizeGuideFetchedRef = useRef(false);
|
|
185
189
|
const [sizingCountry, setSizingCountry] = useState(detectLocale);
|
|
186
190
|
const imperial = isImperial(sizingCountry);
|
|
187
191
|
const [sizingUnit, setSizingUnit] = useState(imperial ? "in" : "cm");
|
|
@@ -202,6 +206,17 @@ function PrimeStyleTryon({
|
|
|
202
206
|
const pollingRef = useRef(null);
|
|
203
207
|
const completedRef = useRef(false);
|
|
204
208
|
const bodyRef = useRef(null);
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
const id = "ps-tryon-styles";
|
|
211
|
+
if (document.getElementById(id)) return;
|
|
212
|
+
const el = document.createElement("style");
|
|
213
|
+
el.id = id;
|
|
214
|
+
el.textContent = STYLES;
|
|
215
|
+
document.head.appendChild(el);
|
|
216
|
+
return () => {
|
|
217
|
+
el.remove();
|
|
218
|
+
};
|
|
219
|
+
}, []);
|
|
205
220
|
useEffect(() => {
|
|
206
221
|
try {
|
|
207
222
|
const key = getApiKey();
|
|
@@ -257,6 +272,21 @@ function PrimeStyleTryon({
|
|
|
257
272
|
useEffect(() => {
|
|
258
273
|
lsSet("history", history);
|
|
259
274
|
}, [history]);
|
|
275
|
+
useEffect(() => {
|
|
276
|
+
if (view !== "sizing-choice" || sizeGuideFetchedRef.current || !apiRef.current) return;
|
|
277
|
+
sizeGuideFetchedRef.current = true;
|
|
278
|
+
setSizeGuideFetching(true);
|
|
279
|
+
const baseUrl = getApiUrl(apiUrl);
|
|
280
|
+
const key = getApiKey();
|
|
281
|
+
fetch(`${baseUrl}/api/v1/sizing/sizeguide`, {
|
|
282
|
+
method: "POST",
|
|
283
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
284
|
+
body: JSON.stringify({ product: { title: productTitle, variants: [] } })
|
|
285
|
+
}).then((r) => r.ok ? r.json() : null).then((data) => {
|
|
286
|
+
if (data) setSizeGuide(data);
|
|
287
|
+
else setSizeGuide({ found: false });
|
|
288
|
+
}).catch(() => setSizeGuide({ found: false })).finally(() => setSizeGuideFetching(false));
|
|
289
|
+
}, [view, apiUrl, productTitle]);
|
|
260
290
|
const stepIndex = useMemo(() => {
|
|
261
291
|
switch (view) {
|
|
262
292
|
case "welcome":
|
|
@@ -293,6 +323,8 @@ function PrimeStyleTryon({
|
|
|
293
323
|
setProfileSaved(false);
|
|
294
324
|
formRef.current = {};
|
|
295
325
|
setFormGender("male");
|
|
326
|
+
sizeGuideFetchedRef.current = false;
|
|
327
|
+
setSizeGuideFetching(false);
|
|
296
328
|
unsubRef.current?.();
|
|
297
329
|
unsubRef.current = null;
|
|
298
330
|
if (pollingRef.current) {
|
|
@@ -719,10 +751,15 @@ function PrimeStyleTryon({
|
|
|
719
751
|
] });
|
|
720
752
|
}
|
|
721
753
|
function SizingChoiceView() {
|
|
754
|
+
const sgAvailable = sizeGuide?.found === true;
|
|
755
|
+
const sgDisabled = !sizeGuideFetching && !sgAvailable;
|
|
756
|
+
const disabledClass = sgDisabled ? " ps-tryon-choice-disabled" : sizeGuideFetching ? " ps-tryon-choice-loading" : "";
|
|
722
757
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-choice", children: [
|
|
723
758
|
/* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "How would you like to find your size?" }),
|
|
759
|
+
sgDisabled && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice", children: "Size guide is not available for this product" }),
|
|
760
|
+
sizeGuideFetching && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-notice ps-tryon-sg-loading", children: "Checking size guide availability..." }),
|
|
724
761
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-cards", children: [
|
|
725
|
-
/* @__PURE__ */ jsxs("button", { className:
|
|
762
|
+
/* @__PURE__ */ jsxs("button", { className: `ps-tryon-choice-card${disabledClass}`, disabled: sgDisabled || sizeGuideFetching, onClick: () => {
|
|
726
763
|
setSizingMethod("exact");
|
|
727
764
|
setView("sizing-form");
|
|
728
765
|
}, children: [
|
|
@@ -733,7 +770,7 @@ function PrimeStyleTryon({
|
|
|
733
770
|
] }),
|
|
734
771
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: "Best accuracy" })
|
|
735
772
|
] }),
|
|
736
|
-
/* @__PURE__ */ jsxs("button", { className:
|
|
773
|
+
/* @__PURE__ */ jsxs("button", { className: `ps-tryon-choice-card${disabledClass}`, disabled: sgDisabled || sizeGuideFetching, onClick: () => {
|
|
737
774
|
setSizingMethod("quick");
|
|
738
775
|
setView("sizing-form");
|
|
739
776
|
}, children: [
|
|
@@ -1051,8 +1088,7 @@ function PrimeStyleTryon({
|
|
|
1051
1088
|
/* @__PURE__ */ jsx("a", { href: "https://myaifitting.com", target: "_blank", rel: "noopener noreferrer", children: "PrimeStyle AI" })
|
|
1052
1089
|
] })
|
|
1053
1090
|
] }) }),
|
|
1054
|
-
/* @__PURE__ */ jsx(ProfileDetailModal, {})
|
|
1055
|
-
/* @__PURE__ */ jsx("style", { children: STYLES })
|
|
1091
|
+
/* @__PURE__ */ jsx(ProfileDetailModal, {})
|
|
1056
1092
|
] });
|
|
1057
1093
|
}
|
|
1058
1094
|
const STYLES = `
|
|
@@ -1228,6 +1264,15 @@ const STYLES = `
|
|
|
1228
1264
|
padding: 3px 10px; border-radius: 20px; flex-shrink: 0;
|
|
1229
1265
|
background: rgba(187,148,92,0.12); color: #bb945c; font-size: 10px; font-weight: 600;
|
|
1230
1266
|
}
|
|
1267
|
+
.ps-tryon-choice-disabled { opacity: 0.4; cursor: not-allowed !important; pointer-events: none; }
|
|
1268
|
+
.ps-tryon-choice-disabled:hover { border-color: #333; transform: none; box-shadow: none; }
|
|
1269
|
+
.ps-tryon-choice-disabled::before { display: none; }
|
|
1270
|
+
.ps-tryon-choice-loading { opacity: 0.5; cursor: wait !important; pointer-events: none; }
|
|
1271
|
+
.ps-tryon-sg-notice {
|
|
1272
|
+
font-size: 12px; color: #999; text-align: center; padding: 10px 14px;
|
|
1273
|
+
margin-bottom: 12px; border: 1px solid #333; border-radius: 10px; background: #1a1b1a;
|
|
1274
|
+
}
|
|
1275
|
+
.ps-tryon-sg-loading { border-style: dashed; }
|
|
1231
1276
|
|
|
1232
1277
|
/* Sizing form */
|
|
1233
1278
|
.ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 12px; }
|