@primestyleai/tryon 5.10.195 → 5.10.196

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.
@@ -264,6 +264,8 @@ export interface PrimeStyleTryonProps {
264
264
  style?: CSSProperties;
265
265
  /** Optional portal target for modal/dropdown overlays. */
266
266
  portalContainer?: Element | DocumentFragment | null;
267
+ /** Optional Microsoft Clarity project id. Defaults to PrimeStyleAI's SDK replay project. */
268
+ clarityProjectId?: string;
267
269
  onOpen?: () => void;
268
270
  onClose?: () => void;
269
271
  onUpload?: (file: File) => void;
@@ -0,0 +1,9 @@
1
+ import type { ApiClient } from "./api-client";
2
+ interface StartSdkReplayInput {
3
+ client: ApiClient;
4
+ productId?: string;
5
+ productTitle?: string;
6
+ productUrl?: string;
7
+ }
8
+ export declare function startSdkReplay(input: StartSdkReplayInput): () => void;
9
+ export {};
@@ -9396,6 +9396,16 @@ function getDeviceHint() {
9396
9396
  return "desktop";
9397
9397
  }
9398
9398
  const DEFAULT_API_URL = "http://localhost:4000";
9399
+ function isShopifyProxyBase(baseUrl) {
9400
+ return /\/apps\/primestyle(?:\/|$)/.test(baseUrl) || /\/api\/proxy(?:\/|$)/.test(baseUrl);
9401
+ }
9402
+ function getShopDomain$2() {
9403
+ if (typeof window === "undefined") return null;
9404
+ const w2 = window;
9405
+ if (w2.Shopify?.shop) return w2.Shopify.shop;
9406
+ const hostname = window.location.hostname;
9407
+ return hostname.endsWith(".myshopify.com") ? hostname : null;
9408
+ }
9399
9409
  class ApiClient {
9400
9410
  constructor(apiKey, apiUrl) {
9401
9411
  this.apiKey = apiKey || void 0;
@@ -9547,6 +9557,26 @@ class ApiClient {
9547
9557
  }
9548
9558
  return res.json();
9549
9559
  }
9560
+ async reportReplayChunk(input) {
9561
+ const shopifyProxy = isShopifyProxyBase(this.baseUrl);
9562
+ const shopDomain = shopifyProxy ? getShopDomain$2() : null;
9563
+ const url = shopifyProxy && shopDomain ? `${this.baseUrl}/events/replay` : `${this.baseUrl}/api/v1/tryon/replay`;
9564
+ const headers = shopifyProxy && shopDomain ? jsonHeaders() : this.headers;
9565
+ const body = shopifyProxy && shopDomain ? { shopDomain, ...input } : input;
9566
+ const res = await fetch(url, {
9567
+ method: "POST",
9568
+ headers,
9569
+ body: JSON.stringify(body)
9570
+ });
9571
+ if (!res.ok) {
9572
+ const data = await res.json().catch(() => ({}));
9573
+ throw new PrimeStyleError(
9574
+ data.message || "Failed to report SDK replay",
9575
+ "REPLAY_REPORT_FAILED"
9576
+ );
9577
+ }
9578
+ return res.json();
9579
+ }
9550
9580
  getStreamUrl(jobId) {
9551
9581
  const streamPath = jobId ? `/api/v1/tryon/stream/${encodeURIComponent(jobId)}` : "/api/v1/tryon/stream";
9552
9582
  const streamUrl = `${this.baseUrl}${streamPath}`;
@@ -13212,7 +13242,7 @@ const STYLES = `
13212
13242
  }
13213
13243
 
13214
13244
  /* ── Product photo strip (single-garment, below the size card) ──
13215
- Three thumbnails per row, evenly spaced, auto-advances. Lives at
13245
+ Two thumbnails per row, evenly spaced, auto-advances. Lives at
13216
13246
  the bottom of the right panel as decoration / entertainment. */
13217
13247
  .ps-tryon-photo-strip {
13218
13248
  margin-top: 0.65vw;
@@ -13231,17 +13261,16 @@ const STYLES = `
13231
13261
  }
13232
13262
  .ps-tryon-photo-strip-row {
13233
13263
  display: grid;
13234
- grid-template-columns: repeat(3, minmax(0, 1fr));
13264
+ grid-template-columns: repeat(2, minmax(0, 1fr));
13235
13265
  gap: 0.45vw;
13236
13266
  animation: ps-tryon-photo-strip-fade 0.5s ease;
13237
13267
  }
13238
13268
  .ps-tryon-photo-strip-row.ps-count-1 {
13239
- grid-template-columns: minmax(0, calc((100% - 0.9vw) / 3));
13269
+ grid-template-columns: minmax(0, calc((100% - 0.45vw) / 2));
13240
13270
  justify-content: center;
13241
13271
  }
13242
13272
  .ps-tryon-photo-strip-row.ps-count-2 {
13243
- grid-template-columns: repeat(2, minmax(0, calc((100% - 0.9vw) / 3)));
13244
- justify-content: center;
13273
+ grid-template-columns: repeat(2, minmax(0, 1fr));
13245
13274
  }
13246
13275
  .ps-tryon-photo-strip-cell {
13247
13276
  position: relative;
@@ -13302,13 +13331,14 @@ const STYLES = `
13302
13331
  gap: 8px;
13303
13332
  }
13304
13333
  .ps-tryon-photo-strip-row {
13305
- grid-template-columns: repeat(3, minmax(0, 1fr));
13334
+ grid-template-columns: repeat(2, minmax(0, 1fr));
13306
13335
  }
13307
13336
  .ps-tryon-photo-strip-row.ps-count-1 {
13308
- grid-template-columns: minmax(0, calc((100% - 16px) / 3));
13337
+ grid-template-columns: minmax(0, calc((100% - 8px) / 2));
13338
+ justify-content: center;
13309
13339
  }
13310
13340
  .ps-tryon-photo-strip-row.ps-count-2 {
13311
- grid-template-columns: repeat(2, minmax(0, calc((100% - 16px) / 3)));
13341
+ grid-template-columns: repeat(2, minmax(0, 1fr));
13312
13342
  }
13313
13343
  .ps-tryon-photo-strip-cell {
13314
13344
  aspect-ratio: 1 / 1; border-radius: 12px;
@@ -22553,16 +22583,16 @@ const STYLES = `
22553
22583
  }
22554
22584
  .ps-tryon-photo-strip-row {
22555
22585
  display: grid !important;
22556
- grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
22586
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
22557
22587
  gap: 8px !important;
22558
22588
  }
22559
22589
  .ps-tryon-photo-strip-row.ps-count-1 {
22560
- grid-template-columns: minmax(0, calc((100% - 16px) / 3)) !important;
22590
+ grid-template-columns: minmax(0, calc((100% - 8px) / 2)) !important;
22561
22591
  justify-content: center !important;
22562
22592
  }
22563
22593
  .ps-tryon-photo-strip-row.ps-count-2 {
22564
- grid-template-columns: repeat(2, minmax(0, calc((100% - 16px) / 3))) !important;
22565
- justify-content: center !important;
22594
+ grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
22595
+ justify-content: stretch !important;
22566
22596
  }
22567
22597
  .ps-tryon-photo-strip-cell {
22568
22598
  aspect-ratio: 1 / 1 !important;
@@ -23236,6 +23266,232 @@ const STYLES = `
23236
23266
  }
23237
23267
  }
23238
23268
  `;
23269
+ const RRWEB_SCRIPT_URL = "https://cdn.jsdelivr.net/npm/rrweb@2.0.1/dist/rrweb.min.js";
23270
+ const CHUNK_SIZE = 20;
23271
+ const FLUSH_MS = 2500;
23272
+ const MAX_EVENT_JSON_BYTES = 5e6;
23273
+ const MAX_CHUNK_JSON_BYTES = 6e6;
23274
+ let globalSequence = 0;
23275
+ let rrwebLoadPromise = null;
23276
+ function estimateJsonBytes(value) {
23277
+ try {
23278
+ return JSON.stringify(value).length;
23279
+ } catch {
23280
+ return MAX_EVENT_JSON_BYTES + 1;
23281
+ }
23282
+ }
23283
+ function canRecord() {
23284
+ return typeof window !== "undefined" && typeof document !== "undefined";
23285
+ }
23286
+ function getLoadedRrwebRecord() {
23287
+ const rrweb = window.rrweb;
23288
+ return typeof rrweb?.record === "function" ? rrweb.record : null;
23289
+ }
23290
+ function loadRrwebRecord() {
23291
+ const loaded = getLoadedRrwebRecord();
23292
+ if (loaded) return Promise.resolve(loaded);
23293
+ if (rrwebLoadPromise) return rrwebLoadPromise;
23294
+ rrwebLoadPromise = new Promise((resolve) => {
23295
+ const script = document.createElement("script");
23296
+ script.src = RRWEB_SCRIPT_URL;
23297
+ script.async = true;
23298
+ script.crossOrigin = "anonymous";
23299
+ script.onload = () => resolve(getLoadedRrwebRecord());
23300
+ script.onerror = () => resolve(null);
23301
+ document.head.appendChild(script);
23302
+ });
23303
+ return rrwebLoadPromise;
23304
+ }
23305
+ function startSdkReplay(input) {
23306
+ if (!canRecord()) return () => {
23307
+ };
23308
+ const sessionId = getOrCreateSessionId();
23309
+ const queue = [];
23310
+ let stopped = false;
23311
+ let timer = null;
23312
+ let stopRecord;
23313
+ const flush = (all = false) => {
23314
+ if (timer) {
23315
+ window.clearTimeout(timer);
23316
+ timer = null;
23317
+ }
23318
+ if (!queue.length) return;
23319
+ do {
23320
+ const events = [];
23321
+ let chunkBytes = 0;
23322
+ while (queue.length && events.length < CHUNK_SIZE) {
23323
+ const event = queue[0];
23324
+ const eventBytes = estimateJsonBytes(event);
23325
+ if (events.length && chunkBytes + eventBytes > MAX_CHUNK_JSON_BYTES) break;
23326
+ events.push(queue.shift());
23327
+ chunkBytes += eventBytes;
23328
+ if (chunkBytes >= MAX_CHUNK_JSON_BYTES) break;
23329
+ }
23330
+ if (!events.length) events.push(queue.shift());
23331
+ const sequence = globalSequence++;
23332
+ void input.client.reportReplayChunk({
23333
+ sessionId,
23334
+ sequence,
23335
+ events,
23336
+ productId: input.productId,
23337
+ productTitle: input.productTitle,
23338
+ productUrl: input.productUrl,
23339
+ deviceHint: getDeviceHint()
23340
+ }).catch((error) => {
23341
+ console.warn("[ps-sdk:replay] failed to upload replay chunk", error);
23342
+ });
23343
+ } while (all && queue.length);
23344
+ if (queue.length) scheduleFlush(0);
23345
+ };
23346
+ const scheduleFlush = (delay = FLUSH_MS) => {
23347
+ if (stopped || timer) return;
23348
+ timer = window.setTimeout(flush, delay);
23349
+ };
23350
+ void loadRrwebRecord().then((record) => {
23351
+ if (!record || stopped) return;
23352
+ stopRecord = record({
23353
+ emit(event) {
23354
+ if (stopped) return;
23355
+ if (estimateJsonBytes(event) > MAX_EVENT_JSON_BYTES) return;
23356
+ queue.push(event);
23357
+ if (queue.length >= CHUNK_SIZE) flush();
23358
+ else scheduleFlush();
23359
+ },
23360
+ checkoutEveryNms: 1e4,
23361
+ maskAllInputs: false,
23362
+ maskInputOptions: {
23363
+ password: true,
23364
+ email: true,
23365
+ tel: true
23366
+ },
23367
+ blockClass: "ps-replay-block",
23368
+ blockSelector: "body > *:not([data-ps-tryon-portal]):not(.ps-tryon-root)",
23369
+ inlineStylesheet: true,
23370
+ inlineImages: true,
23371
+ collectFonts: false,
23372
+ recordCanvas: false,
23373
+ recordCrossOriginIframes: false,
23374
+ slimDOMOptions: {
23375
+ script: true,
23376
+ comment: true,
23377
+ headFavicon: true,
23378
+ headMetaDescKeywords: true,
23379
+ headMetaSocial: true,
23380
+ headMetaRobots: true,
23381
+ headMetaHttpEquiv: true,
23382
+ headMetaAuthorship: true,
23383
+ headMetaVerification: true
23384
+ },
23385
+ sampling: {
23386
+ mousemove: 80,
23387
+ mouseInteraction: true,
23388
+ scroll: 150,
23389
+ media: 800,
23390
+ input: "last"
23391
+ },
23392
+ errorHandler(error) {
23393
+ console.warn("[ps-sdk:replay] recorder error", error);
23394
+ }
23395
+ });
23396
+ });
23397
+ return () => {
23398
+ stopped = true;
23399
+ if (timer) {
23400
+ window.clearTimeout(timer);
23401
+ timer = null;
23402
+ }
23403
+ try {
23404
+ stopRecord?.();
23405
+ } catch {
23406
+ }
23407
+ flush(true);
23408
+ };
23409
+ }
23410
+ var define_process_env_default = {};
23411
+ const SCRIPT_ID_PREFIX = "ps-clarity-script";
23412
+ const DEFAULT_PROJECT_ID = "wwb75cfm2z";
23413
+ let initializedProjectId = null;
23414
+ function cleanProjectId(value) {
23415
+ const trimmed = String(value || "").trim();
23416
+ if (!trimmed) return null;
23417
+ return /^[a-z0-9]+$/i.test(trimmed) ? trimmed : null;
23418
+ }
23419
+ function readEnvProjectId() {
23420
+ let id2 = "";
23421
+ try {
23422
+ id2 = define_process_env_default.NEXT_PUBLIC_PRIMESTYLE_CLARITY_PROJECT_ID ?? "";
23423
+ } catch {
23424
+ }
23425
+ if (!id2) {
23426
+ try {
23427
+ id2 = define_process_env_default.NEXT_PUBLIC_CLARITY_PROJECT_ID ?? "";
23428
+ } catch {
23429
+ }
23430
+ }
23431
+ return cleanProjectId(id2);
23432
+ }
23433
+ function readWindowProjectId() {
23434
+ if (typeof window === "undefined") return null;
23435
+ const w2 = window;
23436
+ return cleanProjectId(w2.PrimeStyleAIClarityProjectId || w2.PRIMESTYLE_CLARITY_PROJECT_ID);
23437
+ }
23438
+ function resolveSdkClarityProjectId(projectId) {
23439
+ return cleanProjectId(projectId) || readWindowProjectId() || readEnvProjectId() || DEFAULT_PROJECT_ID;
23440
+ }
23441
+ function getClarity() {
23442
+ if (typeof window === "undefined") return null;
23443
+ const clarity = window.clarity;
23444
+ return typeof clarity === "function" ? clarity : null;
23445
+ }
23446
+ function installClarity(projectId) {
23447
+ if (typeof window === "undefined" || typeof document === "undefined") return null;
23448
+ const scriptId = `${SCRIPT_ID_PREFIX}-${projectId}`;
23449
+ if (!document.getElementById(scriptId)) {
23450
+ ((c, l2, a, r2, i) => {
23451
+ c[a] = c[a] || function(...args) {
23452
+ const queued = c[a];
23453
+ (queued.q = queued.q || []).push(args);
23454
+ };
23455
+ const script = l2.createElement(r2);
23456
+ const firstScript = l2.getElementsByTagName(r2)[0];
23457
+ script.id = scriptId;
23458
+ script.async = true;
23459
+ script.src = "https://www.clarity.ms/tag/" + i;
23460
+ firstScript?.parentNode?.insertBefore(script, firstScript);
23461
+ })(window, document, "clarity", "script", projectId);
23462
+ }
23463
+ return getClarity();
23464
+ }
23465
+ function setTag(key, value) {
23466
+ const clarity = getClarity();
23467
+ if (!clarity || value === void 0 || value === null || value === "") return;
23468
+ try {
23469
+ clarity("set", key, String(value).slice(0, 512));
23470
+ } catch {
23471
+ }
23472
+ }
23473
+ function tagSdkClaritySession(input = {}) {
23474
+ const sessionId = getOrCreateSessionId();
23475
+ setTag("ps_session", sessionId);
23476
+ setTag("ps_sdk_session", sessionId);
23477
+ setTag("ps_product_id", input.productId || void 0);
23478
+ setTag("ps_product_title", input.productTitle || void 0);
23479
+ setTag("ps_product_url", input.productUrl || void 0);
23480
+ setTag("ps_sdk_view", input.view || void 0);
23481
+ setTag("ps_tryon_job_id", input.jobId || void 0);
23482
+ setTag("ps_source", input.source || void 0);
23483
+ }
23484
+ function startSdkClarity(input = {}) {
23485
+ if (typeof window === "undefined" || typeof document === "undefined") return false;
23486
+ const projectId = resolveSdkClarityProjectId(input.projectId);
23487
+ {
23488
+ initializedProjectId = initializedProjectId || projectId;
23489
+ installClarity(initializedProjectId);
23490
+ }
23491
+ if (!getClarity()) return false;
23492
+ tagSdkClaritySession(input);
23493
+ return true;
23494
+ }
23239
23495
  function CameraIcon$1({ size = 18 }) {
23240
23496
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
23241
23497
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
@@ -24422,8 +24678,8 @@ function MultiSectionMobile({
24422
24678
  sizeGuide ? null : null
24423
24679
  ] });
24424
24680
  }
24425
- const PER_SLIDE = 3;
24426
- const CYCLE_MS = 4e3;
24681
+ const PER_SLIDE = 2;
24682
+ const CYCLE_MS = 2500;
24427
24683
  function ProductPhotoCarouselCard({
24428
24684
  photos,
24429
24685
  items,
@@ -34727,6 +34983,7 @@ function PrimeStyleTryonInner({
34727
34983
  continueShoppingLabel,
34728
34984
  backToProductPageLabel,
34729
34985
  sizeGuideData,
34986
+ clarityProjectId,
34730
34987
  initialView,
34731
34988
  initialBodyProfileStep
34732
34989
  }) {
@@ -35135,6 +35392,30 @@ function PrimeStyleTryonInner({
35135
35392
  if (pollingRef.current) clearInterval(pollingRef.current);
35136
35393
  };
35137
35394
  }, [apiUrl]);
35395
+ const sdkReplayOpen = view !== "idle";
35396
+ reactExports.useEffect(() => {
35397
+ if (!sdkReplayOpen) return void 0;
35398
+ const client = apiRef.current;
35399
+ if (!client) return void 0;
35400
+ return startSdkReplay({
35401
+ client,
35402
+ productId: effectiveProductId,
35403
+ productTitle: restoredProductTitle || productTitle,
35404
+ productUrl: restoredProductUrl || effectiveProductUrl
35405
+ });
35406
+ }, [sdkReplayOpen, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl]);
35407
+ reactExports.useEffect(() => {
35408
+ if (!sdkReplayOpen) return;
35409
+ startSdkClarity({
35410
+ projectId: clarityProjectId,
35411
+ productId: effectiveProductId,
35412
+ productTitle: restoredProductTitle || productTitle,
35413
+ productUrl: restoredProductUrl || effectiveProductUrl,
35414
+ view,
35415
+ jobId: currentTryOnJobIdRef.current,
35416
+ source: shouldUseShopifyCartAttribution(apiUrl) ? "shopify-sdk" : "sdk"
35417
+ });
35418
+ }, [apiUrl, clarityProjectId, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl, sdkReplayOpen, view]);
35138
35419
  const reportSdkEvent = reactExports.useCallback((eventType, input = {}) => {
35139
35420
  if (shouldUseShopifyCartAttribution(apiUrl)) return;
35140
35421
  const client = apiRef.current;
@@ -36814,6 +37095,14 @@ function PrimeStyleTryonInner({
36814
37095
  }
36815
37096
  );
36816
37097
  currentTryOnJobIdRef.current = response.jobId;
37098
+ tagSdkClaritySession({
37099
+ productId: effectiveProductId,
37100
+ productTitle: restoredProductTitle || productTitle,
37101
+ productUrl: restoredProductUrl || effectiveProductUrl,
37102
+ view,
37103
+ jobId: response.jobId,
37104
+ source: shouldUseShopifyCartAttribution(apiUrl) ? "shopify-sdk" : "sdk"
37105
+ });
36817
37106
  if (response.modelImageId) modelImageIdRef.current = response.modelImageId;
36818
37107
  onProcessing?.(response.jobId);
36819
37108
  const usePollingOnly = shouldUseShopifyCartAttribution(apiUrl);
@@ -36859,7 +37148,7 @@ function PrimeStyleTryonInner({
36859
37148
  setView("error");
36860
37149
  onError?.({ message, code });
36861
37150
  }
36862
- }, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, garmentDetailImage, productTitle, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate, reportSdkClientError, t2, view]);
37151
+ }, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, garmentDetailImage, effectiveProductId, effectiveProductUrl, productTitle, restoredProductTitle, restoredProductUrl, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate, reportSdkClientError, t2, view]);
36863
37152
  reactExports.useEffect(() => {
36864
37153
  if (view !== "size-result") {
36865
37154
  autoTryOnFiredRef.current = false;
@@ -37957,7 +38246,7 @@ function PrimeStyleTryonInner({
37957
38246
  return null;
37958
38247
  }
37959
38248
  }
37960
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { visibility: cssReady ? "visible" : "hidden", ...cssVars, ...style }, suppressHydrationWarning: true, "data-ps-tryon": true, children: [
38249
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { visibility: cssReady ? "visible" : "hidden", ...cssVars, ...style }, suppressHydrationWarning: true, "data-ps-tryon": true, "data-clarity-unmask": "true", children: [
37961
38250
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
37962
38251
  "button",
37963
38252
  {
@@ -37971,7 +38260,7 @@ function PrimeStyleTryonInner({
37971
38260
  }
37972
38261
  ),
37973
38262
  view !== "idle" && resolvedPortalContainer && reactDomExports.createPortal(
37974
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" || view === "profiles" || view === "no-chart" || view === "photo-guide" || view === "error" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
38263
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, "data-clarity-unmask": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" || view === "profiles" || view === "no-chart" || view === "photo-guide" || view === "error" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), "data-clarity-unmask": "true", children: [
37975
38264
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: cx("ps-tryon-header ps-tryon-header-minimal", cn.header), children: [
37976
38265
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
37977
38266
  "a",
@@ -38129,7 +38418,7 @@ function PrimeStyleTryonInner({
38129
38418
  resolvedPortalContainer
38130
38419
  ),
38131
38420
  view !== "body-profile" && view !== "processing" && !(view === "size-result" && sizeGuide?.sections && Object.keys(sizeGuide.sections).length > 1) && /* @__PURE__ */ jsxRuntimeExports.jsx(Stepper, { view, stepIndex }),
38132
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
38421
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, "data-clarity-unmask": "true", children: [
38133
38422
  showBackButton && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-back-btn", onClick: handleBack, children: [
38134
38423
  /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
38135
38424
  /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "17", y1: "6", x2: "1", y2: "6" }),
@@ -38777,7 +39066,8 @@ function buildPropsFromDataAttrs(data) {
38777
39066
  sizingCountry: data.sizingCountry,
38778
39067
  showPoweredBy: data.showPoweredBy === "true",
38779
39068
  buttonStyles: parseJsonAttr(data.buttonStyles, void 0),
38780
- modalStyles: parseJsonAttr(data.modalStyles, void 0)
39069
+ modalStyles: parseJsonAttr(data.modalStyles, void 0),
39070
+ clarityProjectId: data.clarityProjectId
38781
39071
  };
38782
39072
  console.log(`${TAG} built props`, props);
38783
39073
  return props;
package/dist/types.d.ts CHANGED
@@ -12,6 +12,8 @@ export interface PrimeStyleConfig {
12
12
  locale?: string;
13
13
  /** Show "Powered by PrimeStyle" badge (defaults to true) */
14
14
  showPoweredBy?: boolean;
15
+ /** Microsoft Clarity project id for SDK session replay. Defaults to PrimeStyleAI's SDK replay project. */
16
+ clarityProjectId?: string;
15
17
  }
16
18
  /** Button customization options */
17
19
  export interface ButtonStyles {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "5.10.195",
3
+ "version": "5.10.196",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",