@primestyleai/tryon 5.10.178 → 5.10.180

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.
@@ -10225,6 +10225,52 @@ function parseNum(s) {
10225
10225
  const n2 = parseFloat(s.replace(/[^\d.]/g, ""));
10226
10226
  return isNaN(n2) ? 0 : n2;
10227
10227
  }
10228
+ function normalizeUnit(unit) {
10229
+ const u2 = (unit || "").toLowerCase();
10230
+ if (u2 === "in" || u2 === "inch" || u2 === "inches") return "in";
10231
+ if (u2 === "cm") return "cm";
10232
+ if (u2 === "mm") return "mm";
10233
+ return null;
10234
+ }
10235
+ function detectUnitFromText(text) {
10236
+ const t2 = String(text || "");
10237
+ if (/\bmm\b/i.test(t2)) return "mm";
10238
+ if (/\bcm\b/i.test(t2)) return "cm";
10239
+ if (/\bin\b|inch|inches|["”]/i.test(t2)) return "in";
10240
+ return null;
10241
+ }
10242
+ function convertValue(value, from, to) {
10243
+ if (from === to) return value;
10244
+ const inMm = from === "mm" ? value : from === "cm" ? value * 10 : value * 25.4;
10245
+ if (to === "mm") return inMm;
10246
+ if (to === "cm") return inMm / 10;
10247
+ return inMm / 25.4;
10248
+ }
10249
+ function formatUnitNumber(value, unit) {
10250
+ const precision = unit === "mm" ? 0 : 1;
10251
+ const rounded = Number(value.toFixed(precision));
10252
+ return Number.isInteger(rounded) ? String(rounded) : String(rounded);
10253
+ }
10254
+ function convertNumberTextToUnit(text, from, to) {
10255
+ if (from === to) return text;
10256
+ const converted = text.replace(/\s*(cm|mm|in|inch|inches)\b/ig, "").replace(/(\d+(?:\.\d+)?)/g, (raw) => formatUnitNumber(convertValue(Number(raw), from, to), to)).trim();
10257
+ return converted ? `${converted} ${to}` : text;
10258
+ }
10259
+ function normalizeMeasurementValueText(measurement, value, targetUnit) {
10260
+ if (isUnitlessShoeSizeMeasurement(measurement)) return formatUserMeasurementValue(measurement, value);
10261
+ const sourceUnit = detectUnitFromText(value);
10262
+ if (sourceUnit) return convertNumberTextToUnit(value, sourceUnit, targetUnit);
10263
+ const trimmed = String(value || "").trim();
10264
+ return /\d/.test(trimmed) ? `${trimmed} ${targetUnit}` : trimmed;
10265
+ }
10266
+ function normalizeRangeText(range, targetUnit, header) {
10267
+ const sourceUnit = detectUnitFromText(range) || detectUnitFromText(header);
10268
+ if (!sourceUnit) return String(range || "").trim();
10269
+ return convertNumberTextToUnit(range, sourceUnit, targetUnit);
10270
+ }
10271
+ function promptHeaderLabel(header) {
10272
+ return String(header || "").replace(/\s*\((?:cm|mm|in|inch|inches)\)\s*/ig, "").trim();
10273
+ }
10228
10274
  function isUnitlessShoeSizeMeasurement(measurement) {
10229
10275
  const normalized = measurement.toLowerCase().replace(/\s*\(.*?\)\s*/g, " ").trim();
10230
10276
  if (/foot\s*length|length\s*\(cm\)|cm\s*\/\s*jp|mondo|mondopoint/i.test(normalized)) return false;
@@ -10235,11 +10281,15 @@ function formatUserMeasurementValue(measurement, value) {
10235
10281
  return value.replace(/\s*(cm|mm|in|inch|inches)\b/ig, "").trim();
10236
10282
  }
10237
10283
  function computeFit(userValue, chartRange, unit) {
10238
- const { min: rMin, max: rMax } = parseRange(chartRange);
10284
+ const targetUnit = normalizeUnit(unit) || detectUnitFromText(chartRange) || "in";
10285
+ const chartUnit = detectUnitFromText(chartRange);
10286
+ const parsed = parseRange(chartRange);
10287
+ const rMin = chartUnit && chartUnit !== targetUnit ? convertValue(parsed.min, chartUnit, targetUnit) : parsed.min;
10288
+ const rMax = chartUnit && chartUnit !== targetUnit ? convertValue(parsed.max, chartUnit, targetUnit) : parsed.max;
10239
10289
  if (rMin === 0 && rMax === 0) return "good";
10240
- const perfectTol = unit === "cm" ? 1.27 : unit === "mm" ? 12.7 : 0.5;
10241
- const aBitTol = unit === "cm" ? 2.54 : unit === "mm" ? 25.4 : 1;
10242
- const tooFarTol = unit === "cm" ? 5.08 : unit === "mm" ? 50.8 : 2;
10290
+ const perfectTol = targetUnit === "cm" ? 1.27 : targetUnit === "mm" ? 12.7 : 0.5;
10291
+ const aBitTol = targetUnit === "cm" ? 2.54 : targetUnit === "mm" ? 25.4 : 1;
10292
+ const tooFarTol = targetUnit === "cm" ? 5.08 : targetUnit === "mm" ? 50.8 : 2;
10243
10293
  const inRange = userValue >= rMin && userValue <= rMax;
10244
10294
  const overEdge = inRange ? 0 : userValue > rMax ? userValue - rMax : rMin - userValue;
10245
10295
  if (inRange || overEdge <= perfectTol) return "good";
@@ -10262,14 +10312,17 @@ const SKIP_AREAS_FOR_FIT = /* @__PURE__ */ new Set([
10262
10312
  ]);
10263
10313
  function buildFitInfo(matchDetails, poseLines, unit) {
10264
10314
  return matchDetails.filter((m2) => !SKIP_AREAS_FOR_FIT.has(m2.measurement.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim())).map((m2) => {
10265
- const userNum = parseNum(m2.userValue);
10266
- const fit = computeFit(userNum, m2.chartRange, unit);
10315
+ const targetUnit = normalizeUnit(unit) || detectUnitFromText(m2.userValue) || detectUnitFromText(m2.chartRange) || "in";
10316
+ const userValueText = normalizeMeasurementValueText(m2.measurement, m2.userValue, targetUnit);
10317
+ const chartRangeText = normalizeRangeText(m2.chartRange, targetUnit);
10318
+ const userNum = parseNum(userValueText);
10319
+ const fit = computeFit(userNum, chartRangeText, targetUnit);
10267
10320
  const info = {
10268
10321
  area: m2.measurement,
10269
10322
  section: m2.section || void 0,
10270
10323
  fit,
10271
10324
  userValue: userNum || void 0,
10272
- garmentRange: m2.chartRange || void 0
10325
+ garmentRange: chartRangeText || void 0
10273
10326
  };
10274
10327
  if (poseLines) {
10275
10328
  const poseKey = AREA_TO_POSE_KEY[m2.measurement.toLowerCase()];
@@ -10286,6 +10339,7 @@ function buildFitInfo(matchDetails, poseLines, unit) {
10286
10339
  function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, userHeight, userWeight) {
10287
10340
  if (!sizingResult && !sizeGuide && !userHeight && !userWeight) return void 0;
10288
10341
  const out = {};
10342
+ const promptUnit = normalizeUnit(sizingResult?.unit) || detectUnitFromText(sizingResult?.matchDetails?.[0]?.userValue) || detectUnitFromText(Object.values(sizingResult?.sections || {})[0]?.matchDetails?.[0]?.userValue) || "in";
10289
10343
  const baseSize = (selectedSizeOverride || sizingResult?.recommendedSize || "").toString().trim();
10290
10344
  if (userHeight) out.userHeight = userHeight;
10291
10345
  if (userWeight) out.userWeight = userWeight;
@@ -10311,7 +10365,7 @@ function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, u
10311
10365
  chartRowFit = vStr;
10312
10366
  continue;
10313
10367
  }
10314
- if (vStr) bits.push(`${h} ${vStr}`);
10368
+ if (vStr) bits.push(`${promptHeaderLabel(h) || h} ${normalizeRangeText(vStr, promptUnit, h)}`);
10315
10369
  if (chartRowLength == null && /^length\b|inseam/i.test(h) && vStr) {
10316
10370
  chartRowLength = vStr;
10317
10371
  }
@@ -10360,7 +10414,7 @@ function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, u
10360
10414
  const h = (secChart.headers[i] || "").trim();
10361
10415
  const baseHeader = h.replace(/\s*\(.*?\)\s*/g, "").trim();
10362
10416
  if (vStr && !/^(size|standard|country|fit|silhouette|category|body[\s_]?type|eu|uk|us|it|jp|cn|kr|ru|br|au)$/i.test(baseHeader)) {
10363
- bits.push(`${h} ${vStr}`);
10417
+ bits.push(`${promptHeaderLabel(h) || h} ${normalizeRangeText(vStr, promptUnit, h)}`);
10364
10418
  }
10365
10419
  }
10366
10420
  if (bits.length) measurementParts.push(`${cleanSec} ${secSize}: ${bits.join(", ")}`);
@@ -10370,29 +10424,33 @@ function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, u
10370
10424
  if (labelParts.length) out.recommendedSize = labelParts.join(", ");
10371
10425
  if (measurementParts.length) out.recommendedSizeMeasurements = measurementParts.join(" | ");
10372
10426
  }
10373
- const seen = /* @__PURE__ */ new Set();
10427
+ const seenUserMeasurements = /* @__PURE__ */ new Set();
10428
+ const seenSelectedMeasurements = /* @__PURE__ */ new Set();
10374
10429
  const userLines = [];
10375
- const push = (md2) => {
10430
+ const selectedMeasurementLines = [];
10431
+ const push = (md2, sectionName) => {
10376
10432
  if (!md2) return;
10377
10433
  for (const m2 of md2) {
10378
- const k2 = m2.measurement.toLowerCase();
10379
- if (seen.has(k2)) continue;
10380
- seen.add(k2);
10381
- if (m2.userValue) userLines.push(`${m2.measurement} ${formatUserMeasurementValue(m2.measurement, m2.userValue)}`);
10434
+ const normalizedMeasurement = m2.measurement.toLowerCase().replace(/\s*\(.*?\)\s*/g, "").trim();
10435
+ if (SKIP_AREAS_FOR_FIT.has(normalizedMeasurement)) continue;
10436
+ const selectedKey = sectionName ? `${sectionName.toLowerCase()}:${normalizedMeasurement}` : normalizedMeasurement;
10437
+ if (m2.userValue && !seenUserMeasurements.has(normalizedMeasurement)) {
10438
+ seenUserMeasurements.add(normalizedMeasurement);
10439
+ userLines.push(`${m2.measurement} ${normalizeMeasurementValueText(m2.measurement, m2.userValue, promptUnit)}`);
10440
+ }
10441
+ if (m2.chartRange && !seenSelectedMeasurements.has(selectedKey)) {
10442
+ seenSelectedMeasurements.add(selectedKey);
10443
+ const prefix = sectionName ? `${sectionName} ${m2.measurement}` : m2.measurement;
10444
+ selectedMeasurementLines.push(`${prefix} ${normalizeRangeText(m2.chartRange, promptUnit)}`);
10445
+ }
10382
10446
  }
10383
10447
  };
10384
10448
  push(sizingResult?.matchDetails);
10385
10449
  if (sizingResult?.sections) {
10386
- for (const sec of Object.values(sizingResult.sections)) push(sec.matchDetails);
10450
+ for (const [secName, sec] of Object.entries(sizingResult.sections)) push(sec.matchDetails, secName);
10387
10451
  }
10388
10452
  if (userLines.length) out.userMeasurementsText = userLines.join(", ");
10389
- if (sizeGuide?.headers?.length && sizeGuide.rows?.length) {
10390
- const hdrs = sizeGuide.headers;
10391
- const rowStrings = sizeGuide.rows.slice(0, 20).map(
10392
- (row) => hdrs.map((h, i) => `${h} ${row[i] ?? "—"}`).join(", ")
10393
- );
10394
- out.sizeChartSummary = rowStrings.join(" | ");
10395
- }
10453
+ if (selectedMeasurementLines.length) out.recommendedSizeMeasurements = selectedMeasurementLines.join(", ");
10396
10454
  return Object.keys(out).length ? out : void 0;
10397
10455
  }
10398
10456
  const FALLBACK_FIELDS_FEMALE = [
@@ -11346,6 +11404,14 @@ function setStoredProfileSession(session) {
11346
11404
  } catch {
11347
11405
  }
11348
11406
  }
11407
+ function clearStoredProfileSession() {
11408
+ const storage = readStorage();
11409
+ if (!storage) return;
11410
+ try {
11411
+ storage.removeItem(SESSION_KEY);
11412
+ } catch {
11413
+ }
11414
+ }
11349
11415
  function startSocialProfileLogin(provider, apiUrl) {
11350
11416
  if (typeof window === "undefined") {
11351
11417
  return Promise.reject(new Error("Social login must run in the browser."));
@@ -11627,7 +11693,7 @@ function productFitTypeToMeasurementType(fitType) {
11627
11693
  }
11628
11694
  return "body";
11629
11695
  }
11630
- const STYLES$1 = `
11696
+ const STYLES = `
11631
11697
  /* Variable defaults must live on BOTH the root (for the trigger button)
11632
11698
  and the overlay (which is React-portaled to <body> and therefore not
11633
11699
  a descendant of .ps-tryon-root, so the cascade is broken). Without
@@ -11694,6 +11760,7 @@ const STYLES$1 = `
11694
11760
  position: fixed; inset: 0; background: var(--ps-modal-overlay, rgba(0,0,0,0.6));
11695
11761
  display: flex; align-items: center; justify-content: center;
11696
11762
  z-index: 2147483647;
11763
+ pointer-events: auto;
11697
11764
  isolation: isolate;
11698
11765
  contain: layout style;
11699
11766
  padding: 0.83vw;
@@ -12183,11 +12250,20 @@ const STYLES$1 = `
12183
12250
  min-height: 0;
12184
12251
  }
12185
12252
  .ps-tryon-v2-result-panel .ps-tryon-photo-strip {
12186
- flex: 0 1 auto;
12253
+ flex: 0 0 auto;
12187
12254
  min-height: 0;
12255
+ margin-top: clamp(10px, 0.75vw, 14px);
12256
+ margin-bottom: clamp(8px, 0.7vw, 12px);
12188
12257
  }
12189
12258
  .ps-tryon-v2-result-panel .ps-tryon-sr-card-v2 {
12190
- min-height: 10.5vw;
12259
+ min-height: clamp(140px, 10.5vw, 165px);
12260
+ }
12261
+ .ps-tryon-v2-result-panel .ps-tryon-sr-card-v2.ps-full {
12262
+ min-height: clamp(140px, 10.5vw, 165px);
12263
+ }
12264
+ .ps-tryon-v2-result-panel .ps-tryon-photo-strip-cell {
12265
+ aspect-ratio: 1 / 1;
12266
+ height: auto;
12191
12267
  }
12192
12268
  .ps-tryon-v2-result-actions {
12193
12269
  display: flex;
@@ -12682,9 +12758,12 @@ const STYLES$1 = `
12682
12758
  .ps-tryon-photo-strip-row {
12683
12759
  display: grid;
12684
12760
  grid-template-columns: repeat(3, 1fr);
12685
- gap: 0.55vw;
12761
+ gap: 0.45vw;
12686
12762
  animation: ps-tryon-photo-strip-fade 0.5s ease;
12687
12763
  }
12764
+ .ps-tryon-photo-strip-row.ps-count-1 .ps-tryon-photo-strip-cell {
12765
+ grid-column: 2;
12766
+ }
12688
12767
  .ps-tryon-photo-strip-cell {
12689
12768
  position: relative;
12690
12769
  display: block;
@@ -12707,7 +12786,7 @@ const STYLES$1 = `
12707
12786
  object-position: center center;
12708
12787
  padding: 0;
12709
12788
  box-sizing: border-box;
12710
- transform: scale(0.94);
12789
+ transform: none;
12711
12790
  transform-origin: center center;
12712
12791
  user-select: none;
12713
12792
  pointer-events: none;
@@ -12748,7 +12827,7 @@ const STYLES$1 = `
12748
12827
  }
12749
12828
  .ps-tryon-photo-strip-cell > img {
12750
12829
  object-position: center center;
12751
- transform: scale(0.94);
12830
+ transform: none;
12752
12831
  }
12753
12832
  }
12754
12833
 
@@ -18087,7 +18166,56 @@ const STYLES$1 = `
18087
18166
  overflow-y: auto; -webkit-overflow-scrolling: touch;
18088
18167
  padding: 4px;
18089
18168
  }
18169
+ .ps-msp-home {
18170
+ height: 100%;
18171
+ min-height: 0;
18172
+ display: flex;
18173
+ flex-direction: column;
18174
+ gap: max(12px, 0.95vw);
18175
+ }
18176
+ .ps-msp-welcome-panel,
18177
+ .ps-msp-cards-panel {
18178
+ min-width: 0;
18179
+ min-height: 0;
18180
+ background: var(--ps-bg-primary);
18181
+ }
18182
+ .ps-msp-welcome-panel {
18183
+ display: flex;
18184
+ align-items: flex-start;
18185
+ justify-content: space-between;
18186
+ gap: max(12px, 1vw);
18187
+ padding: max(12px, 1vw) 0 max(12px, 0.95vw);
18188
+ border-bottom: 1px solid var(--ps-border-subtle);
18189
+ }
18190
+ .ps-msp-cards-panel {
18191
+ display: flex;
18192
+ flex-direction: column;
18193
+ overflow: hidden;
18194
+ flex: 1;
18195
+ }
18196
+ .ps-msp-cards-scroll {
18197
+ flex: 1;
18198
+ min-height: 0;
18199
+ overflow-y: auto;
18200
+ -webkit-overflow-scrolling: touch;
18201
+ padding: max(4px, 0.35vw) 0 max(8px, 0.65vw);
18202
+ }
18090
18203
  .ps-msp-header { margin-bottom: max(10px, 0.85vw); }
18204
+ .ps-msp-header-row {
18205
+ display: flex;
18206
+ align-items: flex-start;
18207
+ justify-content: space-between;
18208
+ gap: max(10px, 0.8vw);
18209
+ }
18210
+ .ps-msp-header-copy { min-width: 0; }
18211
+ .ps-msp-kicker {
18212
+ font-size: max(9px, 0.58vw);
18213
+ font-weight: 800;
18214
+ letter-spacing: 0.12em;
18215
+ text-transform: uppercase;
18216
+ color: var(--ps-accent);
18217
+ margin-bottom: max(4px, 0.32vw);
18218
+ }
18091
18219
  .ps-msp-title {
18092
18220
  font-size: max(13px, 0.95vw);
18093
18221
  font-weight: 700;
@@ -18096,16 +18224,56 @@ const STYLES$1 = `
18096
18224
  letter-spacing: -0.005em;
18097
18225
  }
18098
18226
  .ps-msp-subtitle {
18099
- font-size: max(10px, 0.7vw);
18227
+ font-size: max(11px, 0.72vw);
18100
18228
  color: var(--ps-text-muted);
18101
- margin: 0; line-height: 1.5;
18229
+ margin: 0;
18230
+ line-height: 1.55;
18231
+ max-width: 54ch;
18232
+ }
18233
+ .ps-msp-header-actions {
18234
+ display: flex;
18235
+ align-items: center;
18236
+ gap: max(8px, 0.65vw);
18237
+ flex-shrink: 0;
18238
+ }
18239
+ .ps-msp-primary-create {
18240
+ border: 0;
18241
+ border-radius: 999px;
18242
+ background: var(--ps-accent);
18243
+ color: #FFFFFF;
18244
+ font-family: inherit;
18245
+ font-size: max(10px, 0.66vw);
18246
+ font-weight: 800;
18247
+ padding: max(7px, 0.52vw) max(11px, 0.8vw);
18248
+ cursor: pointer;
18249
+ transition: opacity 0.15s, transform 0.15s;
18250
+ }
18251
+ .ps-msp-primary-create:hover { opacity: 0.88; }
18252
+ .ps-msp-primary-create:active { transform: scale(0.98); }
18253
+ .ps-msp-logout {
18254
+ flex-shrink: 0;
18255
+ border: 1px solid var(--ps-border-color);
18256
+ border-radius: 999px;
18257
+ background: #FFFFFF;
18258
+ color: #DC2626;
18259
+ font-family: inherit;
18260
+ font-size: max(10px, 0.62vw);
18261
+ font-weight: 700;
18262
+ padding: max(6px, 0.42vw) max(9px, 0.68vw);
18263
+ cursor: pointer;
18264
+ transition: border-color 0.15s, color 0.15s, background 0.15s;
18265
+ }
18266
+ .ps-msp-logout:hover {
18267
+ border-color: #DC2626;
18268
+ color: #B91C1C;
18269
+ background: #FEF2F2;
18102
18270
  }
18103
18271
 
18104
18272
  /* Card grid — compact saved profile cards */
18105
18273
  .ps-msp-grid {
18106
18274
  display: grid;
18107
- grid-template-columns: repeat(auto-fill, minmax(max(140px, 11vw), 1fr));
18108
- gap: max(8px, 0.7vw);
18275
+ grid-template-columns: repeat(auto-fill, minmax(max(160px, 12vw), 1fr));
18276
+ gap: max(10px, 0.8vw);
18109
18277
  margin-bottom: max(14px, 1.2vw);
18110
18278
  }
18111
18279
  .ps-msp-card {
@@ -18406,27 +18574,28 @@ const STYLES$1 = `
18406
18574
  }
18407
18575
  /* When create card is the only item (no saved profiles), make it wider */
18408
18576
  .ps-msp-grid > .ps-msp-card-create:only-child {
18409
- grid-column: 1 / -1;
18410
- min-height: max(160px, 12vw);
18411
- max-width: 380px;
18412
- margin: 0 auto;
18577
+ grid-column: auto;
18578
+ width: max(150px, 12vw);
18579
+ min-height: max(96px, 7.4vw);
18580
+ max-width: max(150px, 12vw);
18581
+ margin: 0;
18413
18582
  }
18414
18583
  .ps-msp-create-icon {
18415
- width: max(32px, 2.6vw);
18416
- height: max(32px, 2.6vw);
18584
+ width: max(28px, 2.2vw);
18585
+ height: max(28px, 2.2vw);
18417
18586
  background: var(--ps-accent); color: #FFFFFF;
18418
18587
  border-radius: max(4px, 0.35vw);
18419
18588
  display: flex; align-items: center; justify-content: center;
18420
18589
  margin-bottom: max(6px, 0.55vw);
18421
18590
  }
18422
18591
  .ps-msp-create-title {
18423
- font-size: max(11px, 0.78vw);
18592
+ font-size: max(10px, 0.68vw);
18424
18593
  font-weight: 700;
18425
18594
  color: var(--ps-text-primary);
18426
18595
  margin-bottom: max(2px, 0.2vw);
18427
18596
  }
18428
18597
  .ps-msp-create-sub {
18429
- font-size: max(8px, 0.55vw);
18598
+ font-size: max(7px, 0.46vw);
18430
18599
  font-weight: 700;
18431
18600
  letter-spacing: 0.14em; text-transform: uppercase;
18432
18601
  color: var(--ps-text-muted);
@@ -18696,11 +18865,34 @@ const STYLES$1 = `
18696
18865
 
18697
18866
  @media (max-width: 768px) {
18698
18867
  /* Profile card grid */
18868
+ .ps-msp-home {
18869
+ height: auto;
18870
+ gap: 3vw;
18871
+ }
18872
+ .ps-msp-welcome-panel {
18873
+ gap: 3vw;
18874
+ padding: 3vw 0;
18875
+ }
18876
+ .ps-msp-cards-scroll {
18877
+ max-height: 66vh;
18878
+ padding: 1vw 0 3vw;
18879
+ }
18880
+ .ps-msp-header-actions { width: 100%; gap: 2vw; }
18881
+ .ps-msp-primary-create { font-size: 3vw; padding: 2.4vw 3.4vw; }
18882
+ .ps-msp-header-actions .ps-msp-primary-create { flex: 1; }
18699
18883
  .ps-msp-grid { grid-template-columns: 1fr; gap: 3vw; }
18700
18884
  .ps-msp-card-create { min-height: 22vw; }
18885
+ .ps-msp-grid > .ps-msp-card-create:only-child {
18886
+ width: 46vw;
18887
+ max-width: 46vw;
18888
+ min-height: 30vw;
18889
+ }
18701
18890
  .ps-msp-header { margin-bottom: 3vw; }
18891
+ .ps-msp-header-row { align-items: flex-start; gap: 3vw; }
18892
+ .ps-msp-kicker { font-size: 2.4vw; margin-bottom: 1vw; }
18702
18893
  .ps-msp-title { font-size: 5.6vw; }
18703
18894
  .ps-msp-subtitle { font-size: 3vw; }
18895
+ .ps-msp-logout { font-size: 2.8vw; padding: 2vw 2.8vw; }
18704
18896
  .ps-msp-card { padding: 3.5vw; border-radius: 3vw; }
18705
18897
  .ps-msp-card-tag { font-size: 2.3vw; padding: 1vw 2vw; border-radius: 1vw; }
18706
18898
  .ps-msp-card-circle { width: 18vw; height: 18vw; margin: 2vw auto 3vw; }
@@ -22269,7 +22461,7 @@ function ProductPhotoCarouselCard({
22269
22461
  const slide = entries.slice(start, start + PER_SLIDE);
22270
22462
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-photo-strip", role: "group", "aria-label": t2("Product photos"), children: [
22271
22463
  isCompleteLook && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-head", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-photo-strip-badge", children: t2("Complete the look") }) }),
22272
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-photo-strip-row", style: { gridTemplateColumns: `repeat(${Math.max(1, Math.min(PER_SLIDE, slide.length))}, 1fr)` }, children: slide.map((item, i) => {
22464
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `ps-tryon-photo-strip-row ps-count-${slide.length}`, children: slide.map((item, i) => {
22273
22465
  const content = /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: item.image, alt: item.title || productTitle || "", draggable: false });
22274
22466
  return item.href ? /* @__PURE__ */ jsxRuntimeExports.jsx(
22275
22467
  "a",
@@ -27982,6 +28174,7 @@ function MySizingProfilesView({
27982
28174
  onSaveProfileMeasurements,
27983
28175
  onSaveBraSize,
27984
28176
  onRequestDelete,
28177
+ onLogout,
27985
28178
  onClose,
27986
28179
  apiUrl,
27987
28180
  apiKey,
@@ -27993,18 +28186,9 @@ function MySizingProfilesView({
27993
28186
  t: t2,
27994
28187
  onRegisterBackInterceptor
27995
28188
  }) {
27996
- const [creating, setCreating] = reactExports.useState(() => !!initialCreateDraft);
28189
+ const [creating, setCreating] = reactExports.useState(false);
27997
28190
  const [viewingId, setViewingId] = reactExports.useState(null);
27998
- const handledDraftKeyRef = reactExports.useRef(initialCreateDraft?.createdAt ?? null);
27999
28191
  const viewingProfile = viewingId ? profiles.find((p2) => p2.id === viewingId) || null : null;
28000
- reactExports.useEffect(() => {
28001
- if (!initialCreateDraft) return;
28002
- const draftKey = initialCreateDraft.createdAt ?? "draft";
28003
- if (handledDraftKeyRef.current === draftKey && creating) return;
28004
- handledDraftKeyRef.current = draftKey;
28005
- setViewingId(null);
28006
- setCreating(true);
28007
- }, [creating, initialCreateDraft]);
28008
28192
  reactExports.useEffect(() => {
28009
28193
  if (viewingId && !profiles.find((p2) => p2.id === viewingId)) {
28010
28194
  setViewingId(null);
@@ -28075,12 +28259,19 @@ function MySizingProfilesView({
28075
28259
  t: t2
28076
28260
  },
28077
28261
  `create-${initialCreateDraft?.createdAt ?? "blank"}`
28078
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
28079
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msp-header", children: [
28080
- /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-msp-title", children: t2("My Sizing Profiles") }),
28081
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-msp-subtitle", children: t2("Manage your bespoke silhouettes. Switch between profiles for different fits or create a new one for specific garment types.") })
28262
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msp-home", children: [
28263
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "ps-msp-welcome-panel", "aria-label": t2("Profile welcome"), children: [
28264
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
28265
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msp-kicker", children: t2("Welcome") }),
28266
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-msp-title", children: t2("My Sizing Profiles") }),
28267
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-msp-subtitle", children: profiles.length > 0 ? t2("Choose a saved profile or create a new one before finding your best fit.") : t2("Create your first fit profile to save your measurements, photo, and size history.") })
28268
+ ] }),
28269
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msp-header-actions", children: [
28270
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-msp-primary-create", onClick: () => setCreating(true), children: t2("Create New Profile") }),
28271
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-msp-logout", onClick: onLogout, children: t2("Sign out") })
28272
+ ] })
28082
28273
  ] }),
28083
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msp-grid", children: [
28274
+ /* @__PURE__ */ jsxRuntimeExports.jsx("section", { className: "ps-msp-cards-panel", "aria-label": t2("Your profiles"), children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msp-cards-scroll", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msp-grid", children: [
28084
28275
  /* @__PURE__ */ jsxRuntimeExports.jsx(CreateProfileCard, { onClick: () => setCreating(true), t: t2 }),
28085
28276
  profiles.map((p2) => /* @__PURE__ */ jsxRuntimeExports.jsx(
28086
28277
  ProfileCard,
@@ -28095,7 +28286,7 @@ function MySizingProfilesView({
28095
28286
  },
28096
28287
  p2.id
28097
28288
  ))
28098
- ] })
28289
+ ] }) }) })
28099
28290
  ] }) }) });
