@primestyleai/tryon 3.18.0 → 3.19.0
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.
|
@@ -308,6 +308,9 @@ const en = {
|
|
|
308
308
|
"Compare with another size": "Compare with another size",
|
|
309
309
|
"recommended": "recommended",
|
|
310
310
|
"size": "size",
|
|
311
|
+
"Your size in other countries": "Your size in other countries",
|
|
312
|
+
"Showing fit for size": "Showing fit for size",
|
|
313
|
+
"Back to": "Back to",
|
|
311
314
|
"Fit Analysis": "Fit Analysis",
|
|
312
315
|
"Show more": "Show more",
|
|
313
316
|
"Done": "Done",
|
package/dist/primestyle-tryon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-
|
|
2
|
-
import { P, b, T, d, r } from "./index-
|
|
1
|
+
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-DmAF7P54.js";
|
|
2
|
+
import { P, b, T, d, r } from "./index-DmAF7P54.js";
|
|
3
3
|
function detectProductImage() {
|
|
4
4
|
const ogImage = document.querySelector(
|
|
5
5
|
'meta[property="og:image"]'
|
package/dist/react/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useMemo, useRef, useCallback } from "react";
|
|
4
|
-
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError, L as LOCALE_LABELS, b as SUPPORTED_LOCALES } from "../index-
|
|
4
|
+
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError, L as LOCALE_LABELS, b as SUPPORTED_LOCALES } from "../index-DmAF7P54.js";
|
|
5
5
|
const HEADER_ALIASES = {
|
|
6
6
|
// ── Size label columns (skipped during field derivation) ──
|
|
7
7
|
size: "__size__",
|
|
@@ -424,9 +424,6 @@ function detectLocale() {
|
|
|
424
424
|
function isImperial(locale) {
|
|
425
425
|
return locale === "US" || locale === "UK";
|
|
426
426
|
}
|
|
427
|
-
function cmToIn(cm) {
|
|
428
|
-
return +(cm / 2.54).toFixed(1);
|
|
429
|
-
}
|
|
430
427
|
function inToCm(inches) {
|
|
431
428
|
return +(inches * 2.54).toFixed(1);
|
|
432
429
|
}
|
|
@@ -826,115 +823,7 @@ function PrimeStyleTryonInner({
|
|
|
826
823
|
}
|
|
827
824
|
return formGender === "female" ? FALLBACK_FIELDS_FEMALE : FALLBACK_FIELDS_MALE;
|
|
828
825
|
}, [sizeGuide, formGender]);
|
|
829
|
-
const computeSizingLocally = useCallback(() => {
|
|
830
|
-
if (sizingMethod !== "exact" || !sizeGuide?.found || !sizeGuide.headers || !sizeGuide.rows) return null;
|
|
831
|
-
const HEADER_MAP = {
|
|
832
|
-
chest: "chest",
|
|
833
|
-
bust: "bust",
|
|
834
|
-
waist: "waist",
|
|
835
|
-
hips: "hips",
|
|
836
|
-
hip: "hips",
|
|
837
|
-
shoulder: "shoulderWidth",
|
|
838
|
-
shoulders: "shoulderWidth",
|
|
839
|
-
"shoulder width": "shoulderWidth",
|
|
840
|
-
sleeve: "sleeveLength",
|
|
841
|
-
"sleeve length": "sleeveLength",
|
|
842
|
-
inseam: "inseam",
|
|
843
|
-
neck: "neckCircumference",
|
|
844
|
-
foot: "footLengthCm",
|
|
845
|
-
"foot length": "footLengthCm"
|
|
846
|
-
};
|
|
847
|
-
const INTL = /* @__PURE__ */ new Set(["eu", "us", "uk", "it", "fr", "de", "jp", "cn", "kr", "au", "br", "eur"]);
|
|
848
|
-
const userMeas = {};
|
|
849
|
-
for (const f of dynamicFields) {
|
|
850
|
-
if (f.unit === "size" || ["shoeEU", "shoeUS", "shoeUK"].includes(f.key)) continue;
|
|
851
|
-
const raw = formRef.current[f.key];
|
|
852
|
-
if (!raw) continue;
|
|
853
|
-
const v = parseFloat(raw);
|
|
854
|
-
if (isNaN(v)) continue;
|
|
855
|
-
userMeas[f.key] = sizingUnit === "in" ? inToCm(v) : v;
|
|
856
|
-
}
|
|
857
|
-
for (const k of ["chest", "bust", "waist", "hips", "shoulderWidth", "sleeveLength", "inseam", "neckCircumference", "footLengthCm"]) {
|
|
858
|
-
if (userMeas[k] || !formRef.current[k]) continue;
|
|
859
|
-
const v = parseFloat(formRef.current[k]);
|
|
860
|
-
if (!isNaN(v)) userMeas[k] = sizingUnit === "in" ? inToCm(v) : v;
|
|
861
|
-
}
|
|
862
|
-
if (Object.keys(userMeas).length === 0) return null;
|
|
863
|
-
let idx = sizeGuide.headers.findIndex((h) => /^size$/i.test(h.trim()));
|
|
864
|
-
if (idx < 0) idx = sizeGuide.headers.findIndex((h) => /size|taglia|größe|taille/i.test(h.trim()));
|
|
865
|
-
if (idx < 0) {
|
|
866
|
-
const firstColVals = sizeGuide.rows.map((r) => r[0]?.trim() || "");
|
|
867
|
-
idx = firstColVals.some((v) => /^(XXS|XS|S|M|L|XL|XXL|XXXL|\d{1,3})$/i.test(v)) ? 0 : 0;
|
|
868
|
-
}
|
|
869
|
-
const colMap = [];
|
|
870
|
-
const intlCols = [];
|
|
871
|
-
sizeGuide.headers.forEach((h, i) => {
|
|
872
|
-
if (i === idx) return;
|
|
873
|
-
const lower = h.toLowerCase().trim().replace(/\s*\(.*\)/, "");
|
|
874
|
-
const clean = lower.replace(/\s*size\s*/gi, "").trim();
|
|
875
|
-
if (INTL.has(clean)) {
|
|
876
|
-
intlCols.push({ hi: i, code: clean.toUpperCase() });
|
|
877
|
-
return;
|
|
878
|
-
}
|
|
879
|
-
let fk = HEADER_MAP[clean];
|
|
880
|
-
if (!fk) {
|
|
881
|
-
const pk = Object.keys(HEADER_MAP).find((k) => clean.includes(k));
|
|
882
|
-
if (pk) fk = HEADER_MAP[pk];
|
|
883
|
-
}
|
|
884
|
-
if (fk && userMeas[fk] !== void 0) colMap.push({ hi: i, formKey: fk, label: h.trim() });
|
|
885
|
-
});
|
|
886
|
-
if (colMap.length === 0) return null;
|
|
887
|
-
const parseRange = (cell) => {
|
|
888
|
-
const nums = cell.replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((n) => !isNaN(n));
|
|
889
|
-
if (nums.length === 0) return null;
|
|
890
|
-
return { min: Math.min(...nums), max: Math.max(...nums) };
|
|
891
|
-
};
|
|
892
|
-
const scores = [];
|
|
893
|
-
for (const row of sizeGuide.rows) {
|
|
894
|
-
const label = row[idx] || "";
|
|
895
|
-
let fitting = 0;
|
|
896
|
-
let total = 0;
|
|
897
|
-
let dist = 0;
|
|
898
|
-
const details = [];
|
|
899
|
-
for (const col of colMap) {
|
|
900
|
-
const range = parseRange(row[col.hi] || "");
|
|
901
|
-
if (!range) continue;
|
|
902
|
-
total++;
|
|
903
|
-
const uv = userMeas[col.formKey];
|
|
904
|
-
const fit = uv >= range.min && uv <= range.max ? "good" : uv < range.min ? "tight" : "loose";
|
|
905
|
-
if (fit === "good") fitting++;
|
|
906
|
-
dist += Math.abs(uv - (range.min + range.max) / 2);
|
|
907
|
-
const dispVal = sizingUnit === "in" ? `${cmToIn(uv)} in` : `${Math.round(uv)} cm`;
|
|
908
|
-
const dispRange = sizingUnit === "in" ? `${cmToIn(range.min)}–${cmToIn(range.max)} in` : `${Math.round(range.min)}–${Math.round(range.max)} cm`;
|
|
909
|
-
details.push({ measurement: col.label, userValue: dispVal, chartRange: dispRange, fit });
|
|
910
|
-
}
|
|
911
|
-
if (total === 0) continue;
|
|
912
|
-
const intl = {};
|
|
913
|
-
for (const ic of intlCols) {
|
|
914
|
-
if (row[ic.hi]) intl[ic.code] = row[ic.hi];
|
|
915
|
-
}
|
|
916
|
-
scores.push({ label, fitting, total, dist, details, intl, row });
|
|
917
|
-
}
|
|
918
|
-
if (scores.length === 0) return null;
|
|
919
|
-
scores.sort((a, b) => b.fitting - a.fitting || a.dist - b.dist);
|
|
920
|
-
const best = scores[0];
|
|
921
|
-
const conf = best.fitting === best.total ? "high" : best.fitting >= best.total * 0.6 ? "medium" : "low";
|
|
922
|
-
return {
|
|
923
|
-
recommendedSize: best.label,
|
|
924
|
-
confidence: conf,
|
|
925
|
-
reasoning: `Based on your measurements, size ${best.label} is the best fit.`,
|
|
926
|
-
internationalSizes: best.intl,
|
|
927
|
-
matchDetails: best.details,
|
|
928
|
-
method: "deterministic"
|
|
929
|
-
};
|
|
930
|
-
}, [sizingMethod, sizeGuide, dynamicFields, sizingUnit]);
|
|
931
826
|
const submitSizing = useCallback(async () => {
|
|
932
|
-
const localResult = computeSizingLocally();
|
|
933
|
-
if (localResult) {
|
|
934
|
-
setSizingResult(localResult);
|
|
935
|
-
setSizingLoading(false);
|
|
936
|
-
return;
|
|
937
|
-
}
|
|
938
827
|
if (!apiRef.current) return;
|
|
939
828
|
const baseUrl = getApiUrl(apiUrl);
|
|
940
829
|
const key = getApiKey();
|
|
@@ -993,7 +882,7 @@ function PrimeStyleTryonInner({
|
|
|
993
882
|
} finally {
|
|
994
883
|
setSizingLoading(false);
|
|
995
884
|
}
|
|
996
|
-
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle, dynamicFields
|
|
885
|
+
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle, dynamicFields]);
|
|
997
886
|
const handleTryOnSubmit = useCallback(async () => {
|
|
998
887
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
999
888
|
const msg = !apiRef.current ? t("SDK not configured. Please provide an API key.") : t("Something went wrong");
|
|
@@ -1582,65 +1471,65 @@ function PrimeStyleTryonInner({
|
|
|
1582
1471
|
] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}-${formKey}`);
|
|
1583
1472
|
}
|
|
1584
1473
|
function SizeResultView() {
|
|
1585
|
-
const
|
|
1586
|
-
const unitLbl = isCmR ? t("cm") : t("in");
|
|
1587
|
-
const allSizes = useMemo(() => {
|
|
1588
|
-
if (!sizeGuide?.found || !sizeGuide.headers || !sizeGuide.rows) return [];
|
|
1589
|
-
const idx = sizeGuide.headers.findIndex((h) => /^size$/i.test(h.trim()));
|
|
1590
|
-
const col = idx >= 0 ? idx : 0;
|
|
1591
|
-
return sizeGuide.rows.map((r) => r[col]?.trim()).filter(Boolean);
|
|
1592
|
-
}, [sizeGuide]);
|
|
1593
|
-
const [compareSize, setCompareSize] = useState("");
|
|
1474
|
+
const unitLbl = sizingUnit === "cm" ? t("cm") : t("in");
|
|
1594
1475
|
const [editVals, setEditVals] = useState({});
|
|
1595
|
-
const
|
|
1476
|
+
const [compareSize, setCompareSize] = useState("");
|
|
1477
|
+
const sizeColIdx = useMemo(() => {
|
|
1478
|
+
if (!sizeGuide?.headers || !sizeGuide?.rows) return -1;
|
|
1479
|
+
const byName = sizeGuide.headers.findIndex((h) => /size|taglia|größe|taille/i.test(h.trim()));
|
|
1480
|
+
if (byName >= 0) return byName;
|
|
1481
|
+
for (let c = 0; c < sizeGuide.headers.length; c++) {
|
|
1482
|
+
const vals = sizeGuide.rows.map((r) => r[c]?.trim() || "");
|
|
1483
|
+
if (vals.some((v) => /^(XXS|XS|S|M|L|XL|XXL|XXXL|ONE SIZE|\d{1,2})$/i.test(v))) return c;
|
|
1484
|
+
}
|
|
1485
|
+
return 0;
|
|
1486
|
+
}, [sizeGuide]);
|
|
1487
|
+
const allSizes = useMemo(() => {
|
|
1488
|
+
if (sizeColIdx < 0 || !sizeGuide?.rows) return [];
|
|
1489
|
+
return sizeGuide.rows.map((r) => r[sizeColIdx]?.trim()).filter(Boolean);
|
|
1490
|
+
}, [sizeGuide, sizeColIdx]);
|
|
1491
|
+
const pNum = (s) => {
|
|
1596
1492
|
const n = parseFloat(s.replace(/[^\d.]/g, ""));
|
|
1597
1493
|
return isNaN(n) ? 0 : n;
|
|
1598
1494
|
};
|
|
1599
|
-
const
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1602
|
-
return { min: Math.min(...nums), max: Math.max(...nums) };
|
|
1495
|
+
const pRange = (s) => {
|
|
1496
|
+
const ns = s.replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((n) => !isNaN(n));
|
|
1497
|
+
return ns.length ? { min: Math.min(...ns), max: Math.max(...ns) } : { min: 0, max: 0 };
|
|
1603
1498
|
};
|
|
1604
|
-
const
|
|
1605
|
-
if (!sizeGuide?.
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
const measCol = sizeGuide.headers.findIndex((h) => {
|
|
1609
|
-
const a = h.toLowerCase().trim();
|
|
1610
|
-
const b = measurement.toLowerCase().trim();
|
|
1499
|
+
const chartRangeFor = useCallback((measurement, size) => {
|
|
1500
|
+
if (!sizeGuide?.headers || !sizeGuide?.rows || sizeColIdx < 0) return null;
|
|
1501
|
+
const mc = sizeGuide.headers.findIndex((h) => {
|
|
1502
|
+
const a = h.toLowerCase().trim(), b = measurement.toLowerCase().trim();
|
|
1611
1503
|
return a === b || a.includes(b) || b.includes(a);
|
|
1612
1504
|
});
|
|
1613
|
-
if (
|
|
1614
|
-
const row = sizeGuide.rows.find((r) => r[
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
const parsed = parseRangeFromDetail(cell);
|
|
1618
|
-
return { range: cell, ...parsed };
|
|
1619
|
-
}, [sizeGuide]);
|
|
1505
|
+
if (mc < 0) return null;
|
|
1506
|
+
const row = sizeGuide.rows.find((r) => r[sizeColIdx]?.trim() === size);
|
|
1507
|
+
return row?.[mc] ? { range: row[mc], ...pRange(row[mc]) } : null;
|
|
1508
|
+
}, [sizeGuide, sizeColIdx]);
|
|
1620
1509
|
const fitRows = useMemo(() => {
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
const
|
|
1626
|
-
const
|
|
1627
|
-
|
|
1628
|
-
let
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
if (compareSize && compareSize !== sizingResult?.recommendedSize) {
|
|
1632
|
-
const alt = getChartRangeForSize(m.measurement, compareSize);
|
|
1510
|
+
if (!sizingResult?.matchDetails?.length) return [];
|
|
1511
|
+
compareSize || sizingResult.recommendedSize || "";
|
|
1512
|
+
return sizingResult.matchDetails.map((m) => {
|
|
1513
|
+
const origNum = pNum(m.userValue);
|
|
1514
|
+
const edited = editVals[m.measurement];
|
|
1515
|
+
const userNum = edited !== void 0 && edited !== "" ? parseFloat(edited) : origNum;
|
|
1516
|
+
let { min: rMin, max: rMax } = pRange(m.chartRange);
|
|
1517
|
+
let chartLabel = m.chartRange;
|
|
1518
|
+
if (compareSize && compareSize !== sizingResult.recommendedSize) {
|
|
1519
|
+
const alt = chartRangeFor(m.measurement, compareSize);
|
|
1633
1520
|
if (alt) {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1521
|
+
chartLabel = alt.range;
|
|
1522
|
+
rMin = alt.min;
|
|
1523
|
+
rMax = alt.max;
|
|
1637
1524
|
}
|
|
1638
1525
|
}
|
|
1639
|
-
const fit = userNum >=
|
|
1640
|
-
return {
|
|
1526
|
+
const fit = userNum >= rMin && userNum <= rMax ? "good" : userNum < rMin ? "tight" : "loose";
|
|
1527
|
+
return { area: m.measurement, userNum, chartLabel, fit };
|
|
1641
1528
|
});
|
|
1642
|
-
}, [sizingResult, compareSize, editVals,
|
|
1529
|
+
}, [sizingResult, compareSize, editVals, chartRangeFor]);
|
|
1643
1530
|
const intlSizes = sizingResult?.internationalSizes || {};
|
|
1531
|
+
const recSize = sizingResult?.recommendedSize || "";
|
|
1532
|
+
const selSize = compareSize || recSize;
|
|
1644
1533
|
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr", children: [
|
|
1645
1534
|
sizingLoading && !sizingResult && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-loading", children: [
|
|
1646
1535
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-size-loading-spinner" }),
|
|
@@ -1648,14 +1537,17 @@ function PrimeStyleTryonInner({
|
|
|
1648
1537
|
] }),
|
|
1649
1538
|
sizingResult && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1650
1539
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-hero", children: [
|
|
1651
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-hero-badge", children:
|
|
1540
|
+
recSize && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-hero-badge", children: recSize }),
|
|
1652
1541
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-hero-info", children: [
|
|
1653
|
-
/* @__PURE__ */
|
|
1542
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-hero-title", children: [
|
|
1543
|
+
t("Your Size"),
|
|
1544
|
+
recSize ? `: ${recSize}` : ""
|
|
1545
|
+
] }),
|
|
1654
1546
|
/* @__PURE__ */ jsx("div", { className: `ps-tryon-sr-hero-conf ps-conf-${sizingResult.confidence}`, children: sizingResult.confidence === "high" ? t("High Confidence") : sizingResult.confidence === "medium" ? t("Medium Confidence") : t("Low Confidence") })
|
|
1655
1547
|
] })
|
|
1656
1548
|
] }),
|
|
1657
1549
|
Object.keys(intlSizes).length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-intl", children: [
|
|
1658
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("
|
|
1550
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("Your size in other countries") }),
|
|
1659
1551
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-intl-primary", children: Object.entries(intlSizes).map(([code, val]) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-intl-card", children: [
|
|
1660
1552
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-card-val", children: val }),
|
|
1661
1553
|
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-card-code", children: code })
|
|
@@ -1663,54 +1555,55 @@ function PrimeStyleTryonInner({
|
|
|
1663
1555
|
] }),
|
|
1664
1556
|
allSizes.length > 1 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-compare", children: [
|
|
1665
1557
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("Compare with another size") }),
|
|
1666
|
-
/* @__PURE__ */ jsx(
|
|
1667
|
-
|
|
1668
|
-
{
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
}
|
|
1677
|
-
)
|
|
1678
|
-
] }),
|
|
1679
|
-
fitRows.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit", children: [
|
|
1680
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-label", children: [
|
|
1681
|
-
t("Fit Analysis"),
|
|
1682
|
-
compareSize && compareSize !== sizingResult.recommendedSize && /* @__PURE__ */ jsxs("span", { className: "ps-tryon-sr-label-hint", children: [
|
|
1683
|
-
" — ",
|
|
1684
|
-
t("size"),
|
|
1558
|
+
/* @__PURE__ */ jsx("select", { className: "ps-tryon-sr-compare-select", value: selSize, onChange: (e) => setCompareSize(e.target.value), children: allSizes.map((s) => /* @__PURE__ */ jsxs("option", { value: s, children: [
|
|
1559
|
+
s,
|
|
1560
|
+
s === recSize ? ` ★ ${t("recommended")}` : ""
|
|
1561
|
+
] }, s)) }),
|
|
1562
|
+
compareSize && compareSize !== recSize && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-compare-note", children: [
|
|
1563
|
+
t("Showing fit for size"),
|
|
1564
|
+
" ",
|
|
1565
|
+
/* @__PURE__ */ jsx("strong", { children: compareSize }),
|
|
1566
|
+
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-sr-compare-reset", onClick: () => setCompareSize(""), children: [
|
|
1567
|
+
t("Back to"),
|
|
1685
1568
|
" ",
|
|
1686
|
-
|
|
1569
|
+
recSize
|
|
1687
1570
|
] })
|
|
1688
|
-
] })
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-
|
|
1571
|
+
] })
|
|
1572
|
+
] }),
|
|
1573
|
+
fitRows.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit", children: [
|
|
1574
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("Fit Analysis") }),
|
|
1575
|
+
fitRows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: `ps-tryon-sr-fit-card ps-fit-${row.fit}`, children: [
|
|
1576
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-card-top", children: [
|
|
1577
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-area", children: row.area }),
|
|
1578
|
+
/* @__PURE__ */ jsx("span", { className: `ps-tryon-sr-fit-badge ps-fit-${row.fit}`, children: row.fit === "good" ? `✓ ${t("within range")}` : row.fit === "tight" ? `↑ ${t("may be snug")}` : `↓ ${t("may be loose")}` })
|
|
1695
1579
|
] }),
|
|
1696
|
-
|
|
1697
|
-
/* @__PURE__ */
|
|
1698
|
-
|
|
1699
|
-
/* @__PURE__ */
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1580
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-card-bottom", children: [
|
|
1581
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-val", children: [
|
|
1582
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-val-label", children: t("You") }),
|
|
1583
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-val-input-wrap", children: [
|
|
1584
|
+
/* @__PURE__ */ jsx(
|
|
1585
|
+
"input",
|
|
1586
|
+
{
|
|
1587
|
+
type: "number",
|
|
1588
|
+
className: "ps-tryon-sr-fit-input",
|
|
1589
|
+
value: editVals[row.area] !== void 0 ? editVals[row.area] : row.userNum,
|
|
1590
|
+
onChange: (e) => setEditVals((prev) => ({ ...prev, [row.area]: e.target.value }))
|
|
1591
|
+
}
|
|
1592
|
+
),
|
|
1593
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-unit", children: unitLbl })
|
|
1594
|
+
] })
|
|
1709
1595
|
] }),
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1596
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-val", children: [
|
|
1597
|
+
/* @__PURE__ */ jsxs("span", { className: "ps-tryon-sr-fit-val-label", children: [
|
|
1598
|
+
t("Chart"),
|
|
1599
|
+
" (",
|
|
1600
|
+
selSize,
|
|
1601
|
+
")"
|
|
1602
|
+
] }),
|
|
1603
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-val-text", children: row.chartLabel })
|
|
1604
|
+
] })
|
|
1605
|
+
] })
|
|
1606
|
+
] }, i))
|
|
1714
1607
|
] }),
|
|
1715
1608
|
fitRows.length === 0 && sizingResult.reasoning && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-reasoning", children: /* @__PURE__ */ jsx("p", { children: sizingResult.reasoning }) }),
|
|
1716
1609
|
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-ctas", children: [
|
|
@@ -2463,44 +2356,49 @@ const STYLES = `
|
|
|
2463
2356
|
.ps-tryon-sr-comparing { font-size: 0.73vw; color: #bb945c; margin-top: 0.42vw; }
|
|
2464
2357
|
.ps-tryon-sr-comparing strong { color: #d6ba7d; }
|
|
2465
2358
|
|
|
2466
|
-
/* Fit analysis
|
|
2467
|
-
.ps-tryon-sr-fit { }
|
|
2468
|
-
.ps-tryon-sr-fit-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
}
|
|
2472
|
-
.ps-tryon-sr-fit-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
}
|
|
2479
|
-
.ps-tryon-sr-fit-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
.ps-tryon-sr-fit-
|
|
2483
|
-
.ps-tryon-sr-fit-
|
|
2484
|
-
|
|
2485
|
-
.ps-tryon-sr-fit-
|
|
2486
|
-
.ps-tryon-sr-fit-col-you { flex: 0 0 22%; }
|
|
2487
|
-
.ps-tryon-sr-fit-col-chart { flex: 0 0 22%; font-size: 0.78vw; color: #999; font-weight: 500; }
|
|
2488
|
-
.ps-tryon-sr-fit-col-fit { flex: 1; text-align: right; }
|
|
2359
|
+
/* Fit analysis cards */
|
|
2360
|
+
.ps-tryon-sr-fit { display: flex; flex-direction: column; gap: 0.52vw; }
|
|
2361
|
+
.ps-tryon-sr-fit-card {
|
|
2362
|
+
border: 1.5px solid #333; border-radius: 0.63vw; overflow: hidden; transition: border-color 0.2s;
|
|
2363
|
+
}
|
|
2364
|
+
.ps-tryon-sr-fit-card.ps-fit-good { border-left: 3px solid #4ade80; }
|
|
2365
|
+
.ps-tryon-sr-fit-card.ps-fit-tight { border-left: 3px solid #f59e0b; }
|
|
2366
|
+
.ps-tryon-sr-fit-card.ps-fit-loose { border-left: 3px solid #60a5fa; }
|
|
2367
|
+
.ps-tryon-sr-fit-card-top {
|
|
2368
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
2369
|
+
padding: 0.52vw 0.83vw; background: #1a1b1a;
|
|
2370
|
+
}
|
|
2371
|
+
.ps-tryon-sr-fit-area { font-size: 0.83vw; font-weight: 600; color: #fff; }
|
|
2372
|
+
.ps-tryon-sr-fit-card-bottom {
|
|
2373
|
+
display: flex; gap: 1vw; padding: 0.52vw 0.83vw;
|
|
2374
|
+
}
|
|
2375
|
+
.ps-tryon-sr-fit-val { flex: 1; }
|
|
2376
|
+
.ps-tryon-sr-fit-val-label { font-size: 0.57vw; font-weight: 700; color: #666; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 0.21vw; display: block; }
|
|
2377
|
+
.ps-tryon-sr-fit-val-input-wrap { display: flex; align-items: center; gap: 0.26vw; }
|
|
2378
|
+
.ps-tryon-sr-fit-val-text { font-size: 0.83vw; font-weight: 600; color: #ccc; }
|
|
2489
2379
|
|
|
2490
2380
|
.ps-tryon-sr-fit-input {
|
|
2491
|
-
width:
|
|
2492
|
-
background: #
|
|
2381
|
+
width: 4vw; padding: 0.31vw 0.42vw; border: 1.5px solid #444; border-radius: 0.36vw;
|
|
2382
|
+
background: #0c0c0d; color: #fff; font-size: 0.83vw; font-weight: 600; font-family: inherit;
|
|
2493
2383
|
outline: none; text-align: center; -moz-appearance: textfield;
|
|
2494
2384
|
}
|
|
2495
2385
|
.ps-tryon-sr-fit-input::-webkit-outer-spin-button,
|
|
2496
2386
|
.ps-tryon-sr-fit-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
|
2497
|
-
.ps-tryon-sr-fit-input:focus { border-color: #bb945c; }
|
|
2498
|
-
.ps-tryon-sr-fit-unit { font-size: 0.
|
|
2387
|
+
.ps-tryon-sr-fit-input:focus { border-color: #bb945c; background: #1a1b1a; }
|
|
2388
|
+
.ps-tryon-sr-fit-unit { font-size: 0.68vw; color: #666; }
|
|
2389
|
+
|
|
2390
|
+
.ps-tryon-sr-fit-badge {
|
|
2391
|
+
display: inline-flex; align-items: center; gap: 0.26vw; padding: 0.26vw 0.57vw;
|
|
2392
|
+
border-radius: 0.36vw; font-size: 0.68vw; font-weight: 700; white-space: nowrap;
|
|
2393
|
+
}
|
|
2394
|
+
.ps-tryon-sr-fit-badge.ps-fit-good { background: rgba(74,222,128,0.1); color: #4ade80; }
|
|
2395
|
+
.ps-tryon-sr-fit-badge.ps-fit-tight { background: rgba(245,158,11,0.1); color: #f59e0b; }
|
|
2396
|
+
.ps-tryon-sr-fit-badge.ps-fit-loose { background: rgba(96,165,250,0.1); color: #60a5fa; }
|
|
2499
2397
|
|
|
2500
2398
|
/* Compare dropdown */
|
|
2501
2399
|
.ps-tryon-sr-compare { }
|
|
2502
2400
|
.ps-tryon-sr-compare-select {
|
|
2503
|
-
width: 100%; padding: 0.
|
|
2401
|
+
width: 100%; padding: 0.57vw 2vw 0.57vw 0.83vw; border: 1.5px solid #333; border-radius: 0.57vw;
|
|
2504
2402
|
background: #1a1b1a; color: #fff; font-size: 0.83vw; font-weight: 600; font-family: inherit;
|
|
2505
2403
|
appearance: none; -webkit-appearance: none; cursor: pointer; outline: none;
|
|
2506
2404
|
background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
@@ -2508,6 +2406,15 @@ const STYLES = `
|
|
|
2508
2406
|
}
|
|
2509
2407
|
.ps-tryon-sr-compare-select:focus { border-color: #bb945c; }
|
|
2510
2408
|
.ps-tryon-sr-compare-select option { background: #1a1b1a; color: #fff; }
|
|
2409
|
+
.ps-tryon-sr-compare-note {
|
|
2410
|
+
font-size: 0.73vw; color: #bb945c; margin-top: 0.42vw; display: flex; align-items: center; gap: 0.52vw;
|
|
2411
|
+
}
|
|
2412
|
+
.ps-tryon-sr-compare-reset {
|
|
2413
|
+
background: none; border: 1px solid #bb945c; color: #bb945c; padding: 0.16vw 0.52vw;
|
|
2414
|
+
border-radius: 0.31vw; font-size: 0.63vw; font-weight: 600; cursor: pointer;
|
|
2415
|
+
font-family: inherit; transition: all 0.2s;
|
|
2416
|
+
}
|
|
2417
|
+
.ps-tryon-sr-compare-reset:hover { background: rgba(187,148,92,0.1); }
|
|
2511
2418
|
|
|
2512
2419
|
.ps-tryon-sr-fit-badge {
|
|
2513
2420
|
display: inline-flex; align-items: center; gap: 0.26vw; padding: 0.21vw 0.52vw;
|