@thefittingroom/shop-ui 5.0.22 → 5.0.23

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/index.js +172 -176
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14054,7 +14054,7 @@ function applyFrameBaseUrl(url, baseUrl2) {
14054
14054
  return `${cleanBase}${url.startsWith("/") ? "" : "/"}${url}`;
14055
14055
  }
14056
14056
  const STORAGE_KEY = "tfr:fitting-room:v1";
14057
- const logger$h = getLogger("fitting-room");
14057
+ const logger$g = getLogger("fitting-room-storage");
14058
14058
  function readAll() {
14059
14059
  try {
14060
14060
  const raw = window.localStorage.getItem(STORAGE_KEY);
@@ -14067,7 +14067,7 @@ function readAll() {
14067
14067
  }
14068
14068
  return parsed;
14069
14069
  } catch (error) {
14070
- logger$h.logWarn("Failed to read fitting room from localStorage", {
14070
+ logger$g.logWarn("Failed to read fitting room from localStorage", {
14071
14071
  error
14072
14072
  });
14073
14073
  return {};
@@ -14077,7 +14077,7 @@ function writeAll(all) {
14077
14077
  try {
14078
14078
  window.localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
14079
14079
  } catch (error) {
14080
- logger$h.logWarn("Failed to write fitting room to localStorage", {
14080
+ logger$g.logWarn("Failed to write fitting room to localStorage", {
14081
14081
  error
14082
14082
  });
14083
14083
  }
@@ -14105,13 +14105,13 @@ async function toggleFittingRoomItem(productId, handle, isPdp) {
14105
14105
  const state = useMainStore.getState();
14106
14106
  const isInFittingRoom = state.fittingRoom.some((item) => item.externalId === productId);
14107
14107
  if (isInFittingRoom) {
14108
- logger$h.logDebug("{{ts}} - Removing from fitting room", {
14108
+ logger$g.logDebug("{{ts}} - Removing from fitting room", {
14109
14109
  productId
14110
14110
  });
14111
14111
  state.removeFromFittingRoom(productId);
14112
14112
  return;
14113
14113
  }
14114
- logger$h.logDebug("{{ts}} - Adding to fitting room", {
14114
+ logger$g.logDebug("{{ts}} - Adding to fitting room", {
14115
14115
  productId,
14116
14116
  handle,
14117
14117
  isPdp
@@ -14133,7 +14133,7 @@ async function toggleFittingRoomItem(productId, handle, isPdp) {
14133
14133
  size = selection.size || null;
14134
14134
  color = selection.color;
14135
14135
  } catch (error) {
14136
- logger$h.logWarn("Failed to read selected options from currentProduct", {
14136
+ logger$g.logWarn("Failed to read selected options from currentProduct", {
14137
14137
  error
14138
14138
  });
14139
14139
  }
@@ -23007,7 +23007,7 @@ function isVersionServiceProvider(provider) {
23007
23007
  }
23008
23008
  const name$q = "@firebase/app";
23009
23009
  const version$1$1 = "0.14.5";
23010
- const logger$g = new Logger3("@firebase/app");
23010
+ const logger$f = new Logger3("@firebase/app");
23011
23011
  const name$p = "@firebase/app-compat";
23012
23012
  const name$o = "@firebase/analytics-compat";
23013
23013
  const name$n = "@firebase/analytics";
@@ -23074,13 +23074,13 @@ function _addComponent(app, component) {
23074
23074
  try {
23075
23075
  app.container.addComponent(component);
23076
23076
  } catch (e) {
23077
- logger$g.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
23077
+ logger$f.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
23078
23078
  }
23079
23079
  }
23080
23080
  function _registerComponent(component) {
23081
23081
  const componentName = component.name;
23082
23082
  if (_components.has(componentName)) {
23083
- logger$g.debug(`There were multiple attempts to register component ${componentName}.`);
23083
+ logger$f.debug(`There were multiple attempts to register component ${componentName}.`);
23084
23084
  return false;
23085
23085
  }
23086
23086
  _components.set(componentName, component);
@@ -23289,7 +23289,7 @@ function registerVersion(libraryKeyOrName, version2, variant) {
23289
23289
  if (versionMismatch) {
23290
23290
  warning.push(`version name "${version2}" contains illegal characters (whitespace or "/")`);
23291
23291
  }
23292
- logger$g.warn(warning.join(" "));
23292
+ logger$f.warn(warning.join(" "));
23293
23293
  return;
23294
23294
  }
23295
23295
  _registerComponent(new Component(
@@ -23333,12 +23333,12 @@ async function readHeartbeatsFromIndexedDB(app) {
23333
23333
  return result;
23334
23334
  } catch (e) {
23335
23335
  if (e instanceof FirebaseError) {
23336
- logger$g.warn(e.message);
23336
+ logger$f.warn(e.message);
23337
23337
  } else {
23338
23338
  const idbGetError = ERROR_FACTORY.create("idb-get", {
23339
23339
  originalErrorMessage: e?.message
23340
23340
  });
23341
- logger$g.warn(idbGetError.message);
23341
+ logger$f.warn(idbGetError.message);
23342
23342
  }
23343
23343
  }
23344
23344
  }
@@ -23351,12 +23351,12 @@ async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
23351
23351
  await tx.done;
23352
23352
  } catch (e) {
23353
23353
  if (e instanceof FirebaseError) {
23354
- logger$g.warn(e.message);
23354
+ logger$f.warn(e.message);
23355
23355
  } else {
23356
23356
  const idbGetError = ERROR_FACTORY.create("idb-set", {
23357
23357
  originalErrorMessage: e?.message
23358
23358
  });
23359
- logger$g.warn(idbGetError.message);
23359
+ logger$f.warn(idbGetError.message);
23360
23360
  }
23361
23361
  }
23362
23362
  }
@@ -23405,7 +23405,7 @@ class HeartbeatServiceImpl {
23405
23405
  }
23406
23406
  return this._storage.overwrite(this._heartbeatsCache);
23407
23407
  } catch (e) {
23408
- logger$g.warn(e);
23408
+ logger$f.warn(e);
23409
23409
  }
23410
23410
  }
23411
23411
  /**
@@ -23436,7 +23436,7 @@ class HeartbeatServiceImpl {
23436
23436
  }
23437
23437
  return headerString;
23438
23438
  } catch (e) {
23439
- logger$g.warn(e);
23439
+ logger$f.warn(e);
23440
23440
  return "";
23441
23441
  }
23442
23442
  }
@@ -41004,7 +41004,7 @@ const firebaseDateToDayjs = (date) => {
41004
41004
  return dayjs(date.seconds * 1e3);
41005
41005
  };
41006
41006
  const LOGIN_TRACKING_PERIOD_SECONDS = 1800;
41007
- const logger$f = getLogger("firebase");
41007
+ const logger$e = getLogger("firebase");
41008
41008
  let firebaseApp = null;
41009
41009
  class FirestoreManager {
41010
41010
  constructor(firestore) {
@@ -41132,7 +41132,7 @@ class AuthManager {
41132
41132
  this.listenToUserProfileUnsub = null;
41133
41133
  }
41134
41134
  if (authUser) {
41135
- logger$f.logDebug("User logged in:", {
41135
+ logger$e.logDebug("User logged in:", {
41136
41136
  uid: authUser.uid
41137
41137
  });
41138
41138
  this.listenToUserProfileUnsub = getFirestoreManager().listenToDoc("users", authUser.uid, (doc2) => {
@@ -41166,7 +41166,7 @@ class AuthManager {
41166
41166
  await firestore.mergeDocData("user_logging", userLoggingDocId, userLoggingData);
41167
41167
  }
41168
41168
  } catch (error) {
41169
- logger$f.logError("Error logging user login activity:", {
41169
+ logger$e.logError("Error logging user login activity:", {
41170
41170
  error
41171
41171
  });
41172
41172
  }
@@ -41364,7 +41364,7 @@ async function getStyleByExternalId(brandId, externalId) {
41364
41364
  recordCache[cacheKey] = record;
41365
41365
  return record;
41366
41366
  }
41367
- const logger$e = getLogger("product");
41367
+ const logger$d = getLogger("product");
41368
41368
  function _init$2() {
41369
41369
  useMainStore.subscribe((state, prevState) => {
41370
41370
  if (state.userHasAvatar && !prevState.userHasAvatar) {
@@ -41397,11 +41397,11 @@ function loadProductDataToStore(externalId) {
41397
41397
  try {
41398
41398
  const productData2 = await loadProductData(externalId);
41399
41399
  useMainStore.getState().setProductData(productData2.externalId, productData2);
41400
- logger$e.logDebug(`Loaded product data for externalId: ${externalId}`, {
41400
+ logger$d.logDebug(`Loaded product data for externalId: ${externalId}`, {
41401
41401
  productData: productData2
41402
41402
  });
41403
41403
  } catch (error) {
41404
- logger$e.logError(`Error loading product data for externalId: ${externalId}`, {
41404
+ logger$d.logError(`Error loading product data for externalId: ${externalId}`, {
41405
41405
  error
41406
41406
  });
41407
41407
  }
@@ -41416,7 +41416,7 @@ function loadProductDataToStore(externalId) {
41416
41416
  }
41417
41417
  loadAndStore();
41418
41418
  }
41419
- const logger$d = getLogger("style-categories");
41419
+ const logger$c = getLogger("style-categories");
41420
41420
  let cached = null;
41421
41421
  let inflight = null;
41422
41422
  function buildIndex(categories, groups) {
@@ -41460,7 +41460,7 @@ async function loadStyleCategoryIndex() {
41460
41460
  }
41461
41461
  inflight = (async () => {
41462
41462
  try {
41463
- logger$d.logDebug("{{ts}} - Loading style-category index");
41463
+ logger$c.logDebug("{{ts}} - Loading style-category index");
41464
41464
  const [categories, groups] = await Promise.all([getStyleCategories(), getStyleCategoryGroups()]);
41465
41465
  cached = buildIndex(categories, groups);
41466
41466
  return cached;
@@ -41473,12 +41473,12 @@ async function loadStyleCategoryIndex() {
41473
41473
  function peekStyleCategoryIndex() {
41474
41474
  return cached;
41475
41475
  }
41476
- const logger$c = getLogger("fitting-room-data");
41476
+ const logger$b = getLogger("fitting-room-data");
41477
41477
  async function loadFittingRoomData() {
41478
41478
  const state = useMainStore.getState();
41479
41479
  const items = state.fittingRoom;
41480
41480
  loadStyleCategoryIndex().catch((error) => {
41481
- logger$c.logError("Failed to load style-category index", {
41481
+ logger$b.logError("Failed to load style-category index", {
41482
41482
  error
41483
41483
  });
41484
41484
  });
@@ -41526,7 +41526,7 @@ async function loadFittingRoomData() {
41526
41526
  }
41527
41527
  }
41528
41528
  } catch (error) {
41529
- logger$c.logError("productLookup batch failed", {
41529
+ logger$b.logError("productLookup batch failed", {
41530
41530
  error,
41531
41531
  handles
41532
41532
  });
@@ -41561,7 +41561,7 @@ function resolveItem(item, merchantSlot, loadedSlot, index) {
41561
41561
  const found = loadedProduct.sizeFitRecommendation.available_sizes.some((sz) => sz.colorway_size_assets.some((csa) => csa.id === item.colorwaySizeAssetId));
41562
41562
  if (!found) {
41563
41563
  needsResize = true;
41564
- logger$c.logDebug("csa no longer in size rec, marking needsResize", {
41564
+ logger$b.logDebug("csa no longer in size rec, marking needsResize", {
41565
41565
  externalId: item.externalId,
41566
41566
  csa: item.colorwaySizeAssetId
41567
41567
  });
@@ -41611,7 +41611,7 @@ function useResolvedFittingRoom() {
41611
41611
  }, []);
41612
41612
  reactExports.useEffect(() => {
41613
41613
  loadFittingRoomData().catch((error) => {
41614
- logger$c.logError("loadFittingRoomData failed", {
41614
+ logger$b.logError("loadFittingRoomData failed", {
41615
41615
  error
41616
41616
  });
41617
41617
  });
@@ -41657,6 +41657,68 @@ function useResolvedFittingRoom() {
41657
41657
  };
41658
41658
  }, [fittingRoom, productData, merchantProductData, index, styleCategoryError]);
41659
41659
  }
41660
+ function buildVtoProductDataFromResolved(item) {
41661
+ const {
41662
+ merchantProduct,
41663
+ loadedProduct
41664
+ } = item;
41665
+ if (!merchantProduct || !loadedProduct) return null;
41666
+ const sizeRec = loadedProduct.sizeFitRecommendation;
41667
+ const recommendedSizeId = sizeRec.recommended_size.id || null;
41668
+ const recommendedSizeLabel = getSizeLabelFromSize(sizeRec.recommended_size);
41669
+ if (recommendedSizeId == null || !recommendedSizeLabel) {
41670
+ logger$b.logWarn("Missing recommended size for item", {
41671
+ externalId: item.externalId
41672
+ });
41673
+ return null;
41674
+ }
41675
+ const sizes = [];
41676
+ for (const sizeRecord of sizeRec.available_sizes) {
41677
+ const sizeLabel = getSizeLabelFromSize(sizeRecord);
41678
+ if (!sizeLabel) continue;
41679
+ const fit = sizeRec.fits.find((f) => f.size_id === sizeRecord.id);
41680
+ if (!fit) continue;
41681
+ const colors = [];
41682
+ for (const csa of sizeRecord.colorway_size_assets) {
41683
+ const variant = merchantProduct.variants.find((v) => v.sku === csa.sku);
41684
+ if (!variant) continue;
41685
+ colors.push({
41686
+ colorwaySizeAssetId: csa.id,
41687
+ colorLabel: variant.color || null,
41688
+ sku: csa.sku,
41689
+ priceFormatted: variant.priceFormatted
41690
+ });
41691
+ }
41692
+ if (colors.length === 0) continue;
41693
+ sizes.push({
41694
+ sizeId: sizeRecord.id,
41695
+ sizeLabel,
41696
+ isRecommended: sizeRecord.id === recommendedSizeId,
41697
+ fit,
41698
+ colors
41699
+ });
41700
+ }
41701
+ if (sizes.length === 0) return null;
41702
+ return {
41703
+ productName: merchantProduct.productName,
41704
+ productDescriptionHtml: merchantProduct.productDescriptionHtml,
41705
+ fitClassification: sizeRec.fit_classification,
41706
+ recommendedSizeId,
41707
+ recommendedSizeLabel,
41708
+ sizes,
41709
+ styleCategoryLabel: item.styleCategory?.label_singular ?? loadedProduct.style.style_category_label ?? null
41710
+ };
41711
+ }
41712
+ function findRecommendedColorSize(data, preferredColor) {
41713
+ const recommended = data.sizes.find((s) => s.isRecommended);
41714
+ if (!recommended || recommended.colors.length === 0) return null;
41715
+ return recommended.colors.find((c) => c.colorLabel === preferredColor) ?? recommended.colors[0];
41716
+ }
41717
+ function findCsaByLabel(data, sizeLabel, preferredColor) {
41718
+ const sizeRecord = data.sizes.find((s) => s.sizeLabel === sizeLabel);
41719
+ if (!sizeRecord || sizeRecord.colors.length === 0) return null;
41720
+ return sizeRecord.colors.find((c) => c.colorLabel === preferredColor) ?? sizeRecord.colors[0];
41721
+ }
41660
41722
  function useMobileSheetSnap(initial = "collapsed") {
41661
41723
  const [snap, setSnap] = reactExports.useState(initial);
41662
41724
  const handleTouchStart = reactExports.useCallback((e) => {
@@ -42501,69 +42563,6 @@ function SizeSelector({
42501
42563
  }), [loadedProductData.sizes, selectedSizeLabel, onChangeSize]);
42502
42564
  return /* @__PURE__ */ jsx$1("div", { css: css2.container, children: sizeSelectorNodeList });
42503
42565
  }
42504
- const logger$b = getLogger("overlays/fitting-room/product-data");
42505
- function buildVtoProductDataFromResolved(item) {
42506
- const {
42507
- merchantProduct,
42508
- loadedProduct
42509
- } = item;
42510
- if (!merchantProduct || !loadedProduct) return null;
42511
- const sizeRec = loadedProduct.sizeFitRecommendation;
42512
- const recommendedSizeId = sizeRec.recommended_size.id || null;
42513
- const recommendedSizeLabel = getSizeLabelFromSize(sizeRec.recommended_size);
42514
- if (recommendedSizeId == null || !recommendedSizeLabel) {
42515
- logger$b.logWarn("Missing recommended size for item", {
42516
- externalId: item.externalId
42517
- });
42518
- return null;
42519
- }
42520
- const sizes = [];
42521
- for (const sizeRecord of sizeRec.available_sizes) {
42522
- const sizeLabel = getSizeLabelFromSize(sizeRecord);
42523
- if (!sizeLabel) continue;
42524
- const fit = sizeRec.fits.find((f) => f.size_id === sizeRecord.id);
42525
- if (!fit) continue;
42526
- const colors = [];
42527
- for (const csa of sizeRecord.colorway_size_assets) {
42528
- const variant = merchantProduct.variants.find((v) => v.sku === csa.sku);
42529
- if (!variant) continue;
42530
- colors.push({
42531
- colorwaySizeAssetId: csa.id,
42532
- colorLabel: variant.color || null,
42533
- sku: csa.sku,
42534
- priceFormatted: variant.priceFormatted
42535
- });
42536
- }
42537
- if (colors.length === 0) continue;
42538
- sizes.push({
42539
- sizeId: sizeRecord.id,
42540
- sizeLabel,
42541
- isRecommended: sizeRecord.id === recommendedSizeId,
42542
- fit,
42543
- colors
42544
- });
42545
- }
42546
- if (sizes.length === 0) return null;
42547
- return {
42548
- productName: merchantProduct.productName,
42549
- productDescriptionHtml: merchantProduct.productDescriptionHtml,
42550
- fitClassification: sizeRec.fit_classification,
42551
- recommendedSizeId,
42552
- recommendedSizeLabel,
42553
- sizes,
42554
- styleCategoryLabel: item.styleCategory?.label_singular ?? loadedProduct.style.style_category_label ?? null
42555
- };
42556
- }
42557
- function findRecommendedColorSize(data, preferredColor) {
42558
- const recommended = data.sizes.find((s) => s.isRecommended);
42559
- if (!recommended || recommended.colors.length === 0) return null;
42560
- return recommended.colors.find((c) => c.colorLabel === preferredColor) ?? recommended.colors[0];
42561
- }
42562
- function findCsaByLabel(data, sizeLabel, preferredColor) {
42563
- const sizeRecord = data.sizes.find((s) => s.sizeLabel === sizeLabel);
42564
- if (!sizeRecord || sizeRecord.colors.length === 0) return null;
42565
- return sizeRecord.colors.find((c) => c.colorLabel === preferredColor) ?? sizeRecord.colors[0];
42566
- }
42567
42566
  function DetailAccordionItem({
42568
42567
  item,
42569
42568
  isOpen,
@@ -43219,8 +43218,7 @@ function TryOnView({
43219
43218
  ] }) })
43220
43219
  ] });
43221
43220
  }
43222
- const logger$a = getLogger("overlays/fitting-room/use-vto-requests");
43223
- const NON_PRIORITY_REQUEST_DELAY_MS = 500;
43221
+ const logger$a = getLogger("use-vto-requests");
43224
43222
  function outfitKey(items) {
43225
43223
  return items.map((i) => `${i.colorway_size_asset_id}:${i.untucked ? 1 : 0}`).sort().join("|");
43226
43224
  }
@@ -43228,6 +43226,7 @@ function useVtoRequests() {
43228
43226
  const [framesByKey, setFramesByKey] = reactExports.useState({});
43229
43227
  const requestedKeysRef = reactExports.useRef(/* @__PURE__ */ new Set());
43230
43228
  const lastPriorityTimeRef = reactExports.useRef(null);
43229
+ const pendingPrefetchTimersRef = reactExports.useRef(/* @__PURE__ */ new Set());
43231
43230
  const [lastError, setLastError] = reactExports.useState(null);
43232
43231
  const clearError = reactExports.useCallback(() => setLastError(null), []);
43233
43232
  const request = reactExports.useCallback((items, priority) => {
@@ -43261,6 +43260,8 @@ function useVtoRequests() {
43261
43260
  });
43262
43261
  };
43263
43262
  if (priority) {
43263
+ for (const timer of pendingPrefetchTimersRef.current) clearTimeout(timer);
43264
+ pendingPrefetchTimersRef.current.clear();
43264
43265
  lastPriorityTimeRef.current = Date.now();
43265
43266
  exec();
43266
43267
  return;
@@ -43269,15 +43270,26 @@ function useVtoRequests() {
43269
43270
  let delay = 0;
43270
43271
  if (last) {
43271
43272
  const now = Date.now();
43272
- const minNext = last + NON_PRIORITY_REQUEST_DELAY_MS;
43273
+ const minNext = last + getStaticData().config.api.vtoPrefetchDelayMs;
43273
43274
  if (now < minNext) delay = minNext - now;
43274
43275
  }
43275
43276
  if (delay > 0) {
43276
- setTimeout(exec, delay);
43277
+ const timer = setTimeout(() => {
43278
+ pendingPrefetchTimersRef.current.delete(timer);
43279
+ exec();
43280
+ }, delay);
43281
+ pendingPrefetchTimersRef.current.add(timer);
43277
43282
  } else {
43278
43283
  exec();
43279
43284
  }
43280
43285
  }, []);
43286
+ reactExports.useEffect(() => {
43287
+ const timers = pendingPrefetchTimersRef.current;
43288
+ return () => {
43289
+ for (const timer of timers) clearTimeout(timer);
43290
+ timers.clear();
43291
+ };
43292
+ }, []);
43281
43293
  const framesForOutfit = reactExports.useCallback((items) => {
43282
43294
  if (items.length === 0) return null;
43283
43295
  const key = outfitKey(items);
@@ -44354,14 +44366,10 @@ function FitChart({
44354
44366
  ] })
44355
44367
  ] });
44356
44368
  }
44357
- const NON_PRIORITY_VTO_REQUEST_DELAY_MS = 500;
44358
44369
  const AVATAR_IMAGE_ASPECT_RATIO = 2 / 3;
44359
44370
  const AVATAR_GUTTER_HEIGHT_PX = 100;
44360
44371
  const CONTENT_AREA_WIDTH_PX = 550;
44361
44372
  const logger$6 = getLogger("overlays/vto-single");
44362
- function compositionKey(csaId, untucked) {
44363
- return `${csaId}:${0}`;
44364
- }
44365
44373
  function VtoSingleOverlay() {
44366
44374
  const userIsLoggedIn = useMainStore((state) => state.userIsLoggedIn);
44367
44375
  const userHasAvatar = useMainStore((state) => state.userHasAvatar);
@@ -44374,9 +44382,10 @@ function VtoSingleOverlay() {
44374
44382
  const [selectedSizeLabel, setSelectedSizeLabel] = reactExports.useState(null);
44375
44383
  const [selectedColorLabel, setSelectedColorLabel] = reactExports.useState(null);
44376
44384
  const [modalStyle, setModalStyle] = reactExports.useState({});
44377
- const [framesByKey, setFramesByKey] = reactExports.useState({});
44378
- const requestedKeysRef = reactExports.useRef(/* @__PURE__ */ new Set());
44379
- const lastPriorityVtoRequestTimeRef = reactExports.useRef(null);
44385
+ const {
44386
+ request: vtoRequest,
44387
+ framesForOutfit
44388
+ } = useVtoRequests();
44380
44389
  reactExports.useEffect(() => {
44381
44390
  if (!userIsLoggedIn) {
44382
44391
  openOverlay(OverlayName.LANDING, {
@@ -44547,63 +44556,17 @@ function VtoSingleOverlay() {
44547
44556
  availableColorLabels: availableColorLabels2
44548
44557
  };
44549
44558
  }, [vtoProductData, selectedSizeLabel, selectedColorLabel]);
44550
- const requestVto$1 = reactExports.useCallback((sizeColorRecord, priority) => {
44551
- const csaId = sizeColorRecord.colorwaySizeAssetId;
44552
- const key = compositionKey(csaId);
44553
- if (requestedKeysRef.current.has(key)) {
44554
- return;
44555
- }
44556
- function executeRequest() {
44557
- logger$6.timerStart(`requestVto_${sizeColorRecord.sku}`);
44558
- logger$6.logDebug(`{{ts}} - Requesting VTO for sku: ${sizeColorRecord.sku}`, {
44559
- priority,
44560
- sizeColorRecord
44561
- });
44562
- requestedKeysRef.current.add(key);
44563
- requestVto([{
44564
- colorway_size_asset_id: csaId,
44565
- untucked: false
44566
- }]).then((resp) => {
44567
- logger$6.timerEnd(`requestVto_${sizeColorRecord.sku}`);
44568
- logger$6.logTimer(`requestVto_${sizeColorRecord.sku}`, `{{ts}} - VTO data is loaded for sku: ${sizeColorRecord.sku}`);
44569
- setFramesByKey((prev2) => ({
44570
- ...prev2,
44571
- [key]: resp.frames
44572
- }));
44573
- }).catch((error) => {
44574
- logger$6.logError(`Error requesting VTO for sku: ${sizeColorRecord.sku}`, {
44575
- error,
44576
- sizeColorRecord
44577
- });
44578
- requestedKeysRef.current.delete(key);
44579
- });
44580
- }
44581
- {
44582
- let delay = 0;
44583
- if (priority) {
44584
- lastPriorityVtoRequestTimeRef.current = Date.now();
44585
- } else {
44586
- const lastPriorityTime = lastPriorityVtoRequestTimeRef.current;
44587
- if (lastPriorityTime) {
44588
- const now = Date.now();
44589
- const minNextRequestTime = lastPriorityTime + NON_PRIORITY_VTO_REQUEST_DELAY_MS;
44590
- if (now < minNextRequestTime) {
44591
- delay = minNextRequestTime - now;
44592
- }
44593
- }
44594
- }
44595
- if (delay) {
44596
- setTimeout(executeRequest, delay);
44597
- return;
44598
- }
44599
- }
44600
- executeRequest();
44601
- }, []);
44559
+ const requestVto2 = reactExports.useCallback((sizeColorRecord, priority) => {
44560
+ vtoRequest([{
44561
+ colorway_size_asset_id: sizeColorRecord.colorwaySizeAssetId,
44562
+ untucked: false
44563
+ }], priority);
44564
+ }, [vtoRequest]);
44602
44565
  reactExports.useEffect(() => {
44603
44566
  if (selectedColorSizeRecord) {
44604
- requestVto$1(selectedColorSizeRecord, true);
44567
+ requestVto2(selectedColorSizeRecord, true);
44605
44568
  }
44606
- }, [requestVto$1, selectedColorSizeRecord]);
44569
+ }, [requestVto2, selectedColorSizeRecord]);
44607
44570
  reactExports.useEffect(() => {
44608
44571
  if (!getStaticData().config.features.vtoPrefetch) {
44609
44572
  return;
@@ -44614,28 +44577,28 @@ function VtoSingleOverlay() {
44614
44577
  for (const sizeRecord of vtoProductData.sizes) {
44615
44578
  const sizeColorRecord = sizeRecord.colors.find((c) => c.colorLabel === selectedColorLabel) ?? sizeRecord.colors[0];
44616
44579
  if (sizeColorRecord) {
44617
- requestVto$1(sizeColorRecord, false);
44580
+ requestVto2(sizeColorRecord, false);
44618
44581
  }
44619
44582
  }
44620
- }, [requestVto$1, vtoProductData, selectedColorLabel]);
44583
+ }, [requestVto2, vtoProductData, selectedColorLabel]);
44621
44584
  const frameUrls = reactExports.useMemo(() => {
44622
44585
  if (!selectedColorSizeRecord) {
44623
44586
  return null;
44624
44587
  }
44625
- const key = compositionKey(selectedColorSizeRecord.colorwaySizeAssetId);
44626
- const frames = framesByKey[key];
44627
- if (!frames || frames.length === 0) {
44588
+ const rewritten = framesForOutfit([{
44589
+ colorway_size_asset_id: selectedColorSizeRecord.colorwaySizeAssetId,
44590
+ untucked: false
44591
+ }]);
44592
+ if (!rewritten) {
44628
44593
  return null;
44629
44594
  }
44630
44595
  logger$6.logDebug(`{{ts}} - Displaying VTO for sku: ${selectedColorSizeRecord.sku}`);
44631
- const baseUrl2 = getStaticData().config.frames.baseUrl;
44632
- const rewritten = frames.map((u) => applyFrameBaseUrl(u, baseUrl2));
44633
44596
  rewritten.forEach((url) => {
44634
44597
  const img = new Image();
44635
44598
  img.src = url;
44636
44599
  });
44637
44600
  return rewritten;
44638
- }, [selectedColorSizeRecord, framesByKey]);
44601
+ }, [selectedColorSizeRecord, framesForOutfit]);
44639
44602
  const handleSignOutClick = reactExports.useCallback(() => {
44640
44603
  closeOverlay();
44641
44604
  const authManager2 = getAuthManager();
@@ -45968,6 +45931,7 @@ function Widget({
45968
45931
  var EnvName = /* @__PURE__ */ ((EnvName2) => {
45969
45932
  EnvName2["DEVELOPMENT"] = "development";
45970
45933
  EnvName2["PRODUCTION"] = "production";
45934
+ EnvName2["DEMO"] = "demo";
45971
45935
  EnvName2["LOCAL"] = "local";
45972
45936
  return EnvName2;
45973
45937
  })(EnvName || {});
@@ -45977,9 +45941,9 @@ const SHARED_CONFIG = {
45977
45941
  appGooglePlayUrl: "https://play.google.com/store/apps/details?id=com.thefittingroom.marketplace"
45978
45942
  },
45979
45943
  build: {
45980
- version: `${"5.0.22"}`,
45981
- commitHash: `${"8a06d35"}`,
45982
- date: `${"2026-05-17T15:31:13.958Z"}`
45944
+ version: `${"5.0.23"}`,
45945
+ commitHash: `${"ab793d5"}`,
45946
+ date: `${"2026-05-19T13:40:12.965Z"}`
45983
45947
  }
45984
45948
  };
45985
45949
  const CONFIGS = {
@@ -45998,7 +45962,8 @@ const CONFIGS = {
45998
45962
  },
45999
45963
  api: {
46000
45964
  baseUrl: "https://tfr.dev.thefittingroom.xyz",
46001
- vtoTimeoutMs: 12e4
45965
+ vtoTimeoutMs: 12e4,
45966
+ vtoPrefetchDelayMs: 3e3
46002
45967
  },
46003
45968
  asset: {
46004
45969
  baseUrl: "https://assets.dev.thefittingroom.xyz/shop-sdk/assets/v5"
@@ -46007,7 +45972,7 @@ const CONFIGS = {
46007
45972
  baseUrl: "https://assets.dev.thefittingroom.xyz"
46008
45973
  },
46009
45974
  features: {
46010
- vtoPrefetch: false
45975
+ vtoPrefetch: true
46011
45976
  },
46012
45977
  ...SHARED_CONFIG
46013
45978
  },
@@ -46026,7 +45991,8 @@ const CONFIGS = {
46026
45991
  },
46027
45992
  api: {
46028
45993
  baseUrl: "https://tfr.p.thefittingroom.xyz",
46029
- vtoTimeoutMs: 12e4
45994
+ vtoTimeoutMs: 12e4,
45995
+ vtoPrefetchDelayMs: 3e3
46030
45996
  },
46031
45997
  asset: {
46032
45998
  baseUrl: "https://assets.p.thefittingroom.xyz/shop-sdk/assets/v5"
@@ -46035,13 +46001,13 @@ const CONFIGS = {
46035
46001
  baseUrl: "https://assets.p.thefittingroom.xyz"
46036
46002
  },
46037
46003
  features: {
46038
- vtoPrefetch: false
46004
+ vtoPrefetch: true
46039
46005
  },
46040
46006
  ...SHARED_CONFIG
46041
46007
  },
46042
46008
  [
46043
- "local"
46044
- /* LOCAL */
46009
+ "demo"
46010
+ /* DEMO */
46045
46011
  ]: {
46046
46012
  firebase: {
46047
46013
  apiKey: "AIzaSyDfjBWzpmzb-mhGN8VSURxzLg6nkzmKUD8",
@@ -46054,7 +46020,8 @@ const CONFIGS = {
46054
46020
  },
46055
46021
  api: {
46056
46022
  baseUrl: "https://demo.thefittingroom.xyz/api",
46057
- vtoTimeoutMs: 12e4
46023
+ vtoTimeoutMs: 12e4,
46024
+ vtoPrefetchDelayMs: 3e3
46058
46025
  },
46059
46026
  asset: {
46060
46027
  baseUrl: "http://demo.thefittingroom.xyz/s3/tfr-assets-dev/shop-sdk/assets/v5"
@@ -46063,7 +46030,36 @@ const CONFIGS = {
46063
46030
  baseUrl: "http://demo.thefittingroom.xyz/s3/tfr-assets-dev"
46064
46031
  },
46065
46032
  features: {
46066
- vtoPrefetch: false
46033
+ vtoPrefetch: true
46034
+ },
46035
+ ...SHARED_CONFIG
46036
+ },
46037
+ [
46038
+ "local"
46039
+ /* LOCAL */
46040
+ ]: {
46041
+ firebase: {
46042
+ apiKey: "AIzaSyDfjBWzpmzb-mhGN8VSURxzLg6nkzmKUD8",
46043
+ authDomain: "fittingroom-dev-5d248.firebaseapp.com",
46044
+ projectId: "fittingroom-dev-5d248",
46045
+ storageBucket: "fittingroom-dev-5d248.appspot.com",
46046
+ messagingSenderId: "2298664147",
46047
+ appId: "1:2298664147:web:340bda75cd5d25f3997026",
46048
+ measurementId: "G-B7GDQ1Y9LL"
46049
+ },
46050
+ api: {
46051
+ baseUrl: "http://localhost:8080",
46052
+ vtoTimeoutMs: 12e4,
46053
+ vtoPrefetchDelayMs: 3e3
46054
+ },
46055
+ asset: {
46056
+ baseUrl: "http://localhost:9000/tfr-assets-dev/shop-sdk/assets/v5"
46057
+ },
46058
+ frames: {
46059
+ baseUrl: "http://localhost:9000/tfr-assets-dev"
46060
+ },
46061
+ features: {
46062
+ vtoPrefetch: true
46067
46063
  },
46068
46064
  ...SHARED_CONFIG
46069
46065
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thefittingroom/shop-ui",
3
- "version": "5.0.22",
3
+ "version": "5.0.23",
4
4
  "description": "the fitting room UI library",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",