@depict-ai/ui 4.3.1 → 4.3.2

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.2";
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,6 +1180,12 @@ 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>"];
@@ -1206,7 +1195,9 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1206
1195
  isExpanded_: isExpanded_,
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_();
@@ -1218,12 +1209,14 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
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(() => isExpanded_() && !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() {
@@ -1250,7 +1243,10 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
1250
1243
  return isExpanded_() ? 0.75 : 1;
1251
1244
  },
1252
1245
  get autoAdjustAspectRatio() {
1253
- return isExpanded_() ? "smoothed" : false;
1246
+ return isExpanded_();
1247
+ },
1248
+ imgProps: {
1249
+ keyRatioUpdating: true
1254
1250
  }
1255
1251
  });
1256
1252
  }
@@ -1264,18 +1260,66 @@ function $1ae437d7d388a66e$export$b73ed90f0ee50dc3({
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_,
@@ -1345,7 +1389,9 @@ function $905010a06f9aeae5$export$ebf0b1d4f90c09ae({
1345
1389
  userWantsExpandedSignal_: [userWantsExpanded, setUserWantsExpanded],
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
@@ -1376,11 +1422,13 @@ function $905010a06f9aeae5$export$ebf0b1d4f90c09ae({
1376
1422
  },
1377
1423
  children: (display, index) => {
1378
1424
  return $5vyXB$solidjsweb.createComponent((0, $1ae437d7d388a66e$export$b73ed90f0ee50dc3), {
1425
+ pseudoRouter_: pseudoRouter_,
1379
1426
  animationDuration_: animationDuration_,
1380
1427
  display_: display,
1381
1428
  FavoriteButton_: FavoriteButton_,
1382
1429
  isExpanded_: userWantsExpanded,
1383
1430
  textFadeInAnimationRunning_: textFadeInAnimationRunning,
1431
+ priceFormatting_: priceFormatting_,
1384
1432
  outerRef_: el => $5vyXB$solidjs.createEffect(() => {
1385
1433
  if (index !== 0) return;
1386
1434
  const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => setLookItemHeight(records.at(-1).contentRect.height)));
@@ -1421,10 +1469,10 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1421
1469
  expandedLooksSignal_: [expandedLooks_, setExpandedLooks],
1422
1470
  FavoriteButton_: FavoriteButton_,
1423
1471
  placeholderImageAspectRatio_: placeholderImageAspectRatio_,
1424
- animationDuration_: animationDuration_
1472
+ animationDuration_: animationDuration_,
1473
+ priceFormatting_: priceFormatting_,
1474
+ pseudoRouter_: pseudoRouter_
1425
1475
  }) {
1426
- // TODO: shopify, run displayTransformers to get dynamic prices
1427
- // TODO: format prices
1428
1476
  const [coverImage] = display_?.image_urls || [];
1429
1477
  const useWantsExpandedSignal_ = $5vyXB$solidjs.createSignal(false);
1430
1478
  const [userWantsExpanded, setUserWantsExpanded] = useWantsExpandedSignal_;
@@ -1456,7 +1504,7 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1456
1504
  when: display_,
1457
1505
  get fallback() {
1458
1506
  return $5vyXB$solidjsweb.createComponent((0, $3bc4a89b971a3af5$export$3f37af283f8fb843), {
1459
- aspectRatio: placeholderImageAspectRatio_
1507
+ aspectRatio: `var(${(0, $6f604560873e4f69$export$8a2234b5b1a5ebd4)}, ${placeholderImageAspectRatio_})`
1460
1508
  });
1461
1509
  },
1462
1510
  get children() {
@@ -1474,10 +1522,124 @@ function $ad882bbe664dbd53$export$44809a8a3e867e30({
1474
1522
  containerWidth_: containerWidth_,
1475
1523
  animationDuration_: animationDuration_,
1476
1524
  supportsHover_: supportsHover_,
1477
- FavoriteButton_: FavoriteButton_
1525
+ FavoriteButton_: FavoriteButton_,
1526
+ priceFormatting_: priceFormatting_,
1527
+ pseudoRouter_: pseudoRouter_
1478
1528
  })]);
1479
1529
  return container;
1480
1530
  }
1531
+
1532
+ /**
1533
+ * 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
1534
+ * @param clickEvent The click event that triggered the navigation
1535
+ */
1536
+ function $747421cd28dec5b5$export$29d28dadc2d6b631(clickEvent) {
1537
+ return clickEvent?.button ||
1538
+ // if not zero it's a wheel click which opens in new tab
1539
+ clickEvent?.metaKey ||
1540
+ // if true, cmd button on macOS which opens in new tab
1541
+ clickEvent?.ctrlKey ||
1542
+ // if true, ctrl button on windows or linux which opens in new tab
1543
+ clickEvent?.shiftKey // if true, shift button on windows, linux or macOS which opens in a new window
1544
+ ;
1545
+ }
1546
+
1547
+ class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
1548
+ /**
1549
+ * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
1550
+ */ /**
1551
+ * 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
1552
+ */
1553
+ #throwing_on_navigation(...args) {
1554
+ const {
1555
+ on_navigation_: on_navigation_
1556
+ } = this;
1557
+ if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
1558
+ // make sure that we don't accidentally catchify if the SDK consumer has fucked up
1559
+ try {
1560
+ return on_navigation_(...args);
1561
+ } catch (e) {
1562
+ queueMicrotask(() => {
1563
+ throw e;
1564
+ });
1565
+ }
1566
+ }
1567
+ /**
1568
+ * Vue has async router that needs to be awaited (it navigates after a microtask)
1569
+ * This standardises waiting for all kinds of routers
1570
+ */
1571
+ #get_navigation_happened_promise(is_replace) {
1572
+ return new Promise(resolve => {
1573
+ const handler = what_happened => {
1574
+ if (what_happened === (is_replace ? "replaceState" : "pushState")) {
1575
+ resolve();
1576
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
1577
+ }
1578
+ };
1579
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
1580
+ });
1581
+ }
1582
+ navigate_ = {
1583
+ /**
1584
+ * Call this if you *just* want to replace the state object in history.state
1585
+ */
1586
+ replace_state_: new_state => {
1587
+ // 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
1588
+ globalThis?.history?.replaceState(new_state, "");
1589
+ },
1590
+ /**
1591
+ * Call this to change the URL
1592
+ * @param new_url_ new URL to go to
1593
+ * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
1594
+ * @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
1595
+ * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
1596
+ * @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
1597
+ */
1598
+ go_to_: $5vyXB$depictaiutilishared.catchify(async ({
1599
+ new_url_: raw_new_url,
1600
+ event_: event_,
1601
+ force_spa_navigation_: force_spa_navigation_,
1602
+ is_replace_: is_replace_,
1603
+ listing_query_: listing_query_,
1604
+ scroll = true
1605
+ }) => {
1606
+ const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
1607
+ const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
1608
+ if ($747421cd28dec5b5$export$29d28dadc2d6b631(event_)) return;
1609
+ const different_origin = new_url_.origin !== location.origin;
1610
+ if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
1611
+ if (force_spa_navigation_ && different_origin)
1612
+ // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
1613
+ $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
1614
+ if (!event_)
1615
+ // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
1616
+ location.assign(new_url_);
1617
+ return;
1618
+ }
1619
+ event_?.preventDefault();
1620
+ const promise = this.#get_navigation_happened_promise(true);
1621
+ if (force_spa_navigation_ && wants_hard_navigation) {
1622
+ // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
1623
+ const new_state = history.state;
1624
+ if (listing_query_) {
1625
+ // In JS-UI we need to know the listing_id of the current category, therefore push it into state
1626
+ if (!this.listing_query_state_key) $5vyXB$depictaiutilishared.report(new Error("listing_query_state_key is not set"), "error");
1627
+ new_state[this.listing_query_state_key] = listing_query_;
1628
+ }
1629
+ history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
1630
+ } else this.#throwing_on_navigation.call(this, {
1631
+ is_replace: is_replace_,
1632
+ new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
1633
+ scroll: scroll
1634
+ });
1635
+ await promise;
1636
+ })
1637
+ };
1638
+ constructor(on_navigation, listing_query_state_key) {
1639
+ this.listing_query_state_key = listing_query_state_key;
1640
+ this.on_navigation_ = on_navigation;
1641
+ }
1642
+ }
1481
1643
  var $072863633018e322$var$_tmpl$ = ["<div", ' class="depict recommendations looks" style="', '">', "</div>"];
