@primestyleai/tryon 5.8.54 → 5.8.55

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.
@@ -67,7 +67,15 @@ export interface BodyLandmarks {
67
67
  y: number;
68
68
  };
69
69
  }
70
+ /** Pixel dimensions of the image the landmarks were detected on. Sent to
71
+ * the backend alongside the landmarks so it can convert normalized x/y
72
+ * into pixels — without this, horizontal and vertical distances on a
73
+ * non-square image are skewed by the aspect ratio. */
74
+ export interface BodyLandmarksWithDims extends BodyLandmarks {
75
+ imageWidth: number;
76
+ imageHeight: number;
77
+ }
70
78
  export declare function detectMeasurementLines(imageSrc: string): Promise<MeasurementLines | null>;
71
79
  /** Detect full body landmarks for per-field measurement guides.
72
80
  * Accepts a URL string OR an already-loaded HTMLImageElement to avoid CORS issues. */
73
- export declare function detectBodyLandmarks(imageSrc: string | HTMLImageElement): Promise<BodyLandmarks | null>;
81
+ export declare function detectBodyLandmarks(imageSrc: string | HTMLImageElement): Promise<BodyLandmarksWithDims | null>;
@@ -121,7 +121,9 @@ async function detectBodyLandmarks(imageSrc) {
121
121
  rightKnee: { x: lm[RIGHT_KNEE].x, y: lm[RIGHT_KNEE].y },
122
122
  leftAnkle: { x: lm[LEFT_ANKLE].x, y: lm[LEFT_ANKLE].y },
123
123
  rightAnkle: { x: lm[RIGHT_ANKLE].x, y: lm[RIGHT_ANKLE].y },
124
- nose: { x: lm[NOSE].x, y: lm[NOSE].y }
124
+ nose: { x: lm[NOSE].x, y: lm[NOSE].y },
125
+ imageWidth: img.naturalWidth || img.width,
126
+ imageHeight: img.naturalHeight || img.height
125
127
  };
126
128
  } catch (err) {
127
129
  console.error("[PS-SDK] Body landmark detection failed:", err);
@@ -8046,7 +8048,8 @@ function SectionDetailView({
8046
8048
  tryOnProcessing,
8047
8049
  backLabel,
8048
8050
  internationalSizes,
8049
- continueLabel
8051
+ continueLabel,
8052
+ renderRaw = false
8050
8053
  }) {
8051
8054
  const recSize = sectionResult?.recommendedSize || "";
8052
8055
  const [selectedSize, setSelectedSize] = useState(null);
@@ -8164,6 +8167,18 @@ function SectionDetailView({
8164
8167
  return { range: val, ...parsed };
8165
8168
  }, [section, sizeColIdx, sizeHeader, unitLbl, columnUnits]);
8166
8169
  const fitRows = useMemo(() => {
8170
+ if (renderRaw) {
8171
+ const raw = sectionResult?.matchDetails || [];
8172
+ return raw.map((m) => ({
8173
+ area: m.measurement.replace(/\s*\(.*?\)\s*$/, "").trim() || m.measurement,
8174
+ rawUserValue: m.userValue,
8175
+ rawChartRange: m.chartRange,
8176
+ fit: m.fit,
8177
+ userNum: 0,
8178
+ chartLabel: "",
8179
+ isLength: false
8180
+ }));
8181
+ }
8167
8182
  const mainDetails = sectionResult?.matchDetails || [];
8168
8183
  const lengthDetails = lengthEntry?.secResult?.matchDetails || [];
8169
8184
  const details = [...mainDetails, ...lengthDetails];
@@ -8233,11 +8248,12 @@ function SectionDetailView({
8233
8248
  }
8234
8249
  return { area: m.measurement, userNum, chartLabel: cleanNumFn(chartLabel), fit, isLength: false };
8235
8250
  });
8236
- }, [sectionResult, lengthEntry, userMeasurements, displaySize, recSize, chartRangeFor, selectedLength, recLength]);
8251
+ }, [sectionResult, lengthEntry, userMeasurements, displaySize, recSize, chartRangeFor, selectedLength, recLength, renderRaw]);
8237
8252
  const goodCount = fitRows.filter(
8238
8253
  (r) => r.fit === "good" || r.fit === "a-bit-tight" || r.fit === "a-bit-loose"
8239
8254
  ).length;
8240
8255
  const matchPercent = fitRows.length > 0 ? Math.round(goodCount / fitRows.length * 100) : 0;
