@depict-ai/ui 4.3.1 → 4.3.3

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.
@@ -94,7 +94,7 @@ $parcel$export(module.exports, "BreadCrumbs", () => $1f4925833f07df29$export$5b7
94
94
  $parcel$export(module.exports, "QuickLinks", () => $1f4925833f07df29$export$de035477d6fef996);
95
95
  $parcel$export(module.exports, "CategoryPage", () => $14f289047713d67a$export$e2bf8ce7779e827e);
96
96
  /*! Depict.ai search and product listing SDK */
97
- const $b757f75811f3261f$export$83d89fbfd8236492 = "4.3.1";
97
+ const $b757f75811f3261f$export$83d89fbfd8236492 = "4.3.3";
98
98
  const $4e04be41243c3d80$var$transform_elements = sorted_cols_at_size => {
99
99
  const cols_at_size = [];
100
100
  for (let i = 0; i < sorted_cols_at_size.length; i++) {
@@ -960,7 +960,7 @@ function $19950faaac026e09$export$6e5611bc7e57e477(props) {
960
960
  });
961
961
  // Work around https://github.com/solidjs/solid/issues/1828
962
962
  const img = new Image(); // Need to use new Image or browser might not start loading image before it's in the DOM
963
- const [, otherAttributes] = $5vyXB$solidjs.splitProps(props, ["resolutions", "size", "src", "srcSet", "loading", "customUrls" // Can't have properties ending on underscore because the property name mangling will get confused by this <-
963
+ const [, otherAttributes] = $5vyXB$solidjs.splitProps(props, ["resolutions", "size", "src", "srcSet", "loading", "keyRatioUpdating", "customUrls" // Can't have properties ending on underscore because the property name mangling will get confused by this <-
964
964
  ]);
965
965
 
966
966
  const [hasSetSize, setHasSetSize] = $5vyXB$solidjs.createSignal(false);
@@ -1016,13 +1016,18 @@ function $19950faaac026e09$export$6e5611bc7e57e477(props) {
1016
1016
  let hasDecodedFastPath = false;
1017
1017
  let timeoutSet = false;
1018
1018
  let gotCleanedUp = false;
1019
+ let srcJustChanged = true;
1019
1020
  img.classList.add("s-responsive-image");
1020
1021
  if (listingContext) {
1021
1022
  let prevValue;
1022
1023
  const aspectRatios = listingContext[$19950faaac026e09$export$f8945274f08a3105] ||= new Set();
1023
1024
  const [, setMostPrevalentAspectRatio] = listingContext[$19950faaac026e09$export$6066eb417ed2e9f7] ||= $5vyXB$solidjs.createSignal();
1024
1025
  img.addEventListener("load", $5vyXB$depictaiutilishared.catchify(() => {
1025
- // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2
1026
+ if (props.keyRatioUpdating) {
1027
+ if (!srcJustChanged) return;
1028
+ srcJustChanged = false;
1029
+ }
1030
+ // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2 and LookItem
1026
1031
  const aspectRatio_ = img.naturalWidth / img.naturalHeight;
1027
1032
  if (prevValue) aspectRatios.delete(prevValue);
1028
1033
  const newValue = !isNaN(aspectRatio_) ? {
@@ -1041,6 +1046,10 @@ function $19950faaac026e09$export$6e5611bc7e57e477(props) {
1041
1046
  }
1042
1047
  $5vyXB$solidjs.onCleanup(() => gotCleanedUp = true);
1043
1048
  $5vyXB$solidjsweb.spread(img, $5vyXB$solidjs.mergeProps(modifiedOtherAttributes), false, true);
1049
+ $5vyXB$solidjs.createRenderEffect(() => {
1050
+ props.src;
1051
+ srcJustChanged = true;
1052
+ });
1044
1053
  $5vyXB$solidjs.createEffect(() => {
1045
1054
  if (!props.size()) return; // wait until we have a size, run every time the size changes
1046
1055
  if (timeoutSet) return;
@@ -1110,48 +1119,22 @@ function $a33065cfed827fc0$export$e4b984597b71e989(props) {
1110
1119
  const [mostPrevalentAspectRatio] = context ?
1111
1120
  // If the context exists we have to create the signal here as getting it here would be too late when it's created by ShopifyResponsiveImg below
1112
1121
  context[(0, $19950faaac026e09$export$6066eb417ed2e9f7)] ||= $5vyXB$solidjs.createSignal() : [];
1113
- const [aspectRatio, setAspectRatio] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(() => props.aspectRatio));
1114
1122
  const container = $93304d59a9747aa6$export$94026ee33dbabc26({
1115
1123
  // Write getters manually instead of using JSX, so we can do more complex logic in the aspectRatio getter without increasing bundle size
1116
1124
  get class() {
1117
1125
  return props.class;
1118
1126
  },
1119
1127
  get aspectRatio() {
1120
- return aspectRatio();
1128
+ if (props.autoAdjustAspectRatio) {
1129
+ const targetRatio = mostPrevalentAspectRatio?.();
1130
+ if (targetRatio != undefined) return `var(${(0, $6f604560873e4f69$export$8a2234b5b1a5ebd4)}, ${targetRatio})`;
1131
+ }
1132
+ return props.aspectRatio;
1121
1133
  }
1122
1134
  });
1123
1135
  const owner = $5vyXB$solidjs.getOwner();
1124
1136
  let createdSizeAccessor = false;
1125
1137
  let wasCleanedUp = false;
1126
- let timeout;
1127
- $5vyXB$solidjs.createEffect(() => {
1128
- const {
1129
- autoAdjustAspectRatio: autoAdjustAspectRatio
1130
- } = props;
1131
- if (autoAdjustAspectRatio) {
1132
- const targetRatio = mostPrevalentAspectRatio?.();
1133
- if (targetRatio != undefined) {
1134
- const targetValue = `var(${(0, $6f604560873e4f69$export$8a2234b5b1a5ebd4)}, ${targetRatio})`;
1135
- const updateAspectRatio = $5vyXB$depictaiutilishared.catchify(() => setAspectRatio(targetValue));
1136
- if (autoAdjustAspectRatio === "smoothed") {
1137
- if (!timeout)
1138
- // If we don't have a timeout yet, also update instantly. This is so that the aspect ratio does get set at the start of a transition, if it changes (when using smoothing).
1139
- updateAspectRatio();
1140
- clearTimeout(timeout);
1141
- timeout = setTimeout(() => {
1142
- timeout = undefined;
1143
- updateAspectRatio();
1144
- }, 500);
1145
- return;
1146
- }
1147
- return updateAspectRatio();
1148
- }
1149
- } else {
1150
- clearTimeout(timeout);
1151
- timeout = undefined;
1152
- }
1153
- setAspectRatio(props.aspectRatio);
1154
- });
1155
1138
  $5vyXB$solidjs.createEffect(() => {
1156
1139
  if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
1157
1140
  // ensure we always have a size accessor
@@ -1197,16 +1180,24 @@ function $d212a67662c5cf38$export$9d4a4b669b1929ab(props) {
1197
1180
  }
1198
1181
  }));
1199
1182
  }
1183
+ function $d659702496cb72ea$export$a71e92cfbb498adc(props) {
1184
+ return $5vyXB$solidjs.createMemo(() => {
1185
+ const price_formatting = props.price_formatting_;
1186
+ return $5vyXB$depictaiutilishared.standard_price_format(props.price_, price_formatting.places_after_comma_, price_formatting.decimal_places_delimiter_, price_formatting.thousands_delimiter_);
1187
+ });
1188
+ }
1200
1189
  var $1ae437d7d388a66e$var$_tmpl$ = ["<div", ' class="img-wrapper">', "</div>"],
1201
1190
  $1ae437d7d388a66e$var$_tmpl$2 = ["<span", ' class="d-price original">', "</span>"],
1202
1191
  $1ae437d7d388a66e$var$_tmpl$3 = ["<div", ' class="right-part"><div class="text-container"><span class="d-title line-clamp">', '</span><span class="', '">', "</span><!--$-->", "<!--/--></div><!--$-->", "<!--/--></div>"];
1203
1192
  function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1204
1193
  display_: display_,
1205
1194
  FavoriteButton_: FavoriteButton_,
1206
- isExpanded_: isExpanded_,
1195
+ userWantsExpandedSignal_: [userWantsExpanded, setUserWantsExpanded],
1207
1196
  textFadeInAnimationRunning_: textFadeInAnimationRunning_,
1208
1197
  outerRef_: outerRef_,
1209
- animationDuration_: animationDuration_
1198
+ animationDuration_: animationDuration_,
1199
+ priceFormatting_: priceFormatting_,
1200
+ pseudoRouter_: pseudoRouter_
1210
1201
  }) {
1211
1202
  const variantToUse = $5vyXB$solidjs.createMemo(() => {
1212
1203
  const display = display_();
@@ -1214,16 +1205,18 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1214
1205
  });
1215
1206
  const imageUrl = $5vyXB$solidjs.createMemo(() => variantToUse()?.image_urls?.[0]);
1216
1207
  const [animationIsRunning, setAnimationIsRunning] = textFadeInAnimationRunning_;
1217
- const [isExpandedThrottledByOurEffectRun, setIsExpandedThrottledByOurEffectRun] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(isExpanded_));
1208
+ const [isExpandedThrottledByOurEffectRun, setIsExpandedThrottledByOurEffectRun] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(userWantsExpanded));
1218
1209
  const [animationEffectExists, setAnimationEffectExists] = $5vyXB$solidjs.createSignal(false);
1219
1210
  const [salePrice] = $5vyXB$solidjs.createResource(() => variantToUse()?.sale_price);
1220
1211
  const [originalPrice] = $5vyXB$solidjs.createResource(() => variantToUse()?.original_price);
1221
- const isOnSale = $5vyXB$solidjs.createMemo(() => salePrice.latest !== originalPrice.latest); // .latest doesn't trigger suspense
1212
+ const isOnSale = $5vyXB$solidjs.createMemo(() => !salePrice.loading && !originalPrice.loading && salePrice.latest !== originalPrice.latest); // .latest doesn't trigger suspense after the initial load
1213
+ const enableLink = $5vyXB$solidjs.createMemo(() => userWantsExpanded() && !animationIsRunning());
1214
+ const href = $5vyXB$solidjs.createMemo(() => variantToUse()?.page_url);
1222
1215
  const FavoriteButton = FavoriteButton_; // Just to get rid of the type error - TS doesn't understand <Show>
1223
1216
  return $5vyXB$solidjsweb.ssrElement("a", $5vyXB$solidjsweb.mergeProps({
1224
1217
  "class": "look-item"
1225
- }, () => isExpanded_() && !animationIsRunning() ? {
1226
- href: variantToUse()?.page_url
1218
+ }, () => enableLink() ? {
1219
+ href: href()
1227
1220
  } : {}), () => ["<!--$-->", $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1228
1221
  when: imageUrl,
1229
1222
  get fallback() {
@@ -1247,10 +1240,13 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1247
1240
  return imageUrl();
1248
1241
  },
1249
1242
  get aspectRatio() {
1250
- return isExpanded_() ? 0.75 : 1;
1243
+ return userWantsExpanded() ? 0.75 : 1;
1251
1244
  },
1252
1245
  get autoAdjustAspectRatio() {
1253
- return isExpanded_() ? "smoothed" : false;
1246
+ return userWantsExpanded();
1247
+ },
1248
+ imgProps: {
1249
+ keyRatioUpdating: true
1254
1250
  }
1255
1251
  });
1256
1252
  }
@@ -1258,24 +1254,72 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1258
1254
  }
1259
1255
  })), "<!--/-->", "<!--$-->", $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1260
1256
  get when() {
1261
- return (animationEffectExists() ? isExpandedThrottledByOurEffectRun() : isExpanded_()) || animationIsRunning();
1257
+ return (animationEffectExists() ? isExpandedThrottledByOurEffectRun() : userWantsExpanded()) || animationIsRunning();
1262
1258
  },
1263
1259
  get children() {
1264
1260
  return $5vyXB$solidjsweb.ssr($1ae437d7d388a66e$var$_tmpl$3, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(variantToUse()?.title) ?? $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1265
1261
  height: "1em",
1266
1262
  width: "20ch"
1267
- })), `d-price ${isOnSale() ? "sale" : ""}`, !variantToUse() || salePrice.loading ? $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1268
- height: "1em",
1269
- width: "20ch"
1270
- })) : $5vyXB$solidjsweb.escape(salePrice()), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1263
+ })), `d-price ${isOnSale() ? "sale" : ""}`, $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1271
1264
  get when() {
1272
- return isOnSale();
1265
+ return variantToUse() && !salePrice.loading;
1273
1266
  },
