@primestyleai/tryon 3.3.0 → 3.4.1

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.
Files changed (2) hide show
  1. package/dist/react/index.js +76 -19
  2. package/package.json +1 -1
@@ -246,6 +246,8 @@ function PrimeStyleTryonInner({
246
246
  useEffect(() => {
247
247
  if (view === "processing") {
248
248
  progressRef.current = 0;
249
+ if (progressBarRef.current) progressBarRef.current.style.width = "0%";
250
+ if (progressTextRef.current) progressTextRef.current.textContent = "0%";
249
251
  const statuses = [
250
252
  { at: 0, text: "Preparing your image..." },
251
253
  { at: 15, text: "Analyzing body proportions..." },
@@ -256,6 +258,7 @@ function PrimeStyleTryonInner({
256
258
  ];
257
259
  const interval = setInterval(() => {
258
260
  const p = progressRef.current;
261
+ if (p >= 100) return;
259
262
  const increment = p < 30 ? 1.2 : p < 60 ? 0.8 : p < 80 ? 0.4 : p < 95 ? 0.15 : 0;
260
263
  progressRef.current = Math.min(p + increment, 95);
261
264
  const val = Math.round(progressRef.current);
@@ -589,8 +592,8 @@ function PrimeStyleTryonInner({
589
592
  if (p.weightUnit) setWeightUnit(p.weightUnit);
590
593
  setFormKey((k) => k + 1);
591
594
  }, [profiles]);
592
- const saveProfile = useCallback((name) => {
593
- const id = activeProfileId || `p_${Date.now()}`;
595
+ const saveProfile = useCallback((name, asNew) => {
596
+ const id = (asNew ? null : activeProfileId) || `p_${Date.now()}`;
594
597
  const p = {
595
598
  id,
596
599
  name,
@@ -857,6 +860,8 @@ function PrimeStyleTryonInner({
857
860
  function SizingFormView() {
858
861
  const isFemale = formGender === "female";
859
862
  const isCm = sizingUnit === "cm";
863
+ const [saveToggle, setSaveToggle] = useState(false);
864
+ const [saveFormName, setSaveFormName] = useState("");
860
865
  return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
861
866
  /* @__PURE__ */ jsxs("button", { className: "ps-tryon-back", onClick: () => setView("sizing-choice"), children: [
862
867
  /* @__PURE__ */ jsx(ArrowLeftIcon, {}),
@@ -948,7 +953,28 @@ function PrimeStyleTryonInner({
948
953
  ] })
949
954
  ] }),
950
955
  /* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
951
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: handleSubmit, children: [
956
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-form-save-toggle", children: [
957
+ /* @__PURE__ */ jsxs("label", { className: "ps-tryon-form-save-check", children: [
958
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: saveToggle, onChange: (e) => setSaveToggle(e.target.checked) }),
959
+ /* @__PURE__ */ jsx("span", { children: "Save as profile" })
960
+ ] }),
961
+ saveToggle && /* @__PURE__ */ jsx(
962
+ "input",
963
+ {
964
+ type: "text",
965
+ className: "ps-tryon-form-save-name",
966
+ placeholder: "Profile name (e.g. John, Sarah)",
967
+ value: saveFormName,
968
+ onChange: (e) => setSaveFormName(e.target.value)
969
+ }
970
+ )
971
+ ] }),
972
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: () => {
973
+ if (saveToggle && saveFormName.trim()) {
974
+ saveProfile(saveFormName.trim());
975
+ }
976
+ handleSubmit();
977
+ }, children: [
952
978
  "Get My Size & Try On ",
953
979
  /* @__PURE__ */ jsx(ArrowRightIcon, {})
954
980
  ] })
@@ -962,7 +988,7 @@ function PrimeStyleTryonInner({
962
988
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-scan-overlay" })
963
989
  ] }),
964
990
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-progress-section", children: [
965
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsx("div", { ref: progressBarRef, className: "ps-tryon-progress-bar-fill", style: { width: "0%" } }) }),
991
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-progress-bar-wrap", children: /* @__PURE__ */ jsx("div", { ref: progressBarRef, className: "ps-tryon-progress-bar-fill" }) }),
966
992
  /* @__PURE__ */ jsx("span", { ref: progressTextRef, className: "ps-tryon-progress-pct", children: "0%" })
967
993
  ] }),
968
994
  /* @__PURE__ */ jsx("div", { ref: progressStatusRef, className: cx("ps-tryon-processing-text", cn.processingText), children: "Preparing your image..." }),
@@ -1018,7 +1044,14 @@ function PrimeStyleTryonInner({
1018
1044
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-save-label", children: "Save your measurements for next time" }),
1019
1045
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-row", children: [
1020
1046
  /* @__PURE__ */ jsx("input", { type: "text", placeholder: "Name this profile (e.g. John, Sarah)", value: profileName, onChange: (e) => setProfileName(e.target.value) }),
1021
- /* @__PURE__ */ jsx("button", { onClick: () => {
1047
+ activeProfileId ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-btn-group", children: [
1048
+ /* @__PURE__ */ jsx("button", { onClick: () => {
1049
+ if (profileName.trim()) saveProfile(profileName.trim());
1050
+ }, children: "Update" }),
1051
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-save-new-btn", onClick: () => {
1052
+ if (profileName.trim()) saveProfile(profileName.trim(), true);
1053
+ }, children: "+ New" })
1054
+ ] }) : /* @__PURE__ */ jsx("button", { onClick: () => {
1022
1055
  if (profileName.trim()) saveProfile(profileName.trim());
1023
1056
  }, children: "Save" })
1024
1057
  ] })
