@primestyleai/tryon 5.10.194 → 5.10.195

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.
@@ -11,6 +11,7 @@ export declare class PrimeStyleTryon extends HTMLElement {
11
11
  private errorMessage;
12
12
  private currentJobId;
13
13
  private productImageUrl;
14
+ private productViewReportedFor;
14
15
  private t;
15
16
  private buttonStyles;
16
17
  private modalStyles;
@@ -36,6 +37,10 @@ export declare class PrimeStyleTryon extends HTMLElement {
36
37
  private initApi;
37
38
  private cleanup;
38
39
  private emit;
40
+ private get eventProductContext();
41
+ private reportProductView;
42
+ private reportEvent;
43
+ private reportClientError;
39
44
  private get buttonText();
40
45
  private get showPoweredBy();
41
46
  private render;
@@ -58,6 +58,29 @@ export interface TryOnFeedbackInput {
58
58
  profileName?: string;
59
59
  profileAccessToken?: string;
60
60
  }
61
+ export type SdkBehaviorEventType = "PRODUCT_VIEW" | "SDK_OPENED" | "PHOTO_UPLOADED" | "SIZING_STARTED" | "SIZING_FAILED" | "SIZE_RECOMMENDATION_SHOWN" | "SIZE_RECOMMENDATION_ACCEPTED" | "ADD_TO_CART_FROM_TRYON" | "SDK_CLIENT_ERROR";
62
+ export interface SdkBehaviorEventInput {
63
+ eventType: SdkBehaviorEventType;
64
+ productId?: string;
65
+ productTitle?: string;
66
+ productUrl?: string;
67
+ jobId?: string;
68
+ recommendedSize?: string;
69
+ metadata?: Record<string, unknown>;
70
+ }
71
+ export interface SdkClientErrorInput {
72
+ message: string;
73
+ code?: string;
74
+ stack?: string;
75
+ component?: string;
76
+ view?: string;
77
+ severity?: "low" | "medium" | "high" | "critical";
78
+ productId?: string;
79
+ productTitle?: string;
80
+ productUrl?: string;
81
+ jobId?: string;
82
+ metadata?: Record<string, unknown>;
83
+ }
61
84
  export declare class ApiClient {
62
85
  private apiKey?;
63
86
  private baseUrl;
@@ -68,7 +91,13 @@ export declare class ApiClient {
68
91
  submitTryOnFeedback(input: TryOnFeedbackInput): Promise<{
69
92
  ok: true;
70
93
  }>;
71
- getStreamUrl(): string;
94
+ reportEvent(input: SdkBehaviorEventInput): Promise<{
95
+ ok: true;
96
+ }>;
97
+ reportClientError(input: SdkClientErrorInput): Promise<{
98
+ ok: true;
99
+ }>;
100
+ getStreamUrl(jobId?: string): string;
72
101
  }
73
102
  export declare function jsonHeaders(apiKey?: string): Record<string, string>;
74
103
  export declare class PrimeStyleError extends Error {
@@ -1,28 +1,28 @@
1
1
  "use client";
2
- const f = "ps_session";
2
+ const p = "ps_session";
3
3
  const A = "ps_mem_";
4
- let S = null;
5
- function E() {
4
+ let E = null;
5
+ function b() {
6
6
  try {
7
7
  return typeof window < "u" && typeof window.localStorage < "u";
8
8
  } catch {
9
9
  return !1;
10
10
  }
11
11
  }
12
- function P() {
12
+ function T() {
13
13
  if (typeof crypto < "u" && typeof crypto.randomUUID == "function")
14
14
  return crypto.randomUUID();
15
- const r = "0123456789abcdef";
15
+ const t = "0123456789abcdef";
16
16
  let e = A;
17
- for (let o = 0; o < 32; o++) e += r[Math.floor(Math.random() * 16)];
17
+ for (let o = 0; o < 32; o++) e += t[Math.floor(Math.random() * 16)];
18
18
  return e;
19
19
  }
20
- function T() {
21
- if (!E()) return S;
20
+ function I() {
21
+ if (!b()) return E;
22
22
  try {
23
- const r = window.localStorage.getItem(f);
24
- if (!r) return null;
25
- const e = JSON.parse(r);
23
+ const t = window.localStorage.getItem(p);
24
+ if (!t) return null;
25
+ const e = JSON.parse(t);
26
26
  return typeof e.id != "string" || typeof e.issuedAt != "number" ? null : {
27
27
  id: e.id,
28
28
  issuedAt: e.issuedAt,
@@ -32,43 +32,51 @@ function T() {
32
32
  return null;
33
33
  }
34
34
  }
35
- function g(r) {
36
- if (S = r, !!E())
35
+ function f(t) {
36
+ if (E = t, !!b())
37
+ try {
38
+ window.localStorage.setItem(p, JSON.stringify(t));
39
+ } catch {
40
+ }
41
+ }
42
+ function S(t) {
43
+ if (!(typeof window > "u"))
37
44
  try {
38
- window.localStorage.setItem(f, JSON.stringify(r));
45
+ const e = window.clarity;
46
+ typeof e == "function" && e("set", p, t);
39
47
  } catch {
40
48
  }
41
49
  }
42
- function p() {
43
- const r = Date.now(), e = T();
44
- if (e && r - e.lastSeenAt < 2592e6)
45
- return r - e.lastSeenAt > 5 * 60 * 1e3 && g({ ...e, lastSeenAt: r }), e.id;
46
- const o = { id: P(), issuedAt: r, lastSeenAt: r };
47
- return g(o), o.id;
50
+ function c() {
51
+ const t = Date.now(), e = I();
52
+ if (e && t - e.lastSeenAt < 2592e6)
53
+ return t - e.lastSeenAt > 5 * 60 * 1e3 && f({ ...e, lastSeenAt: t }), S(e.id), e.id;
54
+ const o = { id: T(), issuedAt: t, lastSeenAt: t };
55
+ return f(o), S(o.id), o.id;
48
56
  }
49
- function y() {
57
+ function m() {
50
58
  if (typeof navigator > "u") return null;
51
- const r = (navigator.userAgent || "").toLowerCase();
52
- return /ipad|tablet|(android(?!.*mobile))/.test(r) ? "tablet" : /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(r) ? "mobile" : "desktop";
59
+ const t = (navigator.userAgent || "").toLowerCase();
60
+ return /ipad|tablet|(android(?!.*mobile))/.test(t) ? "tablet" : /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(t) ? "mobile" : "desktop";
53
61
  }
54
- const I = "http://localhost:4000";
55
- class O {
62
+ const w = "http://localhost:4000";
63
+ class Y {
56
64
  constructor(e, o) {
57
- this.apiKey = e || void 0, this.baseUrl = (o || I).replace(/\/+$/, "");
65
+ this.apiKey = e || void 0, this.baseUrl = (o || w).replace(/\/+$/, "");
58
66
  }
59
67
  get headers() {
60
- return w(this.apiKey);
68
+ return v(this.apiKey);
61
69
  }
62
- async submitTryOn(e, o, a, s, t) {
70
+ async submitTryOn(e, o, a, s, r) {
63
71
  const i = {
64
72
  garmentImage: o,
65
73
  // Attribution fields — backend logs these into the TryOnEvent collection
66
74
  // so non-technical operators can answer "which products are being tried on
67
75
  // and by how many customers". Safe fallbacks when absent.
68
- sessionId: p(),
69
- deviceHint: y()
76
+ sessionId: c(),
77
+ deviceHint: m()
70
78
  };
71
- if (t?.modelImageId && (i.modelImageId = t.modelImageId), e && (i.modelImage = e), a && a.length > 0 && (i.fitInfo = a), s && s !== "apparel" && (i.category = s), t?.productId && (i.productId = t.productId), t?.productTitle && (i.productTitle = t.productTitle), t?.productCategory && (i.productCategory = t.productCategory), t?.productSubcategory && (i.productSubcategory = t.productSubcategory), t?.productFitType && (i.productFitType = t.productFitType), t?.productType && (i.productType = t.productType), t?.productTags?.length && (i.productTags = t.productTags), t?.productDescription && (i.productDescription = t.productDescription), t?.productMaterial && (i.productMaterial = t.productMaterial), t?.garmentDetailImage && t.garmentDetailImage !== o && (i.garmentDetailImage = t.garmentDetailImage), t?.silhouetteContext && (i.silhouetteContext = t.silhouetteContext), t?.editFromPrevious && (i.editFromPrevious = !0), a && a.length > 0)
79
+ if (r?.modelImageId && (i.modelImageId = r.modelImageId), e && (i.modelImage = e), a && a.length > 0 && (i.fitInfo = a), s && s !== "apparel" && (i.category = s), r?.productId && (i.productId = r.productId), r?.productTitle && (i.productTitle = r.productTitle), r?.productCategory && (i.productCategory = r.productCategory), r?.productSubcategory && (i.productSubcategory = r.productSubcategory), r?.productFitType && (i.productFitType = r.productFitType), r?.productType && (i.productType = r.productType), r?.productTags?.length && (i.productTags = r.productTags), r?.productDescription && (i.productDescription = r.productDescription), r?.productMaterial && (i.productMaterial = r.productMaterial), r?.garmentDetailImage && r.garmentDetailImage !== o && (i.garmentDetailImage = r.garmentDetailImage), r?.silhouetteContext && (i.silhouetteContext = r.silhouetteContext), r?.editFromPrevious && (i.editFromPrevious = !0), a && a.length > 0)
72
80
  for (const n of a) {
73
81
  const l = (n.garmentRange || "").replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((u) => !isNaN(u));
74
82
  if (l.length && n.userValue != null) {
@@ -112,8 +120,8 @@ class O {
112
120
  headers: this.headers,
113
121
  body: JSON.stringify({
114
122
  ...e,
115
- sessionId: p(),
116
- deviceHint: y()
123
+ sessionId: c(),
124
+ deviceHint: m()
117
125
  })
118
126
  });
119
127
  if (!o.ok) {
@@ -125,21 +133,61 @@ class O {
125
133
  }
126
134
  return o.json();
127
135
  }
128
- getStreamUrl() {
129
- const e = `${this.baseUrl}/api/v1/tryon/stream`;
130
- return this.apiKey ? `${e}?key=${encodeURIComponent(this.apiKey)}` : e;
136
+ async reportEvent(e) {
137
+ const o = await fetch(`${this.baseUrl}/api/v1/tryon/event`, {
138
+ method: "POST",
139
+ headers: this.headers,
140
+ keepalive: !0,
141
+ body: JSON.stringify({
142
+ ...e,
143
+ sessionId: c(),
144
+ deviceHint: m()
145
+ })
146
+ });
147
+ if (!o.ok) {
148
+ const a = await o.json().catch(() => ({}));
149
+ throw new h(
150
+ a.message || "Failed to report SDK event",
151
+ "EVENT_REPORT_FAILED"
152
+ );
153
+ }
154
+ return o.json();
155
+ }
156
+ async reportClientError(e) {
157
+ const o = await fetch(`${this.baseUrl}/api/v1/tryon/client-error`, {
158
+ method: "POST",
159
+ headers: this.headers,
160
+ keepalive: !0,
161
+ body: JSON.stringify({
162
+ ...e,
163
+ sessionId: c(),
164
+ deviceHint: m()
165
+ })
166
+ });
167
+ if (!o.ok) {
168
+ const a = await o.json().catch(() => ({}));
169
+ throw new h(
170
+ a.message || "Failed to report SDK client error",
171
+ "CLIENT_ERROR_REPORT_FAILED"
172
+ );
173
+ }
174
+ return o.json();
175
+ }
176
+ getStreamUrl(e) {
177
+ const o = e ? `/api/v1/tryon/stream/${encodeURIComponent(e)}` : "/api/v1/tryon/stream", a = `${this.baseUrl}${o}`;
178
+ return this.apiKey ? `${a}?key=${encodeURIComponent(this.apiKey)}` : a;
131
179
  }
132
180
  }
133
- function w(r) {
181
+ function v(t) {
134
182
  const e = { "Content-Type": "application/json" };
135
- return r && (e.Authorization = `Bearer ${r}`), e;
183
+ return t && (e.Authorization = `Bearer ${t}`), e;
136
184
  }
137
185
  class h extends Error {
138
186
  constructor(e, o) {
139
187
  super(e), this.name = "PrimeStyleError", this.code = o;
140
188
  }
141
189
  }
142
- class Y {
190
+ class F {
143
191
  constructor(e) {
144
192
  this.eventSource = null, this.listeners = /* @__PURE__ */ new Map(), this.reconnectTimer = null, this.reconnectAttempts = 0, this.maxReconnectAttempts = 5, this.streamUrl = e;
145
193
  }
@@ -190,10 +238,10 @@ class Y {
190
238
  this.reconnectTimer && (clearTimeout(this.reconnectTimer), this.reconnectTimer = null), this.eventSource && (this.eventSource.close(), this.eventSource = null), this.listeners.clear(), this.reconnectAttempts = 0;
191
239
  }
192
240
  }
193
- const v = 512, U = 0.65;
194
- function C(r, e = {}) {
195
- const o = e.maxDimension ?? v, a = e.quality ?? U;
196
- return new Promise((s, t) => {
241
+ const U = 512, C = 0.65;
242
+ function z(t, e = {}) {
243
+ const o = e.maxDimension ?? U, a = e.quality ?? C;
244
+ return new Promise((s, r) => {
197
245
  const i = new FileReader();
198
246
  i.onload = () => {
199
247
  const d = new Image();
@@ -202,27 +250,27 @@ function C(r, e = {}) {
202
250
  const n = document.createElement("canvas");
203
251
  let { width: l, height: u } = d;
204
252
  (l > o || u > o) && (l > u ? (u = Math.round(u * o / l), l = o) : (l = Math.round(l * o / u), u = o)), n.width = l, n.height = u;
205
- const m = n.getContext("2d");
206
- if (!m) {
207
- t(new Error("Canvas context not available"));
253
+ const y = n.getContext("2d");
254
+ if (!y) {
255
+ r(new Error("Canvas context not available"));
208
256
  return;
209
257
  }
210
- m.drawImage(d, 0, 0, l, u);
211
- const b = n.toDataURL("image/jpeg", a);
212
- s(b);
258
+ y.drawImage(d, 0, 0, l, u);
259
+ const P = n.toDataURL("image/jpeg", a);
260
+ s(P);
213
261
  } catch (n) {
214
- t(n);
262
+ r(n);
215
263
  }
216
- }, d.onerror = () => t(new Error("Failed to load image")), d.src = i.result;
217
- }, i.onerror = () => t(new Error("Failed to read file")), i.readAsDataURL(r);
264
+ }, d.onerror = () => r(new Error("Failed to load image")), d.src = i.result;
265
+ }, i.onerror = () => r(new Error("Failed to read file")), i.readAsDataURL(t);
218
266
  });
219
267
  }
220
- function F(r) {
221
- return ["image/jpeg", "image/png", "image/webp", "image/avif"].includes(r.type);
268
+ function K(t) {
269
+ return ["image/jpeg", "image/png", "image/webp", "image/avif"].includes(t.type);
222
270
  }
223
- async function V(r, e, o) {
271
+ async function V(t, e, o) {
224
272
  try {
225
- const a = typeof r == "string" ? r : await C(r, { maxDimension: 384, quality: 0.6 }), s = await fetch(`${e}/api/v1/sizing/age-check`, {
273
+ const a = typeof t == "string" ? t : await z(t, { maxDimension: 384, quality: 0.6 }), s = await fetch(`${e}/api/v1/sizing/age-check`, {
226
274
  method: "POST",
227
275
  headers: {
228
276
  "Content-Type": "application/json",
@@ -232,30 +280,30 @@ async function V(r, e, o) {
232
280
  });
233
281
  if (!s.ok)
234
282
  return { isAdult: !0, confidence: "low" };
235
- const t = await s.json();
283
+ const r = await s.json();
236
284
  return {
237
- isAdult: t?.isAdult !== !1,
285
+ isAdult: r?.isAdult !== !1,
238
286
  // anything other than explicit false → allow
239
- confidence: t?.confidence === "high" ? "high" : "low",
240
- detectedGender: t?.detectedGender === "male" || t?.detectedGender === "female" || t?.detectedGender === "unknown" ? t.detectedGender : void 0,
241
- reasoning: typeof t?.reasoning == "string" ? t.reasoning : void 0
287
+ confidence: r?.confidence === "high" ? "high" : "low",
288
+ detectedGender: r?.detectedGender === "male" || r?.detectedGender === "female" || r?.detectedGender === "unknown" ? r.detectedGender : void 0,
289
+ reasoning: typeof r?.reasoning == "string" ? r.reasoning : void 0
242
290
  };
243
291
  } catch {
244
292
  return { isAdult: !0, confidence: "low" };
245
293
  }
246
294
  }
247
- const c = {};
248
- function z(r, e) {
249
- c[r] = { ...c[r] || {}, ...e };
295
+ const g = {};
296
+ function D(t, e) {
297
+ g[t] = { ...g[t] || {}, ...e };
250
298
  }
251
- function K(r) {
252
- const e = r?.toLowerCase().split("-")[0] || "en";
253
- return (o) => e === "en" || !c[e] ? o : c[e][o] ?? o;
299
+ function j(t) {
300
+ const e = t?.toLowerCase().split("-")[0] || "en";
301
+ return (o) => e === "en" || !g[e] ? o : g[e][o] ?? o;
254
302
  }
255
- function j() {
303
+ function J() {
256
304
  return typeof navigator > "u" ? "en" : (navigator.language || navigator.userLanguage || "en").split("-")[0].toLowerCase();
257
305
  }
258
- const J = [
306
+ const q = [
259
307
  "en",
260
308
  "es",
261
309
  "fr",
@@ -266,7 +314,7 @@ const J = [
266
314
  "zh",
267
315
  "ko",
268
316
  "ar"
269
- ], q = {
317
+ ], Z = {
270
318
  en: "English",
271
319
  es: "Español",
272
320
  fr: "Français",
@@ -277,7 +325,7 @@ const J = [
277
325
  zh: "中文",
278
326
  ko: "한국어",
279
327
  ar: "العربية"
280
- }, Z = [
328
+ }, x = [
281
329
  "Virtual Try-On",
282
330
  "Find Your Size & See It On You",
283
331
  "See Your Fit",
@@ -471,7 +519,7 @@ const J = [
471
519
  // ── Photo step — profile photo preload pill ──
472
520
  "Loaded from profile",
473
521
  "Clear"
474
- ], D = {
522
+ ], G = {
475
523
  "Virtual Try-On": "Probador Virtual",
476
524
  "Find Your Size & See It On You": "Encuentra tu talla y pruébatelo",
477
525
  "See Your Fit": "Ver tu ajuste",
@@ -726,7 +774,7 @@ const J = [
726
774
  // ── Photo step — profile photo preload pill ──
727
775
  "Loaded from profile": "Cargada del perfil",
728
776
  Clear: "Borrar"
729
- }, G = {
777
+ }, B = {
730
778
  "Virtual Try-On": "Essayage Virtuel",
731
779
  "Find Your Size & See It On You": "Trouvez votre taille et essayez-le",
732
780
  "See Your Fit": "Voir votre ajustement",
@@ -981,7 +1029,7 @@ const J = [
981
1029
  // ── Photo step — profile photo preload pill ──
982
1030
  "Loaded from profile": "Chargée depuis le profil",
983
1031
  Clear: "Effacer"
984
- }, B = {
1032
+ }, N = {
985
1033
  "Virtual Try-On": "Virtuelle Anprobe",
986
1034
  "Find Your Size & See It On You": "Finden Sie Ihre Größe und probieren Sie es an",
987
1035
  "See Your Fit": "Ihre Passform ansehen",
@@ -1746,7 +1794,7 @@ const J = [
1746
1794
  // ── Photo step — profile photo preload pill ──
1747
1795
  "Loaded from profile": "Carregada do perfil",
1748
1796
  Clear: "Limpar"
1749
- }, N = {
1797
+ }, k = {
1750
1798
  "Virtual Try-On": "バーチャル試着",
1751
1799
  "Find Your Size & See It On You": "あなたのサイズを見つけて試着",
1752
1800
  "See Your Fit": "フィット感を見る",
@@ -2001,7 +2049,7 @@ const J = [
2001
2049
  // ── Photo step — profile photo preload pill ──
2002
2050
  "Loaded from profile": "プロフィールから読み込み",
2003
2051
  Clear: "クリア"
2004
- }, k = {
2052
+ }, L = {
2005
2053
  "Virtual Try-On": "虚拟试穿",
2006
2054
  "Find Your Size & See It On You": "找到你的尺码并试穿",
2007
2055
  "See Your Fit": "查看合身效果",
@@ -2256,7 +2304,7 @@ const J = [
2256
2304
  // ── Photo step — profile photo preload pill ──
2257
2305
  "Loaded from profile": "已从个人资料加载",
2258
2306
  Clear: "清除"
2259
- }, L = {
2307
+ }, R = {
2260
2308
  "Virtual Try-On": "가상 피팅",
2261
2309
  "Find Your Size & See It On You": "사이즈를 찾고 입어보세요",
2262
2310
  "See Your Fit": "핏 확인하기",
@@ -2511,7 +2559,7 @@ const J = [
2511
2559
  // ── Photo step — profile photo preload pill ──
2512
2560
  "Loaded from profile": "프로필에서 불러옴",
2513
2561
  Clear: "지우기"
2514
- }, R = {
2562
+ }, W = {
2515
2563
  "Virtual Try-On": "تجربة افتراضية",
2516
2564
  "Find Your Size & See It On You": "اعثر على مقاسك وجرّبه",
2517
2565
  "See Your Fit": "شاهد الملاءمة",
@@ -2766,34 +2814,34 @@ const J = [
2766
2814
  // ── Photo step — profile photo preload pill ──
2767
2815
  "Loaded from profile": "تم التحميل من الملف الشخصي",
2768
2816
  Clear: "مسح"
2769
- }, W = {
2770
- es: D,
2771
- fr: G,
2772
- de: B,
2817
+ }, O = {
2818
+ es: G,
2819
+ fr: B,
2820
+ de: N,
2773
2821
  it: H,
2774
2822
  pt: M,
2775
- ja: N,
2776
- zh: k,
2777
- ko: L,
2778
- ar: R
2823
+ ja: k,
2824
+ zh: L,
2825
+ ko: R,
2826
+ ar: W
2779
2827
  };
2780
- for (const [r, e] of Object.entries(W))
2781
- z(r, e);
2828
+ for (const [t, e] of Object.entries(O))
2829
+ D(t, e);
2782
2830
  export {
2783
- O as A,
2784
- q as L,
2831
+ Y as A,
2832
+ Z as L,
2785
2833
  h as P,
2786
- Y as S,
2787
- Z as T,
2788
- C as a,
2789
- J as b,
2790
- K as c,
2834
+ F as S,
2835
+ x as T,
2836
+ z as a,
2837
+ q as b,
2838
+ j as c,
2791
2839
  V as d,
2792
- j as e,
2793
- y as f,
2794
- p as g,
2795
- F as i,
2796
- w as j,
2797
- z as r
2840
+ J as e,
2841
+ m as f,
2842
+ c as g,
2843
+ K as i,
2844
+ v as j,
2845
+ D as r
2798
2846
  };
2799
- //# sourceMappingURL=index-BiotPzcm.js.map
2847
+ //# sourceMappingURL=index-D_9-KLXy.js.map