1274
- get children() {
1275
- return $5vyXB$solidjsweb.ssr($1ae437d7d388a66e$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), !variantToUse() || originalPrice.loading ? $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1267
+ get fallback() {
1268
+ return $5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1276
1269
  height: "1em",
1277
1270
  width: "20ch"
1278
- })) : $5vyXB$solidjsweb.escape(originalPrice()));
1271
+ });
1272
+ },
1273
+ get children() {
1274
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1275
+ get when() {
1276
+ return salePrice.latest;
1277
+ },
1278
+ get children() {
1279
+ return [priceFormatting_().pre_, $5vyXB$solidjsweb.createComponent((0, $d659702496cb72ea$export$a71e92cfbb498adc), {
1280
+ get price_() {
1281
+ return salePrice();
1282
+ },
1283
+ get price_formatting_() {
1284
+ return priceFormatting_();
1285
+ }
1286
+ }), priceFormatting_().post_];
1287
+ }
1288
+ });
1289
+ }
1290
+ })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1291
+ get when() {
1292
+ return isOnSale();
1293
+ },
1294
+ get children() {
1295
+ return $5vyXB$solidjsweb.ssr($1ae437d7d388a66e$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1296
+ get when() {
1297
+ return variantToUse() && !originalPrice.loading;
1298
+ },
1299
+ get fallback() {
1300
+ return $5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1301
+ height: "1em",
1302
+ width: "20ch"
1303
+ });
1304
+ },
1305
+ get children() {
1306
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1307
+ get when() {
1308
+ return salePrice.latest;
1309
+ },
1310
+ get children() {
1311
+ return [priceFormatting_().pre_, $5vyXB$solidjsweb.createComponent((0, $d659702496cb72ea$export$a71e92cfbb498adc), {
1312
+ get price_() {
1313
+ return originalPrice();
1314
+ },
1315
+ get price_formatting_() {
1316
+ return priceFormatting_();
1317
+ }
1318
+ }), priceFormatting_().post_];
1319
+ }
1320
+ });
1321
+ }
1322
+ })));
1279
1323
  }