1482
1644
  let $072863633018e322$var$expandedLooksSignal_;
1483
1645
  function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
@@ -1486,6 +1648,7 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1486
1648
  equals: false
1487
1649
  });
1488
1650
  const expandingAnimationDuration = 240;
1651
+ const pseudoRouter = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation");
1489
1652
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1490
1653
  const {
1491
1654
  gridSpacing_: gridSpacing_
@@ -1511,19 +1674,35 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1511
1674
  });
1512
1675
  const decoded = await response?.json?.().catch(() => false);
1513
1676
  if (!decoded)
1514
- // If network fails, make sure to return empty array adn SolidRecommendationSlider will remove its elements
1677
+ // If network fails, make sure to return empty array and SolidRecommendationSlider will remove its elements
1515
1678
  return [];
1516
- return decoded.listings;
1679
+ const {
1680
+ listings: listings
1681
+ } = decoded;
1682
+ const baseData = {
1683
+ merchant: merchant,
1684
+ market: market,
1685
+ locale: locale
1686
+ };
1687
+ return $072863633018e322$var$runDisplayTransformersForLooks(baseData, listings, props.displayTransformers_);
1688
+ });
1689
+ $5vyXB$solidjs.createEffect(() => {
1690
+ const {
1691
+ onNavigation_: onNavigation_
1692
+ } = props;
1693
+ if (onNavigation_) pseudoRouter.on_navigation_ = onNavigation_;
1517
1694
  });
1518
1695
  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
1696
  get children() {
1520
1697
  return $363ce4d1d71041aa$export$d41d19e89346fa2({
1521
- product_card_template_: (display, info) => $ad882bbe664dbd53$export$44809a8a3e867e30({
1698
+ product_card_template_: display => $ad882bbe664dbd53$export$44809a8a3e867e30({
1522
1699
  display_: display,
1523
1700
  FavoriteButton_: props.FavoriteButton_,
1524
1701
  placeholderImageAspectRatio_: props.imagePlaceholderAspectRatio_,
1525
1702
  animationDuration_: expandingAnimationDuration,
1526
- expandedLooksSignal_: $072863633018e322$var$expandedLooksSignal_
1703
+ expandedLooksSignal_: $072863633018e322$var$expandedLooksSignal_,
1704
+ priceFormatting_: () => props.priceFormatting_,
1705
+ pseudoRouter_: pseudoRouter
1527
1706
  }),
1528
1707
  recommendations_resource_: looksResource,
1529
1708
  title_: () => props.title_,
@@ -1536,6 +1715,53 @@ function $072863633018e322$export$1935e6bdfc5ed8ce(props) {
1536
1715
  })));
1537
1716
  }, "LookSlider failed");
1538
1717
  }
1718
+ async function $072863633018e322$var$runDisplayTransformersForLooks(baseData, listings, displayTransformers) {
1719
+ try {
1720
+ const {
1721
+ products: productTransformer,
1722
+ categories: providedListingTransformer
1723
+ } = displayTransformers || {};
1724
+ if (!productTransformer && !providedListingTransformer) return listings;
1725
+ const listingTransformer = providedListingTransformer || (({
1726
+ data: data
1727
+ }) => data);
1728
+ const displaysToTransform = [];
1729
+ const displayIdsPerListingId = {};
1730
+ const transformedListingsPromise = listingTransformer({
1731
+ ...baseData,
1732
+ data: listings.map(({
1733
+ displays: displays,
1734
+ ...listing
1735
+ }) => {
1736
+ // Populate our displays by id and displayIdToListings object in the .map where we add ancestors to the listings, for peak efficiency
1737
+ for (let i = 0; i < displays.length; i++) {
1738
+ const display = displays[i];
1739
+ const uniqueIdOfDisplay = $a5871dacf261adf8$export$548d053aba053d79(display);
1740
+ displaysToTransform.push(display);
1741
+ (displayIdsPerListingId[listing.listing_id] ||= []).push(uniqueIdOfDisplay);
1742
+ }
1743
+ return {
1744
+ ...listing,
1745
+ ancestors: []
1746
+ };
1747
+ })
1748
+ });
1749
+ // This allows the person providing the displayTransformer to re-order and remove displays
1750
+ const transformedProducts = productTransformer ? await productTransformer({
1751
+ ...baseData,
1752
+ displays: displaysToTransform
1753
+ }) : displaysToTransform;
1754
+ const transformedListings = await transformedListingsPromise;
1755
+ const transformedDisplayById = Object.fromEntries(transformedProducts.map(display => [$a5871dacf261adf8$export$548d053aba053d79(display), display]));
1756
+ return transformedListings.map(listing => $5vyXB$solidjs.mergeProps(listing, {
1757
+ // use mergeProps because in preview browser we add getters in this object, that would be called too early otherwise
1758
+ displays: (displayIdsPerListingId[listing.listing_id] || []).map(displayId => transformedDisplayById[displayId]).filter(v => v)
1759
+ }));
1760
+ } catch (e) {
1761
+ $5vyXB$depictaiutilishared.dwarn("Displaytransformers threw", e);
1762
+ return [];
1763
+ }
1764
+ }
1539
1765
  const $d84fe647b84b5dc5$export$3064e1e8c6513da3 = new Set();
1540
1766
  let $d84fe647b84b5dc5$var$has_ran = false;
1541
1767
  function $d84fe647b84b5dc5$export$5162a71f252e6122() {
@@ -1576,21 +1802,6 @@ function $d84fe647b84b5dc5$var$starts_with_any_prefix(key) {
1576
1802
  }
1577
1803
  }
1578
1804
 
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
1805
  /**
1595
1806
  * Symbol used to identify the version of a SearchModal function. Values right now: 1 = 1st gen classic modal, 2 = second gen modal
1596
1807
  */
@@ -1630,12 +1841,6 @@ function $deaaf04362a1bc71$export$f50b88e2a00918b5(fn) {
1630
1841
  }
1631
1842
  };
1632
1843
  }
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
1844
  function $f144ea315d9e4caa$export$fb40a80c530e5f2b(selectedIndex, groupIndex, indexInGroup) {
1640
1845
  const isSelected = $5vyXB$solidjs.createMemo(() => {
1641
1846
  const selectedValue = selectedIndex();
@@ -4060,102 +4265,6 @@ function $6e22b5314fb52f4c$var$history_state_change(signals, entries, state) {
4060
4265
  }
4061
4266
  });
4062
4267
  }
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
4268
  var $bbe694fe824b9c78$var$_tmpl$ = ["<div", ' class="image-container">', "</div>"];
4160
4269
  function $bbe694fe824b9c78$export$41e1a079d40a0d58(props) {
4161
4270
  const [display] = $5vyXB$solidjs.createResource(() => ({