@primestyleai/tryon 3.2.2 → 3.4.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.
Files changed (2) hide show
  1. package/dist/react/index.js +90 -27
  2. package/package.json +57 -57
@@ -589,8 +589,8 @@ function PrimeStyleTryonInner({
589
589
  if (p.weightUnit) setWeightUnit(p.weightUnit);
590
590
  setFormKey((k) => k + 1);
591
591
  }, [profiles]);
592
- const saveProfile = useCallback((name) => {
593
- const id = activeProfileId || `p_${Date.now()}`;
592
+ const saveProfile = useCallback((name, asNew) => {
593
+ const id = (asNew ? null : activeProfileId) || `p_${Date.now()}`;
594
594
  const p = {
595
595
  id,
596
596
  name,
@@ -806,7 +806,8 @@ function PrimeStyleTryonInner({
806
806
  const sgChecked = !sizeGuideFetching && sizeGuide !== null;
807
807
  if (sizeGuideFetching) {
808
808
  return /* @__PURE__ */ jsx("div", { className: "ps-tryon-sizing-choice", children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sg-checking", children: [
809
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-spinner" }),
809
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 32 }) }),
810
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar-wrap", children: /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar" }) }),
810
811
  /* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "Checking size guide..." }),
811
812
  /* @__PURE__ */ jsx("p", { className: "ps-tryon-sg-checking-sub", children: "Looking for size chart data for this product" })
812
813
  ] }) });
@@ -856,8 +857,14 @@ function PrimeStyleTryonInner({
856
857
  function SizingFormView() {
857
858
  const isFemale = formGender === "female";
858
859
  const isCm = sizingUnit === "cm";
860
+ const [saveToggle, setSaveToggle] = useState(false);
861
+ const [saveFormName, setSaveFormName] = useState("");
859
862
  return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
860
- profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-profile-select", value: activeProfileId || "", onChange: (e) => {
863
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-back", onClick: () => setView("sizing-choice"), children: [
864
+ /* @__PURE__ */ jsx(ArrowLeftIcon, {}),
865
+ " Back"
866
+ ] }),
867
+ sizingMethod === "exact" && profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-profile-select", value: activeProfileId || "", onChange: (e) => {
861
868
  if (e.target.value) applyProfile(e.target.value);
862
869
  }, children: [
863
870
  /* @__PURE__ */ jsx("option", { value: "", children: "Auto-fill from saved profile..." }),
@@ -943,7 +950,28 @@ function PrimeStyleTryonInner({
943
950
  ] })
944
951
  ] }),
945
952
  /* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
946
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: handleSubmit, children: [
953
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-form-save-toggle", children: [
954
+ /* @__PURE__ */ jsxs("label", { className: "ps-tryon-form-save-check", children: [
955
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: saveToggle, onChange: (e) => setSaveToggle(e.target.checked) }),
956
+ /* @__PURE__ */ jsx("span", { children: "Save as profile" })
957
+ ] }),
958
+ saveToggle && /* @__PURE__ */ jsx(
959
+ "input",
960
+ {
961
+ type: "text",
962
+ className: "ps-tryon-form-save-name",
963
+ placeholder: "Profile name (e.g. John, Sarah)",
964
+ value: saveFormName,
965
+ onChange: (e) => setSaveFormName(e.target.value)
966
+ }
967
+ )
968
+ ] }),
969
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: () => {
970
+ if (saveToggle && saveFormName.trim()) {
971
+ saveProfile(saveFormName.trim());
972
+ }
973
+ handleSubmit();
974
+ }, children: [
947
975
  "Get My Size & Try On ",
948
976
  /* @__PURE__ */ jsx(ArrowRightIcon, {})
949
977
  ] })
@@ -1013,7 +1041,14 @@ function PrimeStyleTryonInner({
1013
1041
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-save-label", children: "Save your measurements for next time" }),
1014
1042
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-row", children: [
1015
1043
  /* @__PURE__ */ jsx("input", { type: "text", placeholder: "Name this profile (e.g. John, Sarah)", value: profileName, onChange: (e) => setProfileName(e.target.value) }),
1016
- /* @__PURE__ */ jsx("button", { onClick: () => {
1044
+ activeProfileId ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-btn-group", children: [
1045
+ /* @__PURE__ */ jsx("button", { onClick: () => {
1046
+ if (profileName.trim()) saveProfile(profileName.trim());
1047
+ }, children: "Update" }),
1048
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-save-new-btn", onClick: () => {
1049
+ if (profileName.trim()) saveProfile(profileName.trim(), true);
1050
+ }, children: "+ New" })
1051
+ ] }) : /* @__PURE__ */ jsx("button", { onClick: () => {
1017
1052
  if (profileName.trim()) saveProfile(profileName.trim());
1018
1053
  }, children: "Save" })