1280
1324
  })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1281
1325
  when: FavoriteButton_,
@@ -1342,10 +1386,12 @@ var $905010a06f9aeae5$var$_tmpl$ = ["<div", ' class="scroll-padding">', "</div>"
1342
1386
  function $905010a06f9aeae5$export$ebf0b1d4f90c09ae({
1343
1387
  displays_: displays_,
1344
1388
  FavoriteButton_: FavoriteButton_,
1345
- userWantsExpandedSignal_: [userWantsExpanded, setUserWantsExpanded],
1389
+ userWantsExpandedSignal_: userWantsExpandedSignal_,
1346
1390
  containerWidth_: containerWidth_,
1347
1391
  animationDuration_: animationDuration_,
1348
- supportsHover_: supportsHover_
1392
+ supportsHover_: supportsHover_,
1393
+ priceFormatting_: priceFormatting_,
1394
+ pseudoRouter_: pseudoRouter_
1349
1395
  }) {
1350
1396
  let isAffectedByChromeBug = false;
1351
1397
  // If the user requests the drawer to be expanded or not
@@ -1354,6 +1400,7 @@ function $905010a06f9aeae5$export$ebf0b1d4f90c09ae({
1354
1400
  // The following three signals just contain the state if the animations are actually running and should only be set by the respective animation code
1355
1401
  const textFadeInAnimationRunning = $5vyXB$solidjs.createSignal(false);
1356
1402
  const [getSecondPartAnimationRunning] = textFadeInAnimationRunning;
1403
+ const [userWantsExpanded, setUserWantsExpanded] = userWantsExpandedSignal_;
1357
1404
  $b9e830d616d01b31$export$7b9a0e99f0aeb2f3().then(is => isAffectedByChromeBug = is);
1358
1405
  return $5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1359
1406
  get children() {
@@ -1376,11 +1423,13 @@ function $905010a06f9aeae5$export$ebf0b1d4f90c09ae({
1376
1423
  },
1377
1424
  children: (display, index) => {
1378
1425
  return $5vyXB$solidjsweb.createComponent((0, $1ae437d7d388a66e$export$b73ed90f0ee50dc3), {
1426
+ pseudoRouter_: pseudoRouter_,
1379
1427
  animationDuration_: animationDuration_,
1380
1428
  display_: display,
1381
1429
  FavoriteButton_: FavoriteButton_,
1382
- isExpanded_: userWantsExpanded,
1430
+ userWantsExpandedSignal_: userWantsExpandedSignal_,
1383
1431
  textFadeInAnimationRunning_: textFadeInAnimationRunning,
1432
+ priceFormatting_: priceFormatting_,
1384
1433
  outerRef_: el => $5vyXB$solidjs.createEffect(() => {
1385
1434
  if (index !== 0) return;
1386
1435
  const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => setLookItemHeight(records.at(-1).contentRect.height)));
@@ -1421,10 +1470,10 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1421
1470
  expandedLooksSignal_: [expandedLooks_, setExpandedLooks],
1422
1471
  FavoriteButton_: FavoriteButton_,
1423
1472
  placeholderImageAspectRatio_: placeholderImageAspectRatio_,
1424
- animationDuration_: animationDuration_
1473
+ animationDuration_: animationDuration_,
1474
+ priceFormatting_: priceFormatting_,
1475
+ pseudoRouter_: pseudoRouter_
1425
1476
  }) {
1426
- // TODO: shopify, run displayTransformers to get dynamic prices
1427
- // TODO: format prices
1428
1477
  const [coverImage] = display_?.image_urls || [];
1429
1478
  const useWantsExpandedSignal_ = $5vyXB$solidjs.createSignal(false);
1430
1479
  const [userWantsExpanded, setUserWantsExpanded] = useWantsExpandedSignal_;
@@ -1456,7 +1505,7 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1456
1505
  when: display_,
1457
1506
  get fallback() {
1458
1507
  return $5vyXB$solidjsweb.createComponent((0, $3bc4a89b971a3af5$export$3f37af283f8fb843), {
1459
- aspectRatio: placeholderImageAspectRatio_
1508
+ aspectRatio: `var(${(0, $6f604560873e4f69$export$8a2234b5b1a5ebd4)}, ${placeholderImageAspectRatio_})`
1460
1509
  });
1461
1510
  },
1462
1511
  get children() {
@@ -1474,10 +1523,124 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1474
1523
  containerWidth_: containerWidth_,
1475
1524
  animationDuration_: animationDuration_,
1476
1525
  supportsHover_: supportsHover_,
1477
- FavoriteButton_: FavoriteButton_
1526
+ FavoriteButton_: FavoriteButton_,
1527
+ priceFormatting_: priceFormatting_,
1528
+ pseudoRouter_: pseudoRouter_
1478
1529
  })]);
1479
1530
  return container;
1480
1531
  }
1532
+
1533
+ /**
1534
+ * This function is used to determine if the user is trying to open a link in a new tab or window, and we therefore should not single page navigate
1535
+ * @param clickEvent The click event that triggered the navigation
1536
+ */
1537
+ function $747421cd28dec5b5$export$29d28dadc2d6b631(clickEvent) {
1538
+ return clickEvent?.button ||
1539
+ // if not zero it's a wheel click which opens in new tab
1540
+ clickEvent?.metaKey ||
1541
+ // if true, cmd button on macOS which opens in new tab
1542
+ clickEvent?.ctrlKey ||
1543
+ // if true, ctrl button on windows or linux which opens in new tab
1544
+ clickEvent?.shiftKey // if true, shift button on windows, linux or macOS which opens in a new window
1545
+ ;
1546
+ }
1547
+
1548
+ class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
1549
+ /**
1550
+ * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
1551
+ */ /**
1552
+ * We store listing_id in history.state and do operate on this both here and in js-ui, this is the key to be used which js-ui provides
1553
+ */
1554
+ #throwing_on_navigation(...args) {
1555
+ const {
1556
+ on_navigation_: on_navigation_
1557
+ } = this;
1558
+ if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
1559
+ // make sure that we don't accidentally catchify if the SDK consumer has fucked up
1560
+ try {
1561
+ return on_navigation_(...args);
1562
+ } catch (e) {
1563
+ queueMicrotask(() => {
1564
+ throw e;
1565
+ });
1566
+ }
1567
+ }
1568
+ /**
1569
+ * Vue has async router that needs to be awaited (it navigates after a microtask)
1570
+ * This standardises waiting for all kinds of routers
1571
+ */
1572
+ #get_navigation_happened_promise(is_replace) {
1573
+ return new Promise(resolve => {
1574
+ const handler = what_happened => {
1575
+ if (what_happened === (is_replace ? "replaceState" : "pushState")) {
1576
+ resolve();
1577
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
1578
+ }
1579
+ };
1580
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
1581
+ });
1582
+ }
1583
+ navigate_ = {
1584
+ /**
1585
+ * Call this if you *just* want to replace the state object in history.state
1586
+ */
1587
+ replace_state_: new_state => {
1588
+ // This doesn't break any router, so we just do this directly for now, since many don't expose an interface for changing the state
1589
+ globalThis?.history?.replaceState(new_state, "");
1590
+ },
1591
+ /**
1592
+ * Call this to change the URL
1593
+ * @param new_url_ new URL to go to
1594
+ * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
1595
+ * @param force_spa_navigation_ if you want to force SPA navigation even if on_navigation_ is set to "hard_navigation". You should only set this to true for inter-SDK-page navigations
1596
+ * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
1597
+ * @param listing_id_ If you are navigating to a category and know the listing_id of, please provide it. This is for making a better devEx in js-ui
1598
+ */
1599
+ go_to_: $5vyXB$depictaiutilishared.catchify(async ({
1600
+ new_url_: raw_new_url,
1601
+ event_: event_,
1602
+ force_spa_navigation_: force_spa_navigation_,
1603
+ is_replace_: is_replace_,
1604
+ listing_query_: listing_query_,
1605
+ scroll = true
1606
+ }) => {
1607
+ const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
1608
+ const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
1609
+ if ($747421cd28dec5b5$export$29d28dadc2d6b631(event_)) return;
1610
+ const different_origin = new_url_.origin !== location.origin;
1611
+ if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
1612
+ if (force_spa_navigation_ && different_origin)
1613
+ // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
1614
+ $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
1615
+ if (!event_)
1616
+ // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
1617
+ location.assign(new_url_);
1618
+ return;
1619
+ }
1620
+ event_?.preventDefault();
1621
+ const promise = this.#get_navigation_happened_promise(true);
1622
+ if (force_spa_navigation_ && wants_hard_navigation) {
1623
+ // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
1624
+ const new_state = history.state;
1625
+ if (listing_query_) {
1626
+ // In JS-UI we need to know the listing_id of the current category, therefore push it into state
1627
+ if (!this.listing_query_state_key) $5vyXB$depictaiutilishared.report(new Error("listing_query_state_key is not set"), "error");
1628
+ new_state[this.listing_query_state_key] = listing_query_;
1629
+ }
1630
+ history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
1631
+ } else this.#throwing_on_navigation.call(this, {
1632
+ is_replace: is_replace_,
1633
+ new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
1634
+ scroll: scroll
1635
+ });
1636
+ await promise;
1637
+ })
1638
+ };
1639
+ constructor(on_navigation, listing_query_state_key) {
1640
+ this.listing_query_state_key = listing_query_state_key;
1641
+ this.on_navigation_ = on_navigation;
1642
+ }
1643
+ }
1481
1644
  var $072863633018e322$var$_tmpl$ = ["<div", ' class="depict recommendations looks" style="', '">', "</div>"];