28100
28291
  }
28101
28292
  const googleIcon = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2048%2048'%3e%3cpath%20fill='%23FFC107'%20d='M43.6%2020.5H42V20H24v8h11.3C33.7%2032.7%2029.3%2036%2024%2036c-6.6%200-12-5.4-12-12s5.4-12%2012-12c3.1%200%205.9%201.2%208%203.1l5.7-5.7C34.1%206.1%2029.3%204%2024%204%2012.9%204%204%2012.9%204%2024s8.9%2020%2020%2020%2020-8.9%2020-20c0-1.3-.1-2.4-.4-3.5z'/%3e%3cpath%20fill='%23FF3D00'%20d='M6.3%2014.7l6.6%204.8C14.7%2015.1%2019%2012%2024%2012c3.1%200%205.9%201.2%208%203.1l5.7-5.7C34.1%206.1%2029.3%204%2024%204%2016.2%204%209.5%208.5%206.3%2014.7z'/%3e%3cpath%20fill='%234CAF50'%20d='M24%2044c5.2%200%209.9-2%2013.4-5.2l-6.2-5.2C29.2%2035.1%2026.7%2036%2024%2036c-5.2%200-9.6-3.3-11.3-7.8l-6.5%205C9.4%2039.6%2016.1%2044%2024%2044z'/%3e%3cpath%20fill='%231976D2'%20d='M43.6%2020.5H42V20H24v8h11.3c-.8%202.3-2.3%204.2-4.1%205.6l6.2%205.2C36.9%2039.2%2044%2034%2044%2024c0-1.3-.1-2.4-.4-3.5z'/%3e%3c/svg%3e";