1019
1054
  ] })
@@ -1053,16 +1088,21 @@ function PrimeStyleTryonInner({
1053
1088
  ] }),
1054
1089
  /* @__PURE__ */ jsx(ChevronRightIcon, {})
1055
1090
  ] }, 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: [
1056
- entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
1091
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-images", children: [
1092
+ entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
1093
+ entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" })
1094
+ ] }),
1057
1095
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-info", children: [
1058
1096
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-product", children: entry.productTitle || "Product" }),
1059
1097
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-meta", children: [
1060
1098
  entry.profileName ? `${entry.profileName} · ` : "",
1061
1099
  new Date(entry.date).toLocaleDateString()
1062
1100
  ] }),
1063
- entry.recommendedSize && /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-sizing", children: /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-size-badge", children: entry.recommendedSize }) })
1101
+ entry.recommendedSize && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-sizing", children: [
1102
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-size-badge", children: entry.recommendedSize }),
1103
+ entry.reasoning && /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-sizing-reason", children: entry.reasoning })
1104
+ ] })
1064
1105
  ] }),
1065
- entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" }),
1066
1106
  /* @__PURE__ */ jsx("button", { className: "ps-tryon-history-delete", onClick: (e) => {
1067
1107
  e.stopPropagation();
1068
1108
  setHistory((prev) => prev.filter((_, i) => i !== idx));
@@ -1208,6 +1248,7 @@ const STYLES = `
1208
1248
  scrollbar-width: thin; scrollbar-color: #333 transparent;
1209
1249
  }
1210
1250
  .ps-tryon-modal-wide { max-width: 920px; }
1251
+ .ps-tryon-modal:has(.ps-tryon-drawer-open) { overflow: hidden; }
1211
1252
  @keyframes ps-slide-up { from { transform: translateY(20px) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
1212
1253
 
1213
1254
  /* Header */
@@ -1357,17 +1398,21 @@ const STYLES = `
1357
1398
  display: flex; align-items: center; justify-content: center; gap: 6px;
1358
1399
  }
1359
1400
  .ps-tryon-sg-found svg { stroke: #4ade80; }
1360
- .ps-tryon-sg-checking {
1361
- display: flex; flex-direction: column; align-items: center; padding: 40px 20px; text-align: center;
1362
- }
1363
- .ps-tryon-sg-checking-spinner {
1364
- width: 40px; height: 40px; border: 3px solid #333;
1365
- border-top-color: #bb945c; border-radius: 50%;
1366
- animation: ps-spin 0.8s linear infinite; margin-bottom: 20px;
1367
- }
1401
+ .ps-tryon-sg-checking { display: flex; flex-direction: column; align-items: center; padding: 40px 20px; text-align: center; }
1402
+ .ps-tryon-sg-checking-icon { color: #bb945c; margin-bottom: 16px; animation: ps-pulse-ruler 1.5s ease-in-out infinite; }
1403
+ .ps-tryon-sg-checking-icon svg { stroke: currentColor; fill: none; }
1404
+ @keyframes ps-pulse-ruler { 0%, 100% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.15); opacity: 1; } }
1405
+ .ps-tryon-sg-checking-bar-wrap { width: 180px; height: 4px; background: #333; border-radius: 2px; overflow: hidden; margin-bottom: 20px; }
1406
+ .ps-tryon-sg-checking-bar { height: 100%; width: 40%; background: linear-gradient(90deg, #bb945c, #d6ba7d); border-radius: 2px; animation: ps-sg-bar 1.5s ease-in-out infinite; }
1407
+ @keyframes ps-sg-bar { 0% { transform: translateX(-100%); } 100% { transform: translateX(350%); } }
1368
1408
  .ps-tryon-sg-checking .ps-tryon-section-title { margin-bottom: 6px; }
1369
1409
  .ps-tryon-sg-checking-sub { font-size: 13px; color: #999; margin: 0; }
1370
1410
 
1411
+ /* Back button */
1412
+ .ps-tryon-back { display: flex; align-items: center; gap: 6px; background: none; border: none; color: #999; font-size: 13px; cursor: pointer; padding: 0; margin-bottom: 12px; font-family: inherit; transition: color 0.2s; }
1413
+ .ps-tryon-back:hover { color: #fff; }
1414
+ .ps-tryon-back svg { stroke: currentColor; fill: none; }
1415
+
1371
1416
  /* Sizing form */
1372
1417
  .ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 12px; }
1373
1418
  .ps-tryon-input-row { display: flex; align-items: center; gap: 10px; }
@@ -1403,6 +1448,19 @@ const STYLES = `
1403
1448
  .ps-tryon-shoe-section { border-top: 1px solid #333; padding-top: 14px; margin-top: 6px; display: flex; flex-direction: column; gap: 10px; }
1404
1449
  .ps-tryon-shoe-title { font-size: 13px; font-weight: 600; color: #999; }
1405
1450
  .ps-tryon-disclaimer { font-size: 11px; color: #666; margin: 4px 0 0; }
1451
+ .ps-tryon-form-save-toggle { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
1452
+ .ps-tryon-form-save-check {
1453
+ display: flex; align-items: center; gap: 8px; font-size: 13px; color: #ccc; cursor: pointer; user-select: none;
1454
+ }
1455
+ .ps-tryon-form-save-check input[type="checkbox"] {
1456
+ width: 16px; height: 16px; accent-color: #bb945c; cursor: pointer;
1457
+ }
1458
+ .ps-tryon-form-save-name {
1459
+ padding: 8px 12px; border: 1.5px solid #333; border-radius: 10px;
1460
+ background: #1a1b1a; color: #fff; font-size: 13px; font-family: inherit; outline: none;
1461
+ transition: border-color 0.2s;
1462
+ }
1463
+ .ps-tryon-form-save-name:focus { border-color: #bb945c; }
1406
1464
 
1407
1465
  /* Processing */
1408
1466
  .ps-tryon-processing { text-align: center; padding: 24px; display: flex; flex-direction: column; align-items: center; }
@@ -1510,6 +1568,9 @@ const STYLES = `
1510
1568
  font-size: 13px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; font-family: inherit;
1511
1569
  }
1512
1570
  .ps-tryon-save-row button:hover { opacity: 0.9; }
1571
+ .ps-tryon-save-btn-group { display: flex; gap: 6px; }
1572
+ .ps-tryon-save-new-btn { background: transparent !important; border: 1.5px solid #bb945c !important; color: #bb945c !important; }
1573
+ .ps-tryon-save-new-btn:hover { background: rgba(187,148,92,0.1) !important; }
1513
1574
  .ps-tryon-save-done { font-size: 12px; color: #4ade80; margin-top: 10px; display: flex; align-items: center; gap: 6px; justify-content: center; }
1514
1575
  .ps-tryon-save-done svg { stroke: currentColor; }
1515
1576
 
@@ -1538,7 +1599,7 @@ const STYLES = `
1538
1599
  }
1539
1600
  .ps-tryon-drawer-back:hover { border-color: #bb945c; color: #bb945c; }
1540
1601
  .ps-tryon-drawer-title { font-size: 16px; font-weight: 600; color: #fff; }
1541
- .ps-tryon-drawer-list { display: flex; flex-direction: column; gap: 8px; }
1602
+ .ps-tryon-drawer-list { display: flex; flex-direction: column; gap: 10px; }
1542
1603
  .ps-tryon-drawer-empty { text-align: center; padding: 32px 16px; color: #666; font-size: 14px; }
1543
1604
 
1544
1605
  /* Profile items */
@@ -1561,22 +1622,24 @@ const STYLES = `
1561
1622
 
1562
1623
  /* History items */
1563
1624
  .ps-tryon-history-item {
1564
- display: flex; gap: 10px; padding: 12px;
1565
- border: 1px solid #333; border-radius: 12px; align-items: center; transition: all 0.2s;
1625
+ display: flex; gap: 14px; padding: 14px;
1626
+ border: 1px solid #333; border-radius: 12px; align-items: flex-start; transition: all 0.2s;
1566
1627
  }
1567
- .ps-tryon-history-item:hover { border-color: #bb945c; }
1568
- .ps-tryon-history-thumb { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
1628
+ .ps-tryon-history-item:hover { border-color: #bb945c; box-shadow: 0 4px 12px rgba(187,148,92,0.06); }
1629
+ .ps-tryon-history-images { display: flex; gap: 8px; flex-shrink: 0; }
1630
+ .ps-tryon-history-thumb { width: 64px; height: 80px; border-radius: 10px; object-fit: cover; flex-shrink: 0; }
1569
1631
  .ps-tryon-history-info { flex: 1; min-width: 0; }
1570
- .ps-tryon-history-product { font-size: 13px; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1632
+ .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; }
1571
1633
  .ps-tryon-history-meta { font-size: 11px; color: #666; margin-top: 3px; }
1572
- .ps-tryon-history-sizing { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
1634
+ .ps-tryon-history-sizing { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
1635
+ .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; }
1573
1636
  .ps-tryon-history-size-badge {
1574
- width: 28px; height: 28px; border-radius: 50%;
1637
+ flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%;
1575
1638
  display: flex; align-items: center; justify-content: center;
1576
1639
  background: linear-gradient(135deg, #bb945c, #d6ba7d);
1577
- color: #111; font-size: 11px; font-weight: 700; flex-shrink: 0;
1640
+ color: #111; font-size: 13px; font-weight: 700;
1578
1641
  }
1579
- .ps-tryon-history-result-img { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; border: 1.5px solid #bb945c; }
1642
+ .ps-tryon-history-result-img { width: 64px; height: 80px; border-radius: 10px; object-fit: cover; flex-shrink: 0; border: 2px solid #bb945c; }
1580
1643
  .ps-tryon-history-delete {
1581
1644
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
1582
1645
  border: none; background: transparent; cursor: pointer; color: #666; border-radius: 6px; transition: all 0.2s; flex-shrink: 0;
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
- {
2
- "name": "@primestyleai/tryon",
3
- "version": "3.2.2",
4
- "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
- "type": "module",
6
- "main": "dist/primestyle-tryon.js",
7
- "module": "dist/primestyle-tryon.js",
8
- "types": "dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "import": "./dist/primestyle-tryon.js",
12
- "types": "./dist/index.d.ts"
13
- },
14
- "./react": {
15
- "import": "./dist/react/index.js",
16
- "types": "./dist/react/index.d.ts"
17
- }
18
- },
19
- "files": [
20
- "dist",
21
- "logo.svg",
22
- "README.md"
23
- ],
24
- "scripts": {
25
- "dev": "vite build --watch",
26
- "build": "vite build && tsc --emitDeclarationOnly",
27
- "prepublishOnly": "npm run build"
28
- },
29
- "keywords": [
30
- "virtual-try-on",
31
- "react",
32
- "web-component",
33
- "fashion",
34
- "ai",
35
- "primestyle"
36
- ],
37
- "author": "PrimeStyle AI",
38
- "license": "MIT",
39
- "peerDependencies": {
40
- "react": ">=18.0.0",
41
- "react-dom": ">=18.0.0"
42
- },
43
- "peerDependenciesMeta": {
44
- "react": {
45
- "optional": true
46
- },
47
- "react-dom": {
48
- "optional": true
49
- }
50
- },
51
- "devDependencies": {
52
- "@types/react": "^18.3.28",
53
- "terser": "^5.31.0",
54
- "typescript": "^5.5.0",
55
- "vite": "^5.4.0"
56
- }
57
- }
1
+ {
2
+ "name": "@primestyleai/tryon",
3
+ "version": "3.4.0",
4
+ "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
+ "type": "module",
6
+ "main": "dist/primestyle-tryon.js",
7
+ "module": "dist/primestyle-tryon.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/primestyle-tryon.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./react": {
15
+ "import": "./dist/react/index.js",
16
+ "types": "./dist/react/index.d.ts"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "logo.svg",
22
+ "README.md"
23
+ ],
24
+ "scripts": {
25
+ "dev": "vite build --watch",
26
+ "build": "vite build && tsc --emitDeclarationOnly",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "virtual-try-on",
31
+ "react",
32
+ "web-component",
33
+ "fashion",
34
+ "ai",
35
+ "primestyle"
36
+ ],
37
+ "author": "PrimeStyle AI",
38
+ "license": "MIT",
39
+ "peerDependencies": {
40
+ "react": ">=18.0.0",
41
+ "react-dom": ">=18.0.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "react": {
45
+ "optional": true
46
+ },
47
+ "react-dom": {
48
+ "optional": true
49
+ }
50
+ },
51
+ "devDependencies": {
52
+ "@types/react": "^18.3.28",
53
+ "terser": "^5.31.0",
54
+ "typescript": "^5.5.0",
55
+ "vite": "^5.4.0"
56
+ }
57
+ }