1482
1645
  let $072863633018e322$var$expandedLooksSignal_;
1483
1646
  function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
@@ -1486,6 +1649,7 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1486
1649
  equals: false
1487
1650
  });
1488
1651
  const expandingAnimationDuration = 240;
1652
+ const pseudoRouter = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation");
1489
1653
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1490
1654
  const {
1491
1655
  gridSpacing_: gridSpacing_
@@ -1511,19 +1675,35 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1511
1675
  });
1512
1676
  const decoded = await response?.json?.().catch(() => false);
1513
1677
  if (!decoded)
1514
- // If network fails, make sure to return empty array adn SolidRecommendationSlider will remove its elements
1678
+ // If network fails, make sure to return empty array and SolidRecommendationSlider will remove its elements
1515
1679
  return [];
1516
- return decoded.listings;
1680
+ const {
1681
+ listings: listings
1682
+ } = decoded;
1683
+ const baseData = {
1684
+ merchant: merchant,
1685
+ market: market,
1686
+ locale: locale
1687
+ };
1688
+ return $072863633018e322$var$runDisplayTransformersForLooks(baseData, listings, props.displayTransformers_);
1689
+ });
1690
+ $5vyXB$solidjs.createEffect(() => {
1691
+ const {
1692
+ onNavigation_: onNavigation_
1693
+ } = props;
1694
+ if (onNavigation_) pseudoRouter.on_navigation_ = onNavigation_;
1517
1695
  });