@@ -32102,7 +32293,7 @@ if (typeof document !== "undefined") {
32102
32293
  if (!document.getElementById(id2)) {
32103
32294
  const el2 = document.createElement("style");
32104
32295
  el2.id = id2;
32105
- el2.textContent = STYLES$1;
32296
+ el2.textContent = STYLES;
32106
32297
  document.head.appendChild(el2);
32107
32298
  }
32108
32299
  }
@@ -32154,6 +32345,27 @@ function sanitizeHistoryEntry(entry) {
32154
32345
  hasResult: entry.hasResult || !!entry.resultImageUrl || void 0
32155
32346
  };
32156
32347
  }
32348
+ function comparableProductId(value) {
32349
+ return String(value || "").trim().replace(/^gid:\/\/shopify\/Product\//i, "").replace(/^Product\//i, "");
32350
+ }
32351
+ function historyEntryMatchesProduct(entry, productId, productTitle) {
32352
+ const currentId = comparableProductId(productId);
32353
+ const entryId = comparableProductId(entry.productId);
32354
+ if (currentId && entryId) return currentId === entryId;
32355
+ const currentTitle = String(productTitle || "").trim().toLowerCase();
32356
+ const entryTitle = String(entry.productTitle || "").trim().toLowerCase();
32357
+ return !!currentTitle && !!entryTitle && currentTitle === entryTitle;
32358
+ }
32359
+ function hasCompletedTryOnResult(entry) {
32360
+ return !!(entry.resultImageUrl || entry.hasResult);
32361
+ }
32362
+ function dispatchTryOnCompleteEvent(detail) {
32363
+ if (typeof window === "undefined") return;
32364
+ try {
32365
+ window.dispatchEvent(new CustomEvent("primestyle:tryon-complete", { detail }));
32366
+ } catch {
32367
+ }
32368
+ }
32157
32369
  function computeMatchScore(recData) {
32158
32370
  if (!recData) return null;
32159
32371
  const all = [];
@@ -32209,6 +32421,7 @@ function PrimeStyleTryonInner({
32209
32421
  productDescription,
32210
32422
  productMaterial,
32211
32423
  buttonText,
32424
+ limitOneColorTryOnPerProduct = false,
32212
32425
  apiUrl,
32213
32426
  showPoweredBy = true,
32214
32427
  showIcon = true,
@@ -32542,6 +32755,12 @@ function PrimeStyleTryonInner({
32542
32755
  setProfileAuthLoadingProvider(null);
32543
32756
  }
32544
32757
  }, [activeProfileId, apiUrl, hydrateProfileStore, profiles, t2]);
32758
+ const handleProfileLogout = reactExports.useCallback(() => {
32759
+ clearStoredProfileSession();
32760
+ setProfileSession(null);
32761
+ setProfileAuthError(null);
32762
+ setProfileAuthLoadingProvider(null);
32763
+ }, []);
32545
32764
  const fileInputRef = reactExports.useRef(null);
32546
32765
  const apiRef = reactExports.useRef(null);
32547
32766
  const sseRef = reactExports.useRef(null);
@@ -33201,6 +33420,14 @@ function PrimeStyleTryonInner({
33201
33420
  cleanupJob();
33202
33421
  setTryOnProcessing(false);
33203
33422
  setTryOnStartedAt(null);
33423
+ dispatchTryOnCompleteEvent({
33424
+ jobId: update.galleryId,
33425
+ historyEntryId: currentHistoryEntryIdRef.current,
33426
+ productId: effectiveProductId,
33427
+ productTitle,
33428
+ recommendedSize: sizingResultRef.current?.recommendedSize,
33429
+ resultImageUrl: update.imageUrl
33430
+ });
33204
33431
  onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
33205
33432
  }
33206
33433
  } else if (update.status === "failed") {
@@ -34404,6 +34631,21 @@ function PrimeStyleTryonInner({
34404
34631
  setDrawer(null);
34405
34632
  setView("size-result");
34406
34633
  }, [cleanupJob, productId, productTitle, effectiveProductImages, effectiveProductCarouselItems]);
34634
+ const savedOneColorFitEntry = reactExports.useMemo(() => {
34635
+ if (!limitOneColorTryOnPerProduct) return null;
34636
+ return history.find(
34637
+ (entry) => hasCompletedTryOnResult(entry) && !!entry.recommendedSize && historyEntryMatchesProduct(entry, effectiveProductId, productTitle)
34638
+ ) || null;
34639
+ }, [limitOneColorTryOnPerProduct, history, effectiveProductId, productTitle]);
34640
+ const storefrontButtonText = savedOneColorFitEntry?.recommendedSize ? `${t2("Your size is")} ${savedOneColorFitEntry.recommendedSize}` : resolvedButtonText;
34641
+ const handleStorefrontButtonClick = reactExports.useCallback(() => {
34642
+ if (savedOneColorFitEntry) {
34643
+ onOpen?.();
34644
+ restoreHistory(savedOneColorFitEntry);
34645
+ return;
34646
+ }
34647
+ handleOpen();
34648
+ }, [handleOpen, onOpen, restoreHistory, savedOneColorFitEntry]);
34407
34649
  const updateField = reactExports.useCallback((key, val) => {
34408
34650
  formRef.current[key] = val;
34409
34651
  }, []);
@@ -34814,6 +35056,7 @@ function PrimeStyleTryonInner({
34814
35056
  lsSet("profiles", lsGet("profiles", []).filter((p2) => p2.id !== id2));
34815
35057
  },
34816
35058
  onRequestDelete: (id2) => setDeleteConfirmId(id2),
35059
+ onLogout: handleProfileLogout,
34817
35060
  onClose: () => setView("body-profile"),
34818
35061
  onRegisterBackInterceptor: handleRegisterProfilesBack,
34819
35062
  t: t2
@@ -34873,15 +35116,12 @@ function PrimeStyleTryonInner({
34873
35116
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
34874
35117
  "button",
34875
35118
  {
34876
- onClick: (e) => {
34877
- console.log("[ps-sdk] button click event fired", e);
34878
- handleOpen();
34879
- },
35119
+ onClick: handleStorefrontButtonClick,
34880
35120
  className: cx(cx("ps-tryon-btn", isTextTrigger ? "ps-tryon-btn--text" : void 0), cn.button),
34881
35121
  type: "button",
34882
35122
  children: [
34883
35123
  !isTextTrigger && showIcon !== false && (buttonIcon || /* @__PURE__ */ jsxRuntimeExports.jsx(CameraIcon$1, {})),
34884
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: resolvedButtonText })
35124
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: storefrontButtonText })
34885
35125
  ]
34886
35126
  }
34887
35127
  ),
@@ -35159,7 +35399,7 @@ class PrimeStyleTryonErrorBoundary extends reactExports.Component {
35159
35399
  function PrimeStyleTryon(props) {
35160
35400
  return /* @__PURE__ */ jsxRuntimeExports.jsx(PrimeStyleTryonErrorBoundary, { ...props });
35161
35401
  }
35162
- const STYLES = `
35402
+ const SIZE_GUIDE_STYLES = `
35163
35403
  .ps-sg-btn {
35164
35404
  display: inline-flex;
35165
35405
  align-items: center;
@@ -35322,7 +35562,7 @@ function injectStyles() {
35322
35562
  if (stylesInjected) return;
35323
35563
  const tag = document.createElement("style");
35324
35564
  tag.id = "ps-sg-styles";
35325
- tag.textContent = STYLES;
35565
+ tag.textContent = SIZE_GUIDE_STYLES;
35326
35566
  document.head.appendChild(tag);
35327
35567
  stylesInjected = true;
35328
35568
  }
@@ -35514,10 +35754,112 @@ function installProductViewTracking() {
35514
35754
  roots.forEach((r2) => maybeFireProductView(r2));
35515
35755
  }
35516
35756
  const TAG = "[primestyle-tryon]";
35517
- console.log(`${TAG} bundle loaded — version 5.7.x storefront entry`);
35757
+ const SHADOW_STYLE_ATTR = "data-primestyle-sdk";
35758
+ const DOCUMENT_STYLE_ATTR = "data-primestyle-sdk-document";
35759
+ const SHADOW_MOUNT_ATTR = "data-primestyle-mount";
35760
+ const PORTAL_HOST_ATTR = "data-primestyle-portal-host";
35761
+ const PORTAL_MOUNT_ATTR = "data-primestyle-portal-mount";
35762
+ const SDK_CSS = `${STYLES}
35763
+
35764
+ ${SIZE_GUIDE_STYLES}`;
35765
+ console.log(`${TAG} storefront bundle loaded`);
35518
35766
  installCartHook();
35519
35767
  installProductViewTracking();
35520
35768
  const MOUNTED = /* @__PURE__ */ new WeakMap();
35769
+ const MOUNT_SIGNATURES = /* @__PURE__ */ new WeakMap();
35770
+ const MOUNTING = /* @__PURE__ */ new WeakSet();
35771
+ function ensureDocumentStyles() {
35772
+ if (typeof document === "undefined" || !document.head) return;
35773
+ let styleTag = document.head.querySelector(`style[${DOCUMENT_STYLE_ATTR}]`);
35774
+ if (!styleTag) {
35775
+ styleTag = document.createElement("style");
35776
+ styleTag.setAttribute(DOCUMENT_STYLE_ATTR, "true");
35777
+ document.head.appendChild(styleTag);
35778
+ }
35779
+ if (styleTag.textContent !== SDK_CSS) {
35780
+ styleTag.textContent = SDK_CSS;
35781
+ }
35782
+ }
35783
+ function getPortalHost() {
35784
+ if (typeof document === "undefined" || !document.body) return void 0;
35785
+ let portalHost = document.querySelector(`[${PORTAL_HOST_ATTR}]`);
35786
+ if (!portalHost) {
35787
+ portalHost = document.createElement("div");
35788
+ portalHost.setAttribute(PORTAL_HOST_ATTR, "true");
35789
+ document.body.appendChild(portalHost);
35790
+ }
35791
+ portalHost.style.setProperty("display", "block", "important");
35792
+ portalHost.style.setProperty("position", "fixed", "important");
35793
+ portalHost.style.setProperty("inset", "0", "important");
35794
+ portalHost.style.setProperty("width", "100vw", "important");
35795
+ portalHost.style.setProperty("height", "100vh", "important");
35796
+ portalHost.style.setProperty("z-index", "2147483647", "important");
35797
+ portalHost.style.setProperty("visibility", "visible", "important");
35798
+ portalHost.style.setProperty("opacity", "1", "important");
35799
+ portalHost.style.setProperty("pointer-events", "none", "important");
35800
+ portalHost.style.setProperty("transform", "none", "important");
35801
+ portalHost.style.setProperty("margin", "0", "important");
35802
+ portalHost.style.setProperty("padding", "0", "important");
35803
+ if (typeof portalHost.attachShadow === "function") {
35804
+ try {
35805
+ const shadow = portalHost.shadowRoot || portalHost.attachShadow({ mode: "open" });
35806
+ let styleTag = shadow.querySelector(`style[${SHADOW_STYLE_ATTR}]`);
35807
+ if (!styleTag) {
35808
+ styleTag = document.createElement("style");
35809
+ styleTag.setAttribute(SHADOW_STYLE_ATTR, "true");
35810
+ shadow.appendChild(styleTag);
35811
+ }
35812
+ if (styleTag.textContent !== SDK_CSS) {
35813
+ styleTag.textContent = SDK_CSS;
35814
+ }
35815
+ let portalMount = shadow.querySelector(`[${PORTAL_MOUNT_ATTR}]`);
35816
+ if (!portalMount) {
35817
+ portalMount = document.createElement("div");
35818
+ portalMount.setAttribute(PORTAL_MOUNT_ATTR, "true");
35819
+ portalMount.className = "ps-tryon-portal-mount";
35820
+ shadow.appendChild(portalMount);
35821
+ }
35822
+ portalMount.style.setProperty("display", "block", "important");
35823
+ portalMount.style.setProperty("width", "100%", "important");
35824
+ portalMount.style.setProperty("height", "100%", "important");
35825
+ portalMount.style.setProperty("pointer-events", "none", "important");
35826
+ return portalMount;
35827
+ } catch (err) {
35828
+ console.warn(`${TAG} portal shadow DOM mount failed; falling back to page DOM`, err);
35829
+ }
35830
+ }
35831
+ ensureDocumentStyles();
35832
+ return portalHost;
35833
+ }
35834
+ function createShadowMountTarget(el2) {
35835
+ if (!(el2 instanceof HTMLElement) || typeof el2.attachShadow !== "function") {
35836
+ return { mountTarget: el2 };
35837
+ }
35838
+ try {
35839
+ const shadow = el2.shadowRoot || el2.attachShadow({ mode: "open" });
35840
+ let styleTag = shadow.querySelector(`style[${SHADOW_STYLE_ATTR}]`);
35841
+ if (!styleTag) {
35842
+ styleTag = document.createElement("style");
35843
+ styleTag.setAttribute(SHADOW_STYLE_ATTR, "true");
35844
+ shadow.appendChild(styleTag);
35845
+ }
35846
+ if (styleTag.textContent !== SDK_CSS) {
35847
+ styleTag.textContent = SDK_CSS;
35848
+ }
35849
+ let mountTarget = shadow.querySelector(`[${SHADOW_MOUNT_ATTR}]`);
35850
+ if (!mountTarget) {
35851
+ mountTarget = document.createElement("div");
35852
+ mountTarget.setAttribute(SHADOW_MOUNT_ATTR, "true");
35853
+ mountTarget.className = "ps-tryon-shadow-mount";
35854
+ shadow.appendChild(mountTarget);
35855
+ }
35856
+ el2.setAttribute("data-primestyle-shadow", "true");
35857
+ return { mountTarget, portalContainer: getPortalHost() ?? document.body };
35858
+ } catch (err) {
35859
+ console.warn(`${TAG} shadow DOM mount failed; falling back to page DOM`, err);
35860
+ return { mountTarget: el2 };
35861
+ }
35862
+ }
35521
35863
  function readDataAttrs(el2) {
35522
35864
  const out = {};
35523
35865
  for (const attr of Array.from(el2.attributes)) {
@@ -35536,6 +35878,13 @@ function parseJsonAttr(raw, fallback) {
35536
35878
  return fallback;
35537
35879
  }
35538
35880
  }
35881
+ function buildMountSignature(data) {
35882
+ const relevant = {};
35883
+ for (const key of Object.keys(data).sort()) {
35884
+ relevant[key] = data[key];
35885
+ }
35886
+ return JSON.stringify(relevant);
35887
+ }
35539
35888
  function resolveProductUrl(raw) {
35540
35889
  const source = raw || (typeof window !== "undefined" ? window.location.href : "");
35541
35890
  if (!source) return void 0;
@@ -35556,13 +35905,18 @@ function buildPropsFromDataAttrs(data) {
35556
35905
  productTitle: data.productTitle,
35557
35906
  productUrl: resolveProductUrl(data.productUrl),
35558
35907
  productImage: data.productImage,
35559
- productCarouselItems: parseJsonAttr(data.productCarouselItems, void 0),
35908
+ productImages: parseJsonAttr(data.productImages, void 0),
35909
+ productCarouselItems: parseJsonAttr(
35910
+ data.productCarouselItems,
35911
+ void 0
35912
+ ),
35560
35913
  productDescription: data.productDescription,
35561
35914
  productGender: data.productGender,
35562
35915
  productType: data.productType,
35563
35916
  productVendor: data.productVendor,
35564
35917
  productTags: data.productTags ? data.productTags.split(",").map((t2) => t2.trim()).filter(Boolean) : void 0,
35565
35918
  buttonText: data.buttonText || "Find Your Size",
35919
+ limitOneColorTryOnPerProduct: data.limitOneColorTryOnPerProduct === "true",
35566
35920
  locale: data.locale,
35567
35921
  sizeGuideData: parseJsonAttr(data.cachedSizeguide, void 0),
35568
35922
  sizingCountry: data.sizingCountry,
@@ -35599,22 +35953,39 @@ async function fetchSizeGuideForProduct(proxyUrl, productId) {
35599
35953
  }
35600
35954
  }
35601
35955
  async function mount(el2) {
35602
- if (MOUNTED.has(el2)) {
35603
- console.log(`${TAG} already mounted on`, el2);
35956
+ const data = readDataAttrs(el2);
35957
+ const signature = buildMountSignature(data);
35958
+ const existingRoot = MOUNTED.get(el2);
35959
+ if (existingRoot) {
35960
+ if (MOUNT_SIGNATURES.get(el2) === signature) {
35961
+ console.log(`${TAG} already mounted on`, el2);
35962
+ return;
35963
+ }
35964
+ console.log(`${TAG} data changed; remounting on`, el2);
35965
+ try {
35966
+ existingRoot.unmount();
35967
+ } catch (err) {
35968
+ console.warn(`${TAG} previous React root failed to unmount`, err);
35969
+ }
35970
+ MOUNTED.delete(el2);
35971
+ MOUNT_SIGNATURES.delete(el2);
35972
+ }
35973
+ if (MOUNTING.has(el2)) {
35974
+ console.log(`${TAG} mount already in progress on`, el2);
35604
35975
  return;
35605
35976
  }
35977
+ MOUNTING.add(el2);
35606
35978
  console.log(`${TAG} mounting on element`, el2);
35607
- const data = readDataAttrs(el2);
35608
35979
  console.log(`${TAG} read data attributes`, data);
35609
35980
  const props = buildPropsFromDataAttrs(data);
35610
- const hadCachedSizeguide = !!data.cachedSizeguide;
35981
+ const shouldRenderStandaloneSizeGuide = !!data.cachedSizeguide && data.disableSizeGuideButton !== "true";
35611
35982
  if (!props.sizeGuideData && props.productId && props.apiUrl) {
35612
35983
  const fetched = await fetchSizeGuideForProduct(props.apiUrl, props.productId);
35613
35984
  if (fetched) {
35614
35985
  props.sizeGuideData = fetched;
35615
35986
  }
35616
35987
  }
35617
- if (hadCachedSizeguide && props.sizeGuideData) {
35988
+ if (shouldRenderStandaloneSizeGuide && props.sizeGuideData) {
35618
35989
  try {
35619
35990
  const buttonStyles = props.buttonStyles;
35620
35991
  createSizeGuideButton(el2, props.sizeGuideData, {
@@ -35626,13 +35997,22 @@ async function mount(el2) {
35626
35997
  }
35627
35998
  }
35628
35999
  try {
35629
- const root = createRoot(el2);
35630
- root.render(reactExports.createElement(PrimeStyleTryon, props));
36000
+ const { mountTarget, portalContainer } = createShadowMountTarget(el2);
36001
+ const root = createRoot(mountTarget);
36002
+ root.render(
36003
+ reactExports.createElement(PrimeStyleTryon, {
36004
+ ...props,
36005
+ portalContainer
36006
+ })
36007
+ );
35631
36008
  MOUNTED.set(el2, root);
36009
+ MOUNT_SIGNATURES.set(el2, signature);
35632
36010
  console.log(`${TAG} ✓ mounted React component`);
35633
36011
  maybeFireProductView(el2);
35634
36012
  } catch (err) {
35635
36013
  console.error(`${TAG} ✗ React mount failed`, err);
36014
+ } finally {
36015
+ MOUNTING.delete(el2);
35636
36016
  }
35637
36017
  }
35638
36018
  function mountAll() {