@@ -1058,16 +1091,21 @@ function PrimeStyleTryonInner({
1058
1091
  ] }),
1059
1092
  /* @__PURE__ */ jsx(ChevronRightIcon, {})
1060
1093
  ] }, p.id)) : history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: "No history yet." }) : history.map((entry, idx) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-item", children: [
1061
- entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
1094
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-images", children: [
1095
+ entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
1096
+ entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" })
1097
+ ] }),
1062
1098
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-info", children: [
1063
1099
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-product", children: entry.productTitle || "Product" }),
1064
1100
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-meta", children: [
1065
1101
  entry.profileName ? `${entry.profileName} · ` : "",
1066
1102
  new Date(entry.date).toLocaleDateString()
1067
1103
  ] }),
1068
- entry.recommendedSize && /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-sizing", children: /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-size-badge", children: entry.recommendedSize }) })
1104
+ entry.recommendedSize && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-sizing", children: [
1105
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-size-badge", children: entry.recommendedSize }),
1106
+ entry.reasoning && /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-sizing-reason", children: entry.reasoning })
1107
+ ] })
1069
1108
  ] }),
1070
- entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" }),
1071
1109
  /* @__PURE__ */ jsx("button", { className: "ps-tryon-history-delete", onClick: (e) => {
1072
1110
  e.stopPropagation();
1073
1111
  setHistory((prev) => prev.filter((_, i) => i !== idx));
@@ -1213,6 +1251,7 @@ const STYLES = `
1213
1251
  scrollbar-width: thin; scrollbar-color: #333 transparent;
1214
1252
  }
1215
1253
  .ps-tryon-modal-wide { max-width: 920px; }
1254
+ .ps-tryon-modal:has(.ps-tryon-drawer-open) { overflow: hidden; }
1216
1255
  @keyframes ps-slide-up { from { transform: translateY(20px) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
1217
1256
 
1218
1257
  /* Header */
@@ -1412,6 +1451,19 @@ const STYLES = `
1412
1451
  .ps-tryon-shoe-section { border-top: 1px solid #333; padding-top: 14px; margin-top: 6px; display: flex; flex-direction: column; gap: 10px; }
1413
1452
  .ps-tryon-shoe-title { font-size: 13px; font-weight: 600; color: #999; }
1414
1453
  .ps-tryon-disclaimer { font-size: 11px; color: #666; margin: 4px 0 0; }
1454
+ .ps-tryon-form-save-toggle { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
1455
+ .ps-tryon-form-save-check {
1456
+ display: flex; align-items: center; gap: 8px; font-size: 13px; color: #ccc; cursor: pointer; user-select: none;
1457
+ }
1458
+ .ps-tryon-form-save-check input[type="checkbox"] {
1459
+ width: 16px; height: 16px; accent-color: #bb945c; cursor: pointer;
1460
+ }
1461
+ .ps-tryon-form-save-name {
1462
+ padding: 8px 12px; border: 1.5px solid #333; border-radius: 10px;
1463
+ background: #1a1b1a; color: #fff; font-size: 13px; font-family: inherit; outline: none;
1464
+ transition: border-color 0.2s;
1465
+ }
1466
+ .ps-tryon-form-save-name:focus { border-color: #bb945c; }
1415
1467
 
1416
1468
  /* Processing */
1417
1469
  .ps-tryon-processing { text-align: center; padding: 24px; display: flex; flex-direction: column; align-items: center; }
@@ -1450,7 +1502,7 @@ const STYLES = `
1450
1502
  }
1451
1503
  .ps-tryon-progress-bar-fill {
1452
1504
  height: 100%; background: linear-gradient(90deg, #bb945c, #d6ba7d);
1453
- border-radius: 3px; transition: width 0.3s ease;
1505
+ border-radius: 3px; transition: width 0.3s ease; width: 0%;
1454
1506
  }
1455
1507
  .ps-tryon-progress-pct {
1456
1508
  font-size: 13px; font-weight: 700; color: #bb945c; min-width: 36px; text-align: right;
@@ -1519,6 +1571,9 @@ const STYLES = `
1519
1571
  font-size: 13px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; font-family: inherit;
1520
1572
  }
1521
1573
  .ps-tryon-save-row button:hover { opacity: 0.9; }
1574
+ .ps-tryon-save-btn-group { display: flex; gap: 6px; }
1575
+ .ps-tryon-save-new-btn { background: transparent !important; border: 1.5px solid #bb945c !important; color: #bb945c !important; }
1576
+ .ps-tryon-save-new-btn:hover { background: rgba(187,148,92,0.1) !important; }
1522
1577
  .ps-tryon-save-done { font-size: 12px; color: #4ade80; margin-top: 10px; display: flex; align-items: center; gap: 6px; justify-content: center; }
1523
1578
  .ps-tryon-save-done svg { stroke: currentColor; }
1524
1579
 
@@ -1547,7 +1602,7 @@ const STYLES = `
1547
1602
  }
1548
1603
  .ps-tryon-drawer-back:hover { border-color: #bb945c; color: #bb945c; }
1549
1604
  .ps-tryon-drawer-title { font-size: 16px; font-weight: 600; color: #fff; }
1550
- .ps-tryon-drawer-list { display: flex; flex-direction: column; gap: 8px; }
1605
+ .ps-tryon-drawer-list { display: flex; flex-direction: column; gap: 10px; }
1551
1606
  .ps-tryon-drawer-empty { text-align: center; padding: 32px 16px; color: #666; font-size: 14px; }
1552
1607
 
1553
1608
  /* Profile items */
@@ -1570,22 +1625,24 @@ const STYLES = `
1570
1625
 
1571
1626
  /* History items */
1572
1627
  .ps-tryon-history-item {
1573
- display: flex; gap: 10px; padding: 12px;
1574
- border: 1px solid #333; border-radius: 12px; align-items: center; transition: all 0.2s;
1628
+ display: flex; gap: 14px; padding: 14px;
1629
+ border: 1px solid #333; border-radius: 12px; align-items: flex-start; transition: all 0.2s;
1575
1630
  }
1576
- .ps-tryon-history-item:hover { border-color: #bb945c; }
1577
- .ps-tryon-history-thumb { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
1631
+ .ps-tryon-history-item:hover { border-color: #bb945c; box-shadow: 0 4px 12px rgba(187,148,92,0.06); }
1632
+ .ps-tryon-history-images { display: flex; gap: 8px; flex-shrink: 0; }
1633
+ .ps-tryon-history-thumb { width: 64px; height: 80px; border-radius: 10px; object-fit: cover; flex-shrink: 0; }
1578
1634
  .ps-tryon-history-info { flex: 1; min-width: 0; }
1579
- .ps-tryon-history-product { font-size: 13px; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1635
+ .ps-tryon-history-product { font-size: 13px; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
1580
1636
  .ps-tryon-history-meta { font-size: 11px; color: #666; margin-top: 3px; }
1581
- .ps-tryon-history-sizing { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
1637
+ .ps-tryon-history-sizing { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
1638
+ .ps-tryon-history-sizing-reason { font-size: 11px; color: #999; flex: 1; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
1582
1639
  .ps-tryon-history-size-badge {
1583
- width: 28px; height: 28px; border-radius: 50%;
1640
+ flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%;
1584
1641
  display: flex; align-items: center; justify-content: center;
1585
1642
  background: linear-gradient(135deg, #bb945c, #d6ba7d);
1586
- color: #111; font-size: 11px; font-weight: 700; flex-shrink: 0;
1643
+ color: #111; font-size: 13px; font-weight: 700;
1587
1644
  }
1588
- .ps-tryon-history-result-img { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; border: 1.5px solid #bb945c; }
1645
+ .ps-tryon-history-result-img { width: 64px; height: 80px; border-radius: 10px; object-fit: cover; flex-shrink: 0; border: 2px solid #bb945c; }
1589
1646
  .ps-tryon-history-delete {
1590
1647
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
1591
1648
  border: none; background: transparent; cursor: pointer; color: #666; border-radius: 6px; transition: all 0.2s; flex-shrink: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",