@primestyleai/tryon 5.8.47 → 5.8.48

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.
@@ -7759,6 +7759,37 @@ function FaceOverlay({
7759
7759
  ] }, key))
7760
7760
  ] });
7761
7761
  }
7762
+ function AccessoryStageCycler({
7763
+ category,
7764
+ sizingDone,
7765
+ t
7766
+ }) {
7767
+ const stages = category === "head" ? [
7768
+ { title: t("DETECTING HEAD"), desc: t("Reading head landmarks from your photo.") },
7769
+ { title: t("MAPPING CIRCUMFERENCE"), desc: t("Estimating head width and depth.") },
7770
+ { title: t("MATCHING HAT SIZE"), desc: t("Comparing your circumference to the size chart.") },
7771
+ { title: t("FINALIZING RESULT"), desc: t("Almost done — preparing your recommendation.") }
7772
+ ] : [
7773
+ { title: t("DETECTING FACE"), desc: t("Identifying 478 face landmarks in your photo.") },
7774
+ { title: t("CALIBRATING SCALE"), desc: t("Using iris size as the pixel-to-mm anchor.") },
7775
+ { title: t("MEASURING FRAME"), desc: t("Mapping bridge, lens width and temple length.") },
7776
+ { title: t("MATCHING FRAME SIZE"), desc: t("Comparing your measurements to the size chart.") },
7777
+ { title: t("FINALIZING RESULT"), desc: t("Almost done — preparing your recommendation.") }
7778
+ ];
7779
+ const [idx, setIdx] = useState(0);
7780
+ useEffect(() => {
7781
+ if (sizingDone) return;
7782
+ const id = setInterval(() => {
7783
+ setIdx((i) => Math.min(i + 1, stages.length - 1));
7784
+ }, 900);
7785
+ return () => clearInterval(id);
7786
+ }, [sizingDone, stages.length]);
7787
+ const current = stages[idx] ?? stages[0];
7788
+ return /* @__PURE__ */ jsx("div", { className: "ps-msc-stage", style: { alignSelf: "center", marginTop: "auto", marginBottom: "auto" }, children: /* @__PURE__ */ jsxs("div", { className: "ps-msc-stage-slot", children: [
7789
+ /* @__PURE__ */ jsx("div", { className: "ps-msc-stage-title", children: current.title }),
7790
+ /* @__PURE__ */ jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
7791
+ ] }, idx) });
7792
+ }
7762
7793
  function SkeletonOverlay({ landmarks, imgWidth, imgHeight }) {
7763
7794
  const W = imgWidth;
7764
7795
  const H = imgHeight;
@@ -8922,6 +8953,9 @@ function SizeResultView({
8922
8953
  const isFaceCategory = measurementType === "face" || measurementType === "head";
8923
8954
  const detectionDone = isFaceCategory ? !!faceLandmarks : !!bodyLandmarks;
8924
8955
  const detectLabel = isFaceCategory ? measurementType === "head" ? t("Detecting head") : t("Detecting face") : t("Detecting body pose");
8956
+ if (isFaceCategory) {
8957
+ return /* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-right-col", style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsx(AccessoryStageCycler, { category: measurementType, sizingDone, t }) });
8958
+ }
8925
8959
  return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-right-col ps-tryon-snap-steps", children: [
8926
8960
  /* @__PURE__ */ jsxs("div", { className: `ps-tryon-snap-step${detectionDone ? " ps-done" : " ps-active"}`, children: [
8927
8961
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-snap-step-icon", children: detectionDone ? /* @__PURE__ */ jsx("span", { className: "ps-tryon-snap-check", children: "✓" }) : /* @__PURE__ */ jsx("div", { className: "ps-tryon-size-loading-spinner", style: { width: "1vw", height: "1vw", borderWidth: "1.5px" } }) }),
@@ -13611,6 +13645,7 @@ function PrimeStyleTryonInner({
13611
13645
  category: measurementType,
13612
13646
  ...Object.keys(faceMm).length > 0 && { faceMeasurementsMm: faceMm, irisConfidence: 1 }
13613
13647
  };
13648
+ const minVisible = new Promise((r) => setTimeout(r, 3200));
13614
13649
  try {
13615
13650
  const resp = await fetch(`${baseUrl}/api/v1/sizing/face-recommend`, {
13616
13651
  method: "POST",
@@ -13619,17 +13654,20 @@ function PrimeStyleTryonInner({
13619
13654
  });
13620
13655
  if (resp.ok) {
13621
13656
  const data = await resp.json();
13657
+ await minVisible;
13622
13658
  setSizingResult(data);
13623
13659
  onComplete?.(data);
13624
13660
  } else {
13625
13661
  const body = await resp.text().catch(() => "");
13626
13662
  console.error("[PS-SDK] face-recommend failed:", resp.status, body);
13663
+ await minVisible;
13627
13664
  setErrorMessage(t("Unable to get size recommendation. Please try again."));
13628
13665
  setView("error");
13629
13666
  setEstimationDone(true);
13630
13667
  }
13631
13668
  } catch (err) {
13632
13669
  console.error("[PS-SDK] face-recommend network error:", err);
13670
+ await minVisible;
13633
13671
  setErrorMessage(t("Unable to connect to sizing service. Please try again."));
13634
13672
  setView("error");
13635
13673
  setEstimationDone(true);
@@ -13824,6 +13862,7 @@ function PrimeStyleTryonInner({
13824
13862
  const measurementType = detectMeasurementType(productTitle);
13825
13863
  if (measurementType === "face" || measurementType === "head") {
13826
13864
  setFaceLandmarks(null);
13865
+ const minVisible = new Promise((r) => setTimeout(r, 3200));
13827
13866
  try {
13828
13867
  const faceResult = await detectFaceMeasurements(objUrl);
13829
13868
  if (faceResult) setFaceLandmarks(faceResult.landmarks);
@@ -13846,6 +13885,7 @@ function PrimeStyleTryonInner({
13846
13885
  });
13847
13886
  if (recRes.ok) {
13848
13887
  const recData = await recRes.json();
13888
+ await minVisible;
13849
13889
  setSizingResult(recData);
13850
13890
  onComplete?.(recData);
13851
13891
  persistResultToProfile(
@@ -13861,10 +13901,12 @@ function PrimeStyleTryonInner({
13861
13901
  recData
13862
13902
  );
13863
13903
  } else {
13904
+ await minVisible;
13864
13905
  setEstimationDone(true);
13865
13906
  }
13866
13907
  } catch (err) {
13867
13908
  console.error("[ps-sdk] face-recommend failed:", err);
13909
+ await minVisible;
13868
13910
  setEstimationDone(true);
13869
13911
  }
13870
13912
  setSizingLoading(false);
@@ -17183,6 +17183,37 @@ function FaceOverlay({
17183
17183
  ] }, key))
17184
17184
  ] });
17185
17185
  }
17186
+ function AccessoryStageCycler({
17187
+ category,
17188
+ sizingDone,
17189
+ t: t2
17190
+ }) {
17191
+ const stages = category === "head" ? [
17192
+ { title: t2("DETECTING HEAD"), desc: t2("Reading head landmarks from your photo.") },
17193
+ { title: t2("MAPPING CIRCUMFERENCE"), desc: t2("Estimating head width and depth.") },
17194
+ { title: t2("MATCHING HAT SIZE"), desc: t2("Comparing your circumference to the size chart.") },
17195
+ { title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation.") }
17196
+ ] : [
17197
+ { title: t2("DETECTING FACE"), desc: t2("Identifying 478 face landmarks in your photo.") },
17198
+ { title: t2("CALIBRATING SCALE"), desc: t2("Using iris size as the pixel-to-mm anchor.") },
17199
+ { title: t2("MEASURING FRAME"), desc: t2("Mapping bridge, lens width and temple length.") },
17200
+ { title: t2("MATCHING FRAME SIZE"), desc: t2("Comparing your measurements to the size chart.") },
17201
+ { title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation.") }
17202
+ ];
17203
+ const [idx, setIdx] = reactExports.useState(0);
17204
+ reactExports.useEffect(() => {
17205
+ if (sizingDone) return;
17206
+ const id2 = setInterval(() => {
17207
+ setIdx((i) => Math.min(i + 1, stages.length - 1));
17208
+ }, 900);
17209
+ return () => clearInterval(id2);
17210
+ }, [sizingDone, stages.length]);
17211
+ const current = stages[idx] ?? stages[0];
17212
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage", style: { alignSelf: "center", marginTop: "auto", marginBottom: "auto" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msc-stage-slot", children: [
17213
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-title", children: current.title }),
17214
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msc-stage-desc", children: current.desc })
17215
+ ] }, idx) });
17216
+ }
17186
17217
  function SkeletonOverlay({ landmarks, imgWidth, imgHeight }) {
17187
17218
  const W2 = imgWidth;
17188
17219
  const H2 = imgHeight;
@@ -18346,6 +18377,9 @@ function SizeResultView({
18346
18377
  const isFaceCategory = measurementType === "face" || measurementType === "head";
18347
18378
  const detectionDone = isFaceCategory ? !!faceLandmarks : !!bodyLandmarks;
18348
18379
  const detectLabel = isFaceCategory ? measurementType === "head" ? t2("Detecting head") : t2("Detecting face") : t2("Detecting body pose");
18380
+ if (isFaceCategory) {
18381
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-right-col", style: { display: "flex", alignItems: "center", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(AccessoryStageCycler, { category: measurementType, sizingDone, t: t2 }) });
18382
+ }
18349
18383
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-right-col ps-tryon-snap-steps", children: [
18350
18384
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-tryon-snap-step${detectionDone ? " ps-done" : " ps-active"}`, children: [
18351
18385
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-snap-step-icon", children: detectionDone ? /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-snap-check", children: "✓" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-size-loading-spinner", style: { width: "1vw", height: "1vw", borderWidth: "1.5px" } }) }),
@@ -23035,6 +23069,7 @@ function PrimeStyleTryonInner({
23035
23069
  category: measurementType,
23036
23070
  ...Object.keys(faceMm).length > 0 && { faceMeasurementsMm: faceMm, irisConfidence: 1 }
23037
23071
  };
23072
+ const minVisible = new Promise((r2) => setTimeout(r2, 3200));
23038
23073
  try {
23039
23074
  const resp = await fetch(`${baseUrl}/api/v1/sizing/face-recommend`, {
23040
23075
  method: "POST",
@@ -23043,17 +23078,20 @@ function PrimeStyleTryonInner({
23043
23078
  });
23044
23079
  if (resp.ok) {
23045
23080
  const data = await resp.json();
23081
+ await minVisible;
23046
23082
  setSizingResult(data);
23047
23083
  onComplete?.(data);
23048
23084
  } else {
23049
23085
  const body = await resp.text().catch(() => "");
23050
23086
  console.error("[PS-SDK] face-recommend failed:", resp.status, body);
23087
+ await minVisible;
23051
23088
  setErrorMessage(t2("Unable to get size recommendation. Please try again."));
23052
23089
  setView("error");
23053
23090
  setEstimationDone(true);
23054
23091
  }
23055
23092
  } catch (err) {
23056
23093
  console.error("[PS-SDK] face-recommend network error:", err);
23094
+ await minVisible;
23057
23095
  setErrorMessage(t2("Unable to connect to sizing service. Please try again."));
23058
23096
  setView("error");
23059
23097
  setEstimationDone(true);
@@ -23248,6 +23286,7 @@ function PrimeStyleTryonInner({
23248
23286
  const measurementType = detectMeasurementType(productTitle);
23249
23287
  if (measurementType === "face" || measurementType === "head") {
23250
23288
  setFaceLandmarks(null);
23289
+ const minVisible = new Promise((r2) => setTimeout(r2, 3200));
23251
23290
  try {
23252
23291
  const faceResult = await detectFaceMeasurements(objUrl);
23253
23292
  if (faceResult) setFaceLandmarks(faceResult.landmarks);
@@ -23270,6 +23309,7 @@ function PrimeStyleTryonInner({
23270
23309
  });
23271
23310
  if (recRes.ok) {
23272
23311
  const recData = await recRes.json();
23312
+ await minVisible;
23273
23313
  setSizingResult(recData);
23274
23314
  onComplete?.(recData);
23275
23315
  persistResultToProfile(
@@ -23285,10 +23325,12 @@ function PrimeStyleTryonInner({
23285
23325
  recData
23286
23326
  );
23287
23327
  } else {
23328
+ await minVisible;
23288
23329
  setEstimationDone(true);
23289
23330
  }
23290
23331
  } catch (err) {
23291
23332
  console.error("[ps-sdk] face-recommend failed:", err);
23333
+ await minVisible;
23292
23334
  setEstimationDone(true);
23293
23335
  }
23294
23336
  setSizingLoading(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "5.8.47",
3
+ "version": "5.8.48",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",