8256
+ const showMatchPercent = !renderRaw;
8241
8257
  const secAny = sectionResult;
8242
8258
  const backendSize = secAny?.size || recSize;
8243
8259
  const backendLength = secAny?.length || recLength;
@@ -8404,7 +8420,7 @@ function SectionDetailView({
8404
8420
  /* @__PURE__ */ jsxs("div", { className: "ps-msd-row-cells", children: [
8405
8421
  /* @__PURE__ */ jsxs("div", { className: "ps-msd-row-cell", children: [
8406
8422
  /* @__PURE__ */ jsx("span", { className: "ps-msd-cell-label", children: t("USER") }),
8407
- /* @__PURE__ */ jsx("span", { className: "ps-msd-cell-value", children: isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` })
8423
+ /* @__PURE__ */ jsx("span", { className: "ps-msd-cell-value", children: renderRaw ? row.rawUserValue || "—" : isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` })
8408
8424
  ] }),
8409
8425
  /* @__PURE__ */ jsxs("div", { className: "ps-msd-row-cell ps-right", children: [
8410
8426
  /* @__PURE__ */ jsxs("span", { className: "ps-msd-cell-label", children: [
@@ -8412,7 +8428,7 @@ function SectionDetailView({
8412
8428
  " ",
8413
8429
  displaySize
8414
8430
  ] }),
8415
- /* @__PURE__ */ jsx("span", { className: "ps-msd-cell-value", children: dLabel(row.chartLabel) })
8431
+ /* @__PURE__ */ jsx("span", { className: "ps-msd-cell-value", children: renderRaw ? row.rawChartRange || "—" : dLabel(row.chartLabel) })
8416
8432
  ] })
8417
8433
  ] }),
8418
8434
  /* @__PURE__ */ jsxs("div", { className: `ps-msd-row-badge ${fitClass}`, children: [
@@ -8511,7 +8527,7 @@ function SectionDetailView({
8511
8527
  ] })
8512
8528
  ] })
8513
8529
  ] }),
8514
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.4vw", marginBottom: "1.2vw" }, children: [
8530
+ showMatchPercent && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.4vw", marginBottom: "1.2vw" }, children: [
8515
8531
  /* @__PURE__ */ jsxs("svg", { width: "1vw", height: "1vw", viewBox: "0 0 16 16", fill: "none", children: [
8516
8532
  /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "8", fill: "var(--ps-accent)" }),
8517
8533
  /* @__PURE__ */ jsx("path", { d: "M4.5 8L7 10.5L11.5 5.5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
@@ -8534,8 +8550,8 @@ function SectionDetailView({
8534
8550
  const fitBg = row.fit === "good" ? "rgba(33,84,239,0.08)" : row.fit.includes("tight") ? "rgba(220,38,38,0.08)" : "rgba(217,119,6,0.08)";
8535
8551
  return /* @__PURE__ */ jsxs("tr", { style: { borderBottom: i < fitRows.length - 1 ? "1px solid rgba(0,0,0,0.04)" : "none" }, children: [
8536
8552
  /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", fontWeight: 500, color: "var(--ps-text-primary)" }, children: row.area }),
8537
- /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` }),
8538
- /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: dLabel(row.chartLabel) }),
8553
+ /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: renderRaw ? row.rawUserValue || "—" : isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` }),
8554
+ /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: renderRaw ? row.rawChartRange || "—" : dLabel(row.chartLabel) }),
8539
8555
  /* @__PURE__ */ jsx("td", { style: { padding: "0.55vw 0.6vw", textAlign: "right" }, children: /* @__PURE__ */ jsx("span", { style: { fontSize: "0.6vw", fontWeight: 600, color: fitColor, background: fitBg, borderRadius: "1vw", padding: "0.15vw 0.5vw", whiteSpace: "nowrap" }, children: row.isLength ? lengthFitLabelFn(row.fit, t) : fitLabelFn(row.fit, t) }) })
8540
8556
  ] }, i);
8541
8557
  }) })
@@ -9264,6 +9280,7 @@ function SizeResultView({
9264
9280
  productImage: resultImageUrl || productImage,
9265
9281
  productTitle,
9266
9282
  isMobile: true,
9283
+ renderRaw: isAccessory,
9267
9284
  isTryOnImage: !!resultImageUrl,
9268
9285
  showLines,
9269
9286
  onToggleLines: () => setShowLines(!showLines),
@@ -9307,7 +9324,8 @@ function SizeResultView({
9307
9324
  onTryOn: resultImageUrl || isAccessory ? void 0 : handleSingleTryOn,
9308
9325
  continueLabel: resultImageUrl ? t("Continue Shopping") : void 0,
9309
9326
  tryOnProcessing,
9310
- t
9327
+ t,
9328
+ renderRaw: isAccessory
9311
9329
  }
9312
9330
  ) }, "panel-single")
9313
9331
  ] });
@@ -13039,6 +13057,7 @@ function FootSizeView(props) {
13039
13057
  {
13040
13058
  title: "Shoe Size",
13041
13059
  fields,
13060
+ disablePhotoUpload: true,
13042
13061
  ...rest
13043
13062
  }
13044
13063
  );
@@ -9583,7 +9583,9 @@ async function detectBodyLandmarks(imageSrc) {
9583
9583
  rightKnee: { x: lm[RIGHT_KNEE].x, y: lm[RIGHT_KNEE].y },
9584
9584
  leftAnkle: { x: lm[LEFT_ANKLE].x, y: lm[LEFT_ANKLE].y },
9585
9585
  rightAnkle: { x: lm[RIGHT_ANKLE].x, y: lm[RIGHT_ANKLE].y },
9586
- nose: { x: lm[NOSE].x, y: lm[NOSE].y }
9586
+ nose: { x: lm[NOSE].x, y: lm[NOSE].y },
9587
+ imageWidth: img.naturalWidth || img.width,
9588
+ imageHeight: img.naturalHeight || img.height
9587
9589
  };
9588
9590
  } catch (err) {
9589
9591
  console.error("[PS-SDK] Body landmark detection failed:", err);
@@ -17470,7 +17472,8 @@ function SectionDetailView({
17470
17472
  tryOnProcessing,
17471
17473
  backLabel,
17472
17474
  internationalSizes,
17473
- continueLabel
17475
+ continueLabel,
17476
+ renderRaw = false
17474
17477
  }) {
17475
17478
  const recSize = sectionResult?.recommendedSize || "";
17476
17479
  const [selectedSize, setSelectedSize] = reactExports.useState(null);
@@ -17588,6 +17591,18 @@ function SectionDetailView({
17588
17591
  return { range: val, ...parsed };
17589
17592
  }, [section, sizeColIdx, sizeHeader, unitLbl, columnUnits]);
17590
17593
  const fitRows = reactExports.useMemo(() => {
17594
+ if (renderRaw) {
17595
+ const raw = sectionResult?.matchDetails || [];
17596
+ return raw.map((m2) => ({
17597
+ area: m2.measurement.replace(/\s*\(.*?\)\s*$/, "").trim() || m2.measurement,
17598
+ rawUserValue: m2.userValue,
17599
+ rawChartRange: m2.chartRange,
17600
+ fit: m2.fit,
17601
+ userNum: 0,
17602
+ chartLabel: "",
17603
+ isLength: false
17604
+ }));
17605
+ }
17591
17606
  const mainDetails = sectionResult?.matchDetails || [];
17592
17607
  const lengthDetails = lengthEntry?.secResult?.matchDetails || [];
17593
17608
  const details = [...mainDetails, ...lengthDetails];
@@ -17657,11 +17672,12 @@ function SectionDetailView({
17657
17672
  }
17658
17673
  return { area: m2.measurement, userNum, chartLabel: cleanNumFn(chartLabel), fit, isLength: false };
17659
17674
  });
17660
- }, [sectionResult, lengthEntry, userMeasurements, displaySize, recSize, chartRangeFor, selectedLength, recLength]);
17675
+ }, [sectionResult, lengthEntry, userMeasurements, displaySize, recSize, chartRangeFor, selectedLength, recLength, renderRaw]);
17661
17676
  const goodCount = fitRows.filter(
17662
17677
  (r2) => r2.fit === "good" || r2.fit === "a-bit-tight" || r2.fit === "a-bit-loose"
17663
17678
  ).length;
17664
17679
  const matchPercent = fitRows.length > 0 ? Math.round(goodCount / fitRows.length * 100) : 0;
17680
+ const showMatchPercent = !renderRaw;
17665
17681
  const secAny = sectionResult;
17666
17682
  const backendSize = secAny?.size || recSize;
17667
17683
  const backendLength = secAny?.length || recLength;
@@ -17828,7 +17844,7 @@ function SectionDetailView({
17828
17844
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msd-row-cells", children: [
17829
17845
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msd-row-cell", children: [
17830
17846
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-cell-label", children: t2("USER") }),
17831
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-cell-value", children: isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` })
17847
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-cell-value", children: renderRaw ? row.rawUserValue || "—" : isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` })
17832
17848
  ] }),
17833
17849
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msd-row-cell ps-right", children: [
17834
17850
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-msd-cell-label", children: [
@@ -17836,7 +17852,7 @@ function SectionDetailView({
17836
17852
  " ",
17837
17853
  displaySize
17838
17854
  ] }),
17839
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-cell-value", children: dLabel(row.chartLabel) })
17855
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-msd-cell-value", children: renderRaw ? row.rawChartRange || "—" : dLabel(row.chartLabel) })
17840
17856
  ] })
17841
17857
  ] }),
17842
17858
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-msd-row-badge ${fitClass}`, children: [
@@ -17935,7 +17951,7 @@ function SectionDetailView({
17935
17951
  ] })
17936
17952
  ] })
17937
17953
  ] }),
17938
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.4vw", marginBottom: "1.2vw" }, children: [
17954
+ showMatchPercent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.4vw", marginBottom: "1.2vw" }, children: [
17939
17955
  /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "1vw", height: "1vw", viewBox: "0 0 16 16", fill: "none", children: [
17940
17956
  /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "8", cy: "8", r: "8", fill: "var(--ps-accent)" }),
17941
17957
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M4.5 8L7 10.5L11.5 5.5", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
@@ -17958,8 +17974,8 @@ function SectionDetailView({
17958
17974
  const fitBg = row.fit === "good" ? "rgba(33,84,239,0.08)" : row.fit.includes("tight") ? "rgba(220,38,38,0.08)" : "rgba(217,119,6,0.08)";
17959
17975
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("tr", { style: { borderBottom: i < fitRows.length - 1 ? "1px solid rgba(0,0,0,0.04)" : "none" }, children: [
17960
17976
  /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", fontWeight: 500, color: "var(--ps-text-primary)" }, children: row.area }),
17961
- /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` }),
17962
- /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: dLabel(row.chartLabel) }),
17977
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: renderRaw ? row.rawUserValue || "—" : isNaN(row.userNum) || row.userNum === 0 ? "—" : `${dNum(row.userNum)} ${unitLbl}` }),
17978
+ /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", fontSize: "0.75vw", color: "var(--ps-text-secondary)" }, children: renderRaw ? row.rawChartRange || "—" : dLabel(row.chartLabel) }),
17963
17979
  /* @__PURE__ */ jsxRuntimeExports.jsx("td", { style: { padding: "0.55vw 0.6vw", textAlign: "right" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: "0.6vw", fontWeight: 600, color: fitColor, background: fitBg, borderRadius: "1vw", padding: "0.15vw 0.5vw", whiteSpace: "nowrap" }, children: row.isLength ? lengthFitLabelFn(row.fit, t2) : fitLabelFn(row.fit, t2) }) })
17964
17980
  ] }, i);
17965
17981
  }) })
@@ -18688,6 +18704,7 @@ function SizeResultView({
18688
18704
  productImage: resultImageUrl || productImage,
18689
18705
  productTitle,
18690
18706
  isMobile: true,
18707
+ renderRaw: isAccessory,
18691
18708
  isTryOnImage: !!resultImageUrl,
18692
18709
  showLines,
18693
18710
  onToggleLines: () => setShowLines(!showLines),
@@ -18731,7 +18748,8 @@ function SizeResultView({
18731
18748
  onTryOn: resultImageUrl || isAccessory ? void 0 : handleSingleTryOn,
18732
18749
  continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
18733
18750
  tryOnProcessing,
18734
- t: t2
18751
+ t: t2,
18752
+ renderRaw: isAccessory
18735
18753
  }
18736
18754
  ) }, "panel-single")
18737
18755
  ] });
@@ -22463,6 +22481,7 @@ function FootSizeView(props) {
22463
22481
  {
22464
22482
  title: "Shoe Size",
22465
22483
  fields,
22484
+ disablePhotoUpload: true,
22466
22485
  ...rest
22467
22486
  }
22468
22487
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "5.8.54",
3
+ "version": "5.8.55",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",