1518
1696
  return $5vyXB$solidjsweb.ssr($072863633018e322$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrStyle(`--animation-duration: ${expandingAnimationDuration}ms`), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1519
1697
  get children() {
1520
1698
  return $363ce4d1d71041aa$export$d41d19e89346fa2({
1521
- product_card_template_: (display, info) => $ad882bbe664dbd53$export$44809a8a3e867e30({
1699
+ product_card_template_: display => $ad882bbe664dbd53$export$44809a8a3e867e30({
1522
1700
  display_: display,
1523
1701
  FavoriteButton_: props.FavoriteButton_,
1524
1702
  placeholderImageAspectRatio_: props.imagePlaceholderAspectRatio_,
1525
1703
  animationDuration_: expandingAnimationDuration,
1526
- expandedLooksSignal_: $072863633018e322$var$expandedLooksSignal_
1704
+ expandedLooksSignal_: $072863633018e322$var$expandedLooksSignal_,
1705
+ priceFormatting_: () => props.priceFormatting_,
1706
+ pseudoRouter_: pseudoRouter
1527
1707
  }),
1528
1708
  recommendations_resource_: looksResource,
1529
1709
  title_: () => props.title_,
@@ -1536,6 +1716,53 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1536
1716
  })));
1537
1717
  }, "LookSlider failed");
1538
1718
  }
1719
+ async function $072863633018e322$var$runDisplayTransformersForLooks(baseData, listings, displayTransformers) {
1720
+ try {
1721
+ const {
1722
+ products: productTransformer,
1723
+ categories: providedListingTransformer
1724
+ } = displayTransformers || {};
1725
+ if (!productTransformer && !providedListingTransformer) return listings;
1726
+ const listingTransformer = providedListingTransformer || (({
1727
+ data: data
1728
+ }) => data);
1729
+ const displaysToTransform = [];
1730
+ const displayIdsPerListingId = {};
1731
+ const transformedListingsPromise = listingTransformer({
1732
+ ...baseData,
1733
+ data: listings.map(({
1734
+ displays: displays,
1735
+ ...listing
1736
+ }) => {
1737
+ // Populate our displays by id and displayIdToListings object in the .map where we add ancestors to the listings, for peak efficiency
1738
+ for (let i = 0; i < displays.length; i++) {
1739
+ const display = displays[i];
1740
+ const uniqueIdOfDisplay = $a5871dacf261adf8$export$548d053aba053d79(display);
1741
+ displaysToTransform.push(display);
1742
+ (displayIdsPerListingId[listing.listing_id] ||= []).push(uniqueIdOfDisplay);
1743
+ }
1744
+ return {
1745
+ ...listing,
1746
+ ancestors: []
1747
+ };
1748
+ })
1749
+ });
1750
+ // This allows the person providing the displayTransformer to re-order and remove displays
1751
+ const transformedProducts = productTransformer ? await productTransformer({
1752
+ ...baseData,
1753
+ displays: displaysToTransform
1754
+ }) : displaysToTransform;
1755
+ const transformedListings = await transformedListingsPromise;
1756
+ const transformedDisplayById = Object.fromEntries(transformedProducts.map(display => [$a5871dacf261adf8$export$548d053aba053d79(display), display]));
1757
+ return transformedListings.map(listing => $5vyXB$solidjs.mergeProps(listing, {
1758
+ // use mergeProps because in preview browser we add getters in this object, that would be called too early otherwise
1759
+ displays: (displayIdsPerListingId[listing.listing_id] || []).map(displayId => transformedDisplayById[displayId]).filter(v => v)
1760
+ }));
1761
+ } catch (e) {
1762
+ $5vyXB$depictaiutilishared.dwarn("Displaytransformers threw", e);
1763
+ return [];
1764
+ }
1765
+ }
1539
1766
  const $d84fe647b84b5dc5$export$3064e1e8c6513da3 = new Set();
1540
1767
  let $d84fe647b84b5dc5$var$has_ran = false;
1541
1768
  function $d84fe647b84b5dc5$export$5162a71f252e6122() {
@@ -1576,21 +1803,6 @@ function $d84fe647b84b5dc5$var$starts_with_any_prefix(key) {
1576
1803
  }
1577
1804
  }
1578
1805
 
1579
- /**
1580
- * This function is used to determine if the user is trying to open a link in a new tab or window, and we therefore should not single page navigate
1581
- * @param clickEvent The click event that triggered the navigation
1582
- */
1583
- function $747421cd28dec5b5$export$29d28dadc2d6b631(clickEvent) {
1584
- return clickEvent?.button ||
1585
- // if not zero it's a wheel click which opens in new tab
1586
- clickEvent?.metaKey ||
1587
- // if true, cmd button on macOS which opens in new tab
1588
- clickEvent?.ctrlKey ||
1589
- // if true, ctrl button on windows or linux which opens in new tab
1590
- clickEvent?.shiftKey // if true, shift button on windows, linux or macOS which opens in a new window
1591
- ;
1592
- }
1593
-
1594
1806
  /**
1595
1807
  * Symbol used to identify the version of a SearchModal function. Values right now: 1 = 1st gen classic modal, 2 = second gen modal
1596
1808
  */
@@ -1630,12 +1842,6 @@ function $deaaf04362a1bc71$export$f50b88e2a00918b5(fn) {
1630
1842
  }
1631
1843
  };
1632
1844
  }
1633
- function $d659702496cb72ea$export$a71e92cfbb498adc(props) {
1634
- return $5vyXB$solidjs.createMemo(() => {
1635
- const price_formatting = props.price_formatting_;
1636
- return $5vyXB$depictaiutilishared.standard_price_format(props.price_, price_formatting.places_after_comma_, price_formatting.decimal_places_delimiter_, price_formatting.thousands_delimiter_);
1637
- });
1638
- }
1639
1845
  function $f144ea315d9e4caa$export$fb40a80c530e5f2b(selectedIndex, groupIndex, indexInGroup) {
1640
1846
  const isSelected = $5vyXB$solidjs.createMemo(() => {
1641
1847
  const selectedValue = selectedIndex();
@@ -4060,102 +4266,6 @@ function $6e22b5314fb52f4c$var$history_state_change(signals, entries, state) {
4060
4266
  }
4061
4267
  });
4062
4268
  }
4063
- class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
4064
- /**
4065
- * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
4066
- */ /**
4067
- * We store listing_id in history.state and do operate on this both here and in js-ui, this is the key to be used which js-ui provides
4068
- */
4069
- #throwing_on_navigation(...args) {
4070
- const {
4071
- on_navigation_: on_navigation_
4072
- } = this;
4073
- if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
4074
- // make sure that we don't accidentally catchify if the SDK consumer has fucked up
4075
- try {
4076
- return on_navigation_(...args);
4077
- } catch (e) {
4078
- queueMicrotask(() => {
4079
- throw e;
4080
- });
4081
- }
4082
- }
4083
- /**
4084
- * Vue has async router that needs to be awaited (it navigates after a microtask)
4085
- * This standardises waiting for all kinds of routers
4086
- */
4087
- #get_navigation_happened_promise(is_replace) {
4088
- return new Promise(resolve => {
4089
- const handler = what_happened => {
4090
- if (what_happened === (is_replace ? "replaceState" : "pushState")) {
4091
- resolve();
4092
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
4093
- }
4094
- };
4095
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
4096
- });
4097
- }
4098
- navigate_ = {
4099
- /**
4100
- * Call this if you *just* want to replace the state object in history.state
4101
- */
4102
- replace_state_: new_state => {
4103
- // This doesn't break any router, so we just do this directly for now, since many don't expose an interface for changing the state
4104
- globalThis?.history?.replaceState(new_state, "");
4105
- },
4106
- /**
4107
- * Call this to change the URL
4108
- * @param new_url_ new URL to go to
4109
- * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
4110
- * @param force_spa_navigation_ if you want to force SPA navigation even if on_navigation_ is set to "hard_navigation". You should only set this to true for inter-SDK-page navigations
4111
- * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
4112
- * @param listing_id_ If you are navigating to a category and know the listing_id of, please provide it. This is for making a better devEx in js-ui
4113
- */
4114
- go_to_: $5vyXB$depictaiutilishared.catchify(async ({
4115
- new_url_: raw_new_url,
4116
- event_: event_,
4117
- force_spa_navigation_: force_spa_navigation_,
4118
- is_replace_: is_replace_,
4119
- listing_query_: listing_query_,
4120
- scroll = true
4121
- }) => {
4122
- const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
4123
- const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
4124
- if ($747421cd28dec5b5$export$29d28dadc2d6b631(event_)) return;
4125
- const different_origin = new_url_.origin !== location.origin;
4126
- if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
4127
- if (force_spa_navigation_ && different_origin)
4128
- // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
4129
- $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
4130
- if (!event_)
4131
- // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
4132
- location.assign(new_url_);
4133
- return;
4134
- }
4135
- event_?.preventDefault();
4136
- const promise = this.#get_navigation_happened_promise(true);
4137
- if (force_spa_navigation_ && wants_hard_navigation) {
4138
- // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
4139
- const new_state = history.state;
4140
- if (listing_query_) {
4141
- // In JS-UI we need to know the listing_id of the current category, therefore push it into state
4142
- if (!this.listing_query_state_key) $5vyXB$depictaiutilishared.report(new Error("listing_query_state_key is not set"), "error");
4143
- new_state[this.listing_query_state_key] = listing_query_;
4144
- }
4145
- history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
4146
- } else this.#throwing_on_navigation.call(this, {
4147
- is_replace: is_replace_,
4148
- new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
4149
- scroll: scroll
4150
- });
4151
- await promise;
4152
- })
4153
- };
4154
- constructor(on_navigation, listing_query_state_key) {
4155
- this.listing_query_state_key = listing_query_state_key;
4156
- this.on_navigation_ = on_navigation;
4157
- }
4158
- }
4159
4269
  var $bbe694fe824b9c78$var$_tmpl$ = ["<div", ' class="image-container">', "</div>"];
4160
4270
  function $bbe694fe824b9c78$export$41e1a079d40a0d58(props) {
4161
4271
  const [display] = $5vyXB$solidjs.createResource(() => ({