@primestyleai/tryon 5.8.44 → 5.8.46
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
CHANGED
|
@@ -238,7 +238,8 @@ function computeMeasurements(lm, imageWidth, imageHeight) {
|
|
|
238
238
|
return pxDist * pxToMm;
|
|
239
239
|
};
|
|
240
240
|
const pd = mmBetween(lm.leftIrisCenter, lm.rightIrisCenter);
|
|
241
|
-
const
|
|
241
|
+
const innerEyeGap = mmBetween(lm.leftInnerEye, lm.rightInnerEye);
|
|
242
|
+
const bridgeWidth = innerEyeGap / 1.6;
|
|
242
243
|
const faceWidth = mmBetween(lm.leftTragus, lm.rightTragus);
|
|
243
244
|
const templeLengthLeft = mmBetween(lm.leftTragus, lm.leftOuterEye);
|
|
244
245
|
const templeLengthRight = mmBetween(lm.rightTragus, lm.rightOuterEye);
|
|
@@ -7950,10 +7951,12 @@ const fitLabelFn = (fit, t) => fit === "good" ? t("perfect fit") : fit === "too-
|
|
|
7950
7951
|
const lengthFitLabelFn = (fit, t) => fit === "good" ? t("perfect fit") : fit === "too-tight" ? t("too short") : fit === "tight" ? t("short") : fit === "a-bit-tight" ? t("a bit short") : fit === "too-loose" ? t("too long") : fit === "loose" ? t("long") : t("a bit long");
|
|
7951
7952
|
function convertNum(n, from, to) {
|
|
7952
7953
|
if (from === to || !n || isNaN(n)) return n;
|
|
7954
|
+
if (from === "mm" || to === "mm") return n;
|
|
7953
7955
|
return from === "cm" ? Math.round(n / 2.54 * 10) / 10 : Math.round(n * 2.54 * 10) / 10;
|
|
7954
7956
|
}
|
|
7955
7957
|
function convertLabel(label, from, to) {
|
|
7956
7958
|
if (from === to) return label;
|
|
7959
|
+
if (from === "mm" || to === "mm") return label;
|
|
7957
7960
|
const conv = (n) => convertNum(n, from, to);
|
|
7958
7961
|
const rangeMatch = label.match(/^(\d+\.?\d*)\s*[-–]\s*(\d+\.?\d*)$/);
|
|
7959
7962
|
if (rangeMatch) return `${conv(parseFloat(rangeMatch[1]))}-${conv(parseFloat(rangeMatch[2]))}`;
|
|
@@ -7994,7 +7997,8 @@ function SectionDetailView({
|
|
|
7994
7997
|
}) {
|
|
7995
7998
|
const recSize = sectionResult?.recommendedSize || "";
|
|
7996
7999
|
const [selectedSize, setSelectedSize] = useState(null);
|
|
7997
|
-
const
|
|
8000
|
+
const unitLblLower = unitLbl.toLowerCase();
|
|
8001
|
+
const displayUnitId = unitLblLower.includes("mm") ? "mm" : unitLblLower.includes("cm") ? "cm" : "in";
|
|
7998
8002
|
const fromUnit = chartUnit || displayUnitId;
|
|
7999
8003
|
const dNum = (n) => convertNum(n, fromUnit, displayUnitId);
|
|
8000
8004
|
const dLabel = (s) => convertLabel(s, fromUnit, displayUnitId);
|
|
@@ -8632,8 +8636,9 @@ function SizeResultView({
|
|
|
8632
8636
|
userHeightCm,
|
|
8633
8637
|
t
|
|
8634
8638
|
}) {
|
|
8635
|
-
const
|
|
8636
|
-
const
|
|
8639
|
+
const resultUnitRaw = (sizingResult?.unit || sizingUnit || "").toString().toLowerCase();
|
|
8640
|
+
const resultUnit = resultUnitRaw === "mm" ? "mm" : resultUnitRaw === "cm" ? "cm" : "in";
|
|
8641
|
+
const unitLbl = resultUnit === "mm" ? t("mm") : sizingUnit === "cm" ? t("cm") : t("in");
|
|
8637
8642
|
const [editVals, setEditVals] = useState({});
|
|
8638
8643
|
const pRange = pRangeFn;
|
|
8639
8644
|
const cellVal = useCallback((row, colIdx, header) => {
|
|
@@ -13422,6 +13427,69 @@ function PrimeStyleTryonInner({
|
|
|
13422
13427
|
const method = methodOverride || sizingMethod;
|
|
13423
13428
|
const baseUrl = getApiUrl(apiUrl);
|
|
13424
13429
|
const key = getApiKey();
|
|
13430
|
+
const measurementType = detectMeasurementType(productTitle);
|
|
13431
|
+
if (measurementType === "face" || measurementType === "head") {
|
|
13432
|
+
const f = formRef.current;
|
|
13433
|
+
const toNum = (v) => {
|
|
13434
|
+
if (!v) return void 0;
|
|
13435
|
+
const n = parseFloat(v);
|
|
13436
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
13437
|
+
};
|
|
13438
|
+
const inputUnit = f.sizingUnit || sizingUnit || (measurementType === "head" ? "cm" : "mm");
|
|
13439
|
+
const toMm = (n) => {
|
|
13440
|
+
if (n == null) return void 0;
|
|
13441
|
+
if (inputUnit === "mm") return n;
|
|
13442
|
+
if (inputUnit === "cm") return n * 10;
|
|
13443
|
+
if (inputUnit === "in") return n * 25.4;
|
|
13444
|
+
return n;
|
|
13445
|
+
};
|
|
13446
|
+
const faceMm = {};
|
|
13447
|
+
const src = {
|
|
13448
|
+
bridgeWidth: toMm(toNum(f.bridgeWidth)),
|
|
13449
|
+
templeLength: toMm(toNum(f.templeLength) ?? toNum(f.armLength)),
|
|
13450
|
+
lensWidth: toMm(toNum(f.lensWidth)),
|
|
13451
|
+
lensHeight: toMm(toNum(f.lensHeight)),
|
|
13452
|
+
faceWidth: toMm(toNum(f.faceWidth) ?? toNum(f.frameWidth)),
|
|
13453
|
+
pd: toMm(toNum(f.pd)),
|
|
13454
|
+
// Headwear — circumference usually typed in cm; keep as mm internally.
|
|
13455
|
+
headCircumference: toMm(toNum(f.headCircumference)),
|
|
13456
|
+
headWidth: toMm(toNum(f.headWidth))
|
|
13457
|
+
};
|
|
13458
|
+
for (const [k, v] of Object.entries(src)) if (typeof v === "number") faceMm[k] = v;
|
|
13459
|
+
const facePayload = {
|
|
13460
|
+
product: { title: productTitle, productId },
|
|
13461
|
+
sizeGuide: sizeGuide?.found ? sizeGuide : { found: false },
|
|
13462
|
+
sizingUnit: measurementType === "head" ? "cm" : "mm",
|
|
13463
|
+
category: measurementType,
|
|
13464
|
+
...Object.keys(faceMm).length > 0 && { faceMeasurementsMm: faceMm, irisConfidence: 1 }
|
|
13465
|
+
};
|
|
13466
|
+
try {
|
|
13467
|
+
const resp = await fetch(`${baseUrl}/api/v1/sizing/face-recommend`, {
|
|
13468
|
+
method: "POST",
|
|
13469
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
13470
|
+
body: JSON.stringify(facePayload)
|
|
13471
|
+
});
|
|
13472
|
+
if (resp.ok) {
|
|
13473
|
+
const data = await resp.json();
|
|
13474
|
+
setSizingResult(data);
|
|
13475
|
+
onComplete?.(data);
|
|
13476
|
+
} else {
|
|
13477
|
+
const body = await resp.text().catch(() => "");
|
|
13478
|
+
console.error("[PS-SDK] face-recommend failed:", resp.status, body);
|
|
13479
|
+
setErrorMessage(t("Unable to get size recommendation. Please try again."));
|
|
13480
|
+
setView("error");
|
|
13481
|
+
setEstimationDone(true);
|
|
13482
|
+
}
|
|
13483
|
+
} catch (err) {
|
|
13484
|
+
console.error("[PS-SDK] face-recommend network error:", err);
|
|
13485
|
+
setErrorMessage(t("Unable to connect to sizing service. Please try again."));
|
|
13486
|
+
setView("error");
|
|
13487
|
+
setEstimationDone(true);
|
|
13488
|
+
} finally {
|
|
13489
|
+
setSizingLoading(false);
|
|
13490
|
+
}
|
|
13491
|
+
return;
|
|
13492
|
+
}
|
|
13425
13493
|
const payload = {
|
|
13426
13494
|
method,
|
|
13427
13495
|
locale: sizingCountry,
|
|
@@ -9700,7 +9700,8 @@ function computeMeasurements(lm, imageWidth, imageHeight) {
|
|
|
9700
9700
|
return pxDist * pxToMm;
|
|
9701
9701
|
};
|
|
9702
9702
|
const pd2 = mmBetween(lm.leftIrisCenter, lm.rightIrisCenter);
|
|
9703
|
-
const
|
|
9703
|
+
const innerEyeGap = mmBetween(lm.leftInnerEye, lm.rightInnerEye);
|
|
9704
|
+
const bridgeWidth = innerEyeGap / 1.6;
|
|
9704
9705
|
const faceWidth = mmBetween(lm.leftTragus, lm.rightTragus);
|
|
9705
9706
|
const templeLengthLeft = mmBetween(lm.leftTragus, lm.leftOuterEye);
|
|
9706
9707
|
const templeLengthRight = mmBetween(lm.rightTragus, lm.rightOuterEye);
|
|
@@ -17374,10 +17375,12 @@ const fitLabelFn = (fit, t2) => fit === "good" ? t2("perfect fit") : fit === "to
|
|
|
17374
17375
|
const lengthFitLabelFn = (fit, t2) => fit === "good" ? t2("perfect fit") : fit === "too-tight" ? t2("too short") : fit === "tight" ? t2("short") : fit === "a-bit-tight" ? t2("a bit short") : fit === "too-loose" ? t2("too long") : fit === "loose" ? t2("long") : t2("a bit long");
|
|
17375
17376
|
function convertNum(n2, from, to) {
|
|
17376
17377
|
if (from === to || !n2 || isNaN(n2)) return n2;
|
|
17378
|
+
if (from === "mm" || to === "mm") return n2;
|
|
17377
17379
|
return from === "cm" ? Math.round(n2 / 2.54 * 10) / 10 : Math.round(n2 * 2.54 * 10) / 10;
|
|
17378
17380
|
}
|
|
17379
17381
|
function convertLabel(label, from, to) {
|
|
17380
17382
|
if (from === to) return label;
|
|
17383
|
+
if (from === "mm" || to === "mm") return label;
|
|
17381
17384
|
const conv = (n2) => convertNum(n2, from, to);
|
|
17382
17385
|
const rangeMatch = label.match(/^(\d+\.?\d*)\s*[-–]\s*(\d+\.?\d*)$/);
|
|
17383
17386
|
if (rangeMatch) return `${conv(parseFloat(rangeMatch[1]))}-${conv(parseFloat(rangeMatch[2]))}`;
|
|
@@ -17418,7 +17421,8 @@ function SectionDetailView({
|
|
|
17418
17421
|
}) {
|
|
17419
17422
|
const recSize = sectionResult?.recommendedSize || "";
|
|
17420
17423
|
const [selectedSize, setSelectedSize] = reactExports.useState(null);
|
|
17421
|
-
const
|
|
17424
|
+
const unitLblLower = unitLbl.toLowerCase();
|
|
17425
|
+
const displayUnitId = unitLblLower.includes("mm") ? "mm" : unitLblLower.includes("cm") ? "cm" : "in";
|
|
17422
17426
|
const fromUnit = chartUnit || displayUnitId;
|
|
17423
17427
|
const dNum = (n2) => convertNum(n2, fromUnit, displayUnitId);
|
|
17424
17428
|
const dLabel = (s) => convertLabel(s, fromUnit, displayUnitId);
|
|
@@ -18056,8 +18060,9 @@ function SizeResultView({
|
|
|
18056
18060
|
userHeightCm,
|
|
18057
18061
|
t: t2
|
|
18058
18062
|
}) {
|
|
18059
|
-
const
|
|
18060
|
-
const
|
|
18063
|
+
const resultUnitRaw = (sizingResult?.unit || sizingUnit || "").toString().toLowerCase();
|
|
18064
|
+
const resultUnit = resultUnitRaw === "mm" ? "mm" : resultUnitRaw === "cm" ? "cm" : "in";
|
|
18065
|
+
const unitLbl = resultUnit === "mm" ? t2("mm") : sizingUnit === "cm" ? t2("cm") : t2("in");
|
|
18061
18066
|
const [editVals, setEditVals] = reactExports.useState({});
|
|
18062
18067
|
const pRange = pRangeFn;
|
|
18063
18068
|
const cellVal = reactExports.useCallback((row, colIdx, header) => {
|
|
@@ -22846,6 +22851,69 @@ function PrimeStyleTryonInner({
|
|
|
22846
22851
|
const method = methodOverride || sizingMethod;
|
|
22847
22852
|
const baseUrl = getApiUrl(apiUrl);
|
|
22848
22853
|
const key = getApiKey();
|
|
22854
|
+
const measurementType = detectMeasurementType(productTitle);
|
|
22855
|
+
if (measurementType === "face" || measurementType === "head") {
|
|
22856
|
+
const f2 = formRef.current;
|
|
22857
|
+
const toNum = (v2) => {
|
|
22858
|
+
if (!v2) return void 0;
|
|
22859
|
+
const n2 = parseFloat(v2);
|
|
22860
|
+
return Number.isFinite(n2) && n2 > 0 ? n2 : void 0;
|
|
22861
|
+
};
|
|
22862
|
+
const inputUnit = f2.sizingUnit || sizingUnit || (measurementType === "head" ? "cm" : "mm");
|
|
22863
|
+
const toMm = (n2) => {
|
|
22864
|
+
if (n2 == null) return void 0;
|
|
22865
|
+
if (inputUnit === "mm") return n2;
|
|
22866
|
+
if (inputUnit === "cm") return n2 * 10;
|
|
22867
|
+
if (inputUnit === "in") return n2 * 25.4;
|
|
22868
|
+
return n2;
|
|
22869
|
+
};
|
|
22870
|
+
const faceMm = {};
|
|
22871
|
+
const src = {
|
|
22872
|
+
bridgeWidth: toMm(toNum(f2.bridgeWidth)),
|
|
22873
|
+
templeLength: toMm(toNum(f2.templeLength) ?? toNum(f2.armLength)),
|
|
22874
|
+
lensWidth: toMm(toNum(f2.lensWidth)),
|
|
22875
|
+
lensHeight: toMm(toNum(f2.lensHeight)),
|
|
22876
|
+
faceWidth: toMm(toNum(f2.faceWidth) ?? toNum(f2.frameWidth)),
|
|
22877
|
+
pd: toMm(toNum(f2.pd)),
|
|
22878
|
+
// Headwear — circumference usually typed in cm; keep as mm internally.
|
|
22879
|
+
headCircumference: toMm(toNum(f2.headCircumference)),
|
|
22880
|
+
headWidth: toMm(toNum(f2.headWidth))
|
|
22881
|
+
};
|
|
22882
|
+
for (const [k2, v2] of Object.entries(src)) if (typeof v2 === "number") faceMm[k2] = v2;
|
|
22883
|
+
const facePayload = {
|
|
22884
|
+
product: { title: productTitle, productId },
|
|
22885
|
+
sizeGuide: sizeGuide?.found ? sizeGuide : { found: false },
|
|
22886
|
+
sizingUnit: measurementType === "head" ? "cm" : "mm",
|
|
22887
|
+
category: measurementType,
|
|
22888
|
+
...Object.keys(faceMm).length > 0 && { faceMeasurementsMm: faceMm, irisConfidence: 1 }
|
|
22889
|
+
};
|
|
22890
|
+
try {
|
|
22891
|
+
const resp = await fetch(`${baseUrl}/api/v1/sizing/face-recommend`, {
|
|
22892
|
+
method: "POST",
|
|
22893
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
|
|
22894
|
+
body: JSON.stringify(facePayload)
|
|
22895
|
+
});
|
|
22896
|
+
if (resp.ok) {
|
|
22897
|
+
const data = await resp.json();
|
|
22898
|
+
setSizingResult(data);
|
|
22899
|
+
onComplete?.(data);
|
|
22900
|
+
} else {
|
|
22901
|
+
const body = await resp.text().catch(() => "");
|
|
22902
|
+
console.error("[PS-SDK] face-recommend failed:", resp.status, body);
|
|
22903
|
+
setErrorMessage(t2("Unable to get size recommendation. Please try again."));
|
|
22904
|
+
setView("error");
|
|
22905
|
+
setEstimationDone(true);
|
|
22906
|
+
}
|
|
22907
|
+
} catch (err) {
|
|
22908
|
+
console.error("[PS-SDK] face-recommend network error:", err);
|
|
22909
|
+
setErrorMessage(t2("Unable to connect to sizing service. Please try again."));
|
|
22910
|
+
setView("error");
|
|
22911
|
+
setEstimationDone(true);
|
|
22912
|
+
} finally {
|
|
22913
|
+
setSizingLoading(false);
|
|
22914
|
+
}
|
|
22915
|
+
return;
|
|
22916
|
+
}
|
|
22849
22917
|
const payload = {
|
|
22850
22918
|
method,
|
|
22851
22919
|
locale: sizingCountry,
|