@depict-ai/ui 4.0.0 → 4.0.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.
package/ES10/index.cjs CHANGED
@@ -92,7 +92,7 @@ $parcel$export(module.exports, "defaultCategoryTitlePlugin", () => $33eed84f447a
92
92
  $parcel$export(module.exports, "version", () => $aa1938dec50d6c12$export$83d89fbfd8236492);
93
93
  $parcel$export(module.exports, "SearchField", () => $98aef9965764903d$export$316f6f283ae64765);
94
94
  /*! Depict.ai search and product listing SDK */
95
- const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.0.0";
95
+ const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.0.2";
96
96
  function $a28000bc10de28ad$export$e417c49320921907(dependency, fetcher) {
97
97
  const [promiseOfCurrentFetcherRun, setPromiseOfCurrentFetcherRun] = $52FdA$solidjs.createSignal();
98
98
  const deparallelizedFetcher = $52FdA$depictaiutilishared.deparallelize_no_drop(async dependencyValue => {
@@ -2533,6 +2533,7 @@ function $858fdcf73148519f$export$e6fffe67d4cdd848(whatToWatch) {
2533
2533
  return size;
2534
2534
  }
2535
2535
  const $858fdcf73148519f$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
2536
+ const $858fdcf73148519f$export$f8945274f08a3105 = /*@__PURE__*/Symbol("listingContextAspectRatios");
2536
2537
  function $858fdcf73148519f$export$6e5611bc7e57e477(props) {
2537
2538
  // Enable reactive props
2538
2539
  const otherOptions = $52FdA$solidjs.createMemo(() => {
@@ -2597,6 +2598,21 @@ function $858fdcf73148519f$export$6e5611bc7e57e477(props) {
2597
2598
  let timeoutSet = false;
2598
2599
  let gotCleanedUp = false;
2599
2600
  img.classList.add("s-responsive-image");
2601
+ if (listingContext) {
2602
+ let prevValue;
2603
+ const aspectRatios = listingContext[$858fdcf73148519f$export$f8945274f08a3105] || (listingContext[$858fdcf73148519f$export$f8945274f08a3105] = new (0, $52FdA$depictaiutilishared.ListenableSet)());
2604
+ img.addEventListener("load", $52FdA$depictaiutilishared.catchify(() => {
2605
+ // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2
2606
+ const aspectRatio_ = img.naturalWidth / img.naturalHeight;
2607
+ if (prevValue) aspectRatios.delete(prevValue);
2608
+ const newValue = !isNaN(aspectRatio_) ? {
2609
+ aspectRatio_: aspectRatio_
2610
+ } : undefined;
2611
+ if (newValue) aspectRatios.add(newValue);
2612
+ prevValue = newValue;
2613
+ }));
2614
+ $52FdA$solidjs.onCleanup(() => prevValue && aspectRatios.delete(prevValue));
2615
+ }
2600
2616
  $52FdA$solidjs.onCleanup(() => gotCleanedUp = true);
2601
2617
  $52FdA$solidjsweb.spread(img, $52FdA$solidjs.mergeProps(otherOptions), false, true);
2602
2618
  $52FdA$solidjs.createEffect(() => {
@@ -2664,9 +2680,29 @@ function $28535bb7671c63d1$export$e4b984597b71e989(props) {
2664
2680
  // create a signal that's the same for all items in this listing
2665
2681
  context[$28535bb7671c63d1$export$d7b7ab832c20e2f4] = $52FdA$solidjs.createSignal();
2666
2682
  const [currentImageSize, setCurrentImageSize] = (context === null || context === void 0 ? void 0 : context[$28535bb7671c63d1$export$d7b7ab832c20e2f4]) || $28535bb7671c63d1$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
2683
+ const aspectRatiosSet = context ? context[(0, $858fdcf73148519f$export$f8945274f08a3105)] || (context[(0, $858fdcf73148519f$export$f8945274f08a3105)] = new (0, $52FdA$depictaiutilishared.ListenableSet)()) : undefined;
2684
+ const [aspectRatios, setAspectRatios] = $52FdA$solidjs.createSignal(aspectRatiosSet, {
2685
+ equals: false
2686
+ });
2687
+ const aspectRatioToUse = $52FdA$solidjs.createMemo(() => {
2688
+ const aspectRatiosSet = aspectRatios(); // This signal "changes" to the same set every time the set changes, so we can use it as a dependency here
2689
+ useMostPrevalentAspectRatio: {
2690
+ if (!aspectRatiosSet || !props.autoAdjustAspectRatio) break useMostPrevalentAspectRatio;
2691
+ // Get the aspect ratio that most of the loaded images inside the ListingProvider we are, load
2692
+ const asArray = [...aspectRatiosSet].map(_ref => {
2693
+ let {
2694
+ aspectRatio_: aspectRatio_
2695
+ } = _ref;
2696
+ return aspectRatio_;
2697
+ });
2698
+ const mostPrevalentAspectRatio = $52FdA$depictaiutilishared.findMostFrequentItem(asArray);
2699
+ if (mostPrevalentAspectRatio) return "var(".concat((0, $c0cf6af094336798$export$8a2234b5b1a5ebd4), ", ").concat(mostPrevalentAspectRatio, ")");
2700
+ }
2701
+ return props.aspectRatio;
2702
+ });
2667
2703
  const container = $52FdA$solidjsweb.createComponent((0, $ce467edb5343cfcd$export$94026ee33dbabc26), {
2668
2704
  get aspectRatio() {
2669
- return props.aspectRatio;
2705
+ return aspectRatioToUse();
2670
2706
  },
2671
2707
  get ["class"]() {
2672
2708
  return props.class;
@@ -2675,6 +2711,10 @@ function $28535bb7671c63d1$export$e4b984597b71e989(props) {
2675
2711
  const owner = $52FdA$solidjs.getOwner();
2676
2712
  let createdSizeAccessor = false;
2677
2713
  let wasCleanedUp = false;
2714
+ for (const event of ["add", "delete"]) {
2715
+ aspectRatiosSet === null || aspectRatiosSet === void 0 || aspectRatiosSet.addEventListener(event, () => setAspectRatios(aspectRatiosSet));
2716
+ $52FdA$solidjs.onCleanup(() => aspectRatiosSet === null || aspectRatiosSet === void 0 ? void 0 : aspectRatiosSet.removeEventListener(event, () => setAspectRatios(aspectRatiosSet)));
2717
+ }
2678
2718
  $52FdA$solidjs.createEffect(() => {
2679
2719
  if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
2680
2720
  // ensure we always have a size accessor
@@ -3742,7 +3782,8 @@ function $43600b30502feeda$var$RawSearchModalV2(_ref) {
3742
3782
  get src() {
3743
3783
  return props.src_;
3744
3784
  },
3745
- aspectRatio: "var(".concat((0, $c0cf6af094336798$export$8a2234b5b1a5ebd4), ", 1)")
3785
+ autoAdjustAspectRatio: true,
3786
+ aspectRatio: 1
3746
3787
  }),
3747
3788
  ...instant_results_options_
3748
3789
  }), _el$4, _co$);
@@ -4094,7 +4135,17 @@ async function $4cf7d9829d60d844$export$79b1565500412d9b(search_modal, modal_fn_
4094
4135
  const actually_close = () => {
4095
4136
  dispose();
4096
4137
  on_dispose === null || on_dispose === void 0 || on_dispose();
4097
- modal_els.forEach(el => el.remove());
4138
+ const {
4139
+ activeElement: activeElement
4140
+ } = document;
4141
+ modal_els.forEach(el => {
4142
+ if (el.contains(activeElement)) {
4143
+ var _blur, _ref;
4144
+ // Fix page jumping to the bottom when closing modal with scape after animation in safari
4145
+ activeElement === null || activeElement === void 0 || (_blur = (_ref = activeElement).blur) === null || _blur === void 0 || _blur.call(_ref);
4146
+ }
4147
+ el.remove();
4148
+ });
4098
4149
  };
4099
4150
  if (animation_started && +new Date() - animation_started > 1000)
4100
4151
  // Animation broke, close it this time
@@ -13479,11 +13530,22 @@ function $a60bc7692ce52705$export$44f738469d5570cf(_ref) {
13479
13530
  modalSearchFieldOuterWidth_: modalSearchFieldOuterWidth_
13480
13531
  } = _ref;
13481
13532
  return $52FdA$solidjs.createRoot(dispose => {
13533
+ const [innerWidthReactive, setInnerWidthReactive] = $52FdA$solidjs.createSignal(innerWidth);
13534
+ const resizeObserver = new ResizeObserver(records => setInnerWidthReactive(records.at(-1).contentRect.width));
13535
+ const {
13536
+ left: left,
13537
+ top: top,
13538
+ width: width
13539
+ } = actualField_.getBoundingClientRect();
13482
13540
  const fakeField = makeFakeField_();
13483
13541
  const owner = $52FdA$solidjs.getOwner();
13484
13542
  const inModalFieldWidth = $52FdA$solidjs.createMemo(
13485
13543
  // Can't have `min(${modalSearchFieldOuterWidth_()}px, var(--field-max-width, 600px))` because the WAAPI doesn't support that, so we need ot calculate it in JS
13486
- () => Math.min(modalSearchFieldOuterWidth_(), parseFloat(getComputedStyle(actualField_).getPropertyValue("--field-max-width") || "600")) + "px");
13544
+ () => Math.min(modalSearchFieldOuterWidth_(), parseFloat(getComputedStyle(actualField_).getPropertyValue("--field-max-width") || "600")));
13545
+ const inModalFieldWidthPx = $52FdA$solidjs.createMemo(() => inModalFieldWidth() + "px");
13546
+ let disableResizePollingTimeout;
13547
+ resizeObserver.observe(document.documentElement);
13548
+ $52FdA$solidjs.onCleanup(() => resizeObserver.disconnect());
13487
13549
  actualField_.replaceWith(fakeField);
13488
13550
  // Don't move the wrapped div since that would confuse run_in_root_or_auto_cleanup, but do actually move the field the user clicked around so that all selection stuff etc. is easier
13489
13551
  const addedToBody = wrap_ ? (() => {
@@ -13492,21 +13554,17 @@ function $a60bc7692ce52705$export$44f738469d5570cf(_ref) {
13492
13554
  return _el$;
13493
13555
  })() : actualField_;
13494
13556
  document.body.append(addedToBody);
13495
- const {
13496
- left: left,
13497
- top: top,
13498
- width: width
13499
- } = fakeField.getBoundingClientRect();
13500
13557
  const zIndexOfFake = getComputedStyle(fakeField).zIndex;
13501
13558
  Object.assign(addedToBody.style, {
13502
13559
  position: "fixed",
13503
13560
  top: top + "px",
13561
+ left: left + "px",
13504
13562
  width: width + "px",
13505
13563
  ...(zIndexOfFake !== "auto" ? {
13506
13564
  zIndex: +zIndexOfFake + 1
13507
13565
  } : {})
13508
13566
  });
13509
- const pxOffCenter = innerWidth / 2 - (left + width / 2);
13567
+ const pxOffCenter = $52FdA$solidjs.untrack(innerWidthReactive) / 2 - (left + width / 2);
13510
13568
  const openDuration = pxOffCenter > 100 ? 250 : 125; // faster animations if little left-right movement
13511
13569
  const closeDuration = pxOffCenter > 100 ? 150 : 100;
13512
13570
  setPollAlignment_(true);
@@ -13525,24 +13583,30 @@ function $a60bc7692ce52705$export$44f738469d5570cf(_ref) {
13525
13583
  // Wait until the ResizeObserver has delivered a value in case that the modal is small or has much padding so we know that we can't animate our fake field to be wider than that
13526
13584
  addedToBody.animate([{
13527
13585
  left: left + "px",
13528
- transform: "translateX(0%)",
13529
13586
  width: width + "px"
13530
13587
  }, {
13531
- left: "50%",
13532
- transform: "translateX(-50%)",
13533
- width: $52FdA$solidjs.untrack(inModalFieldWidth)
13588
+ left: "".concat($52FdA$solidjs.untrack(innerWidthReactive) / 2 - $52FdA$solidjs.untrack(inModalFieldWidth) / 2, "px"),
13589
+ width: $52FdA$solidjs.untrack(inModalFieldWidthPx)
13534
13590
  }], {
13535
13591
  duration: openDuration,
13536
13592
  easing: "ease-in"
13537
13593
  }).finished.then(() => {
13538
13594
  setPollAlignment_(false);
13539
- $52FdA$solidjs.runWithOwner(owner, () => $52FdA$solidjs.createEffect(() =>
13540
- // When animation has finished, still dynamically set the size of the search field behind in case the user resizes the window
13541
- Object.assign(addedToBody.style, {
13542
- left: "50%",
13543
- transform: "translateX(-50%)",
13544
- width: inModalFieldWidth()
13545
- })));
13595
+ $52FdA$solidjs.runWithOwner(owner, () => $52FdA$solidjs.createEffect(() => {
13596
+ // When animation has finished, still dynamically set the size of the search field behind in case the user resizes the window
13597
+ Object.assign(addedToBody.style, {
13598
+ // This is left: 50%, transform: translateX(-50) with extra steps but when using it safari and firefox glitch out like crazy
13599
+ left: "".concat(innerWidthReactive() / 2 - inModalFieldWidth() / 2, "px"),
13600
+ width: inModalFieldWidthPx()
13601
+ });
13602
+ // We might only have changed the left position which align_field doesn't know about, make it poll the position for a while
13603
+ setPollAlignment_(true);
13604
+ if (disableResizePollingTimeout) clearTimeout(disableResizePollingTimeout);
13605
+ disableResizePollingTimeout = setTimeout($52FdA$depictaiutilishared.catchify(() => {
13606
+ setPollAlignment_(false);
13607
+ disableResizePollingTimeout = undefined;
13608
+ }), 1000);
13609
+ }));
13546
13610
  });
13547
13611
  return true;
13548
13612
  }, false);
@@ -13585,13 +13649,11 @@ function $a60bc7692ce52705$export$44f738469d5570cf(_ref) {
13585
13649
  transition: "opacity ".concat(closeDuration, "ms ease-out")
13586
13650
  }));
13587
13651
  await Promise.all([addedToBody.animate([{
13588
- width: $52FdA$solidjs.untrack(inModalFieldWidth),
13589
- left: "50%",
13590
- transform: "translateX(-50%)"
13652
+ width: $52FdA$solidjs.untrack(inModalFieldWidthPx),
13653
+ left: "".concat($52FdA$solidjs.untrack(innerWidthReactive) / 2 - $52FdA$solidjs.untrack(inModalFieldWidth) / 2, "px")
13591
13654
  }, {
13592
13655
  width: width + "px",
13593
- left: left + "px",
13594
- transform: "translateX(0%)"
13656
+ left: left + "px"
13595
13657
  }], {
13596
13658
  duration: closeDuration,
13597
13659
  fill: "forwards",
package/ES10/index.d.ts CHANGED
@@ -10,7 +10,7 @@ import { ProductListingRequestV3 } from "@depict-ai/types/api/ProductListingRequ
10
10
  import { GetListingRequest } from "@depict-ai/types/api/GetListingRequest";
11
11
  import { BaseSearchRequestV3 } from "@depict-ai/types/api/BaseSearchRequestV3";
12
12
  import { SearchFilter as _SearchFilter2 } from "@depict-ai/types/api/SearchRequestV2";
13
- export const version = "4.0.0";
13
+ export const version = "4.0.2";
14
14
  export type ModalAlignmentSignals = {
15
15
  body_: Signal<JSX.CSSProperties>;
16
16
  field_: Signal<JSX.CSSProperties>;
@@ -407,6 +407,28 @@ export function ShopifyResponsiveImg(props: {
407
407
  } & Omit<JSX.ImgHTMLAttributes<HTMLImageElement>, "srcset" | "src" | "sizes"> & {
408
408
  src: string;
409
409
  }): JSX.Element;
410
+ type ImagePlaceholderBaseOptions = {
411
+ style?: JSX.CSSProperties;
412
+ class?: string;
413
+ };
414
+ type ImagePlaceholderBlockOptions = {
415
+ width: string;
416
+ height: string;
417
+ };
418
+ type ImagePlaceholderImageOptions = {
419
+ aspectRatio: number | string;
420
+ };
421
+ /**
422
+ * A placeholder that can be used instead of an image or other block of content while it's loading.
423
+ * The placeholder has `display:block`, meaning it will create a new "row" in the layout for itself. Can be used either for images with a defined aspect ratio (ContainedImage) or blocks.
424
+ * @property aspectRatio if aspectRatio is defined the placeholder will be in "image mode" and fill out the available width and then adjust the height according to the aspectRatio
425
+ * @property width If width and height is set, the defined width and height will be used.
426
+ * @property height If width and height is set, the defined width and height will be used.
427
+ * @property class extra classes to add to the placeholder
428
+ * @property style extra styles to add to the placeholder
429
+ */
430
+ export function ImagePlaceholder(props: ImagePlaceholderBaseOptions & (ImagePlaceholderBlockOptions | ImagePlaceholderImageOptions)): JSX.Element;
431
+ export function DefaultInstantCardPlaceholder(): HTMLDivElement;
410
432
  export const shopifyContainedImageContextSymbol: unique symbol;
411
433
  /**
412
434
  * Abstraction built on top of ShopifyResponsiveImg. This is your one-stop-shop If you just need a responsive image.
@@ -417,11 +439,13 @@ export const shopifyContainedImageContextSymbol: unique symbol;
417
439
  * @property aspectRatio aspect ratio of the image
418
440
  * @property class extra class to add to the container
419
441
  * @property alt alt text for the image
442
+ * @property autoAdjustAspectRatio whether to automatically adjust the aspect ratio of the image to the majority of the aspect ratios of loaded images in the current listing provider. Defaults to false. Can be overriden with css variable --image-aspect-ratio
420
443
  * @property imgProps props to pass to ShopifyResponsiveImg to add to the <img> element
421
444
  */
422
445
  export function ShopifyContainedImage(props: {
423
446
  src: string;
424
447
  aspectRatio: number | string;
448
+ autoAdjustAspectRatio?: boolean;
425
449
  class?: string;
426
450
  imgProps?: Omit<Parameters<typeof ShopifyResponsiveImg>[0], "size" | "src">;
427
451
  }): HTMLDivElement;
@@ -489,28 +513,6 @@ interface Styles {
489
513
  [selector: string]: JSX.CSSProperties;
490
514
  }
491
515
  export const styles_to_valid_css_string: (styles: Styles) => string;
492
- type ImagePlaceholderBaseOptions = {
493
- style?: JSX.CSSProperties;
494
- class?: string;
495
- };
496
- type ImagePlaceholderBlockOptions = {
497
- width: string;
498
- height: string;
499
- };
500
- type ImagePlaceholderImageOptions = {
501
- aspectRatio: number | string;
502
- };
503
- /**
504
- * A placeholder that can be used instead of an image or other block of content while it's loading.
505
- * The placeholder has `display:block`, meaning it will create a new "row" in the layout for itself. Can be used either for images with a defined aspect ratio (ContainedImage) or blocks.
506
- * @property aspectRatio if aspectRatio is defined the placeholder will be in "image mode" and fill out the available width and then adjust the height according to the aspectRatio
507
- * @property width If width and height is set, the defined width and height will be used.
508
- * @property height If width and height is set, the defined width and height will be used.
509
- * @property class extra classes to add to the placeholder
510
- * @property style extra styles to add to the placeholder
511
- */
512
- export function ImagePlaceholder(props: ImagePlaceholderBaseOptions & (ImagePlaceholderBlockOptions | ImagePlaceholderImageOptions)): JSX.Element;
513
- export function DefaultInstantCardPlaceholder(): HTMLDivElement;
514
516
  /**
515
517
  * Second generation search modal - the solid component that gets added to <body> when the search modal is opened
516
518
  */
@@ -642,7 +644,7 @@ export type BaseSearchProviderConfig<InputDisplay extends Display, PossibleTrans
642
644
  */
643
645
  enableContentSearch?: boolean;
644
646
  /**
645
- * The search modal component to use. You can switch between the classic and the new search modal. Provide one of the components here that you can import from the same package as the one you're using to see this message.
647
+ * The search modal component to use. You can switch between the classic and the new search modal. Provide one of the components here that you can import from the same package as the one you're using to see this message (`SearchModalV2` or `ClassicSearchModal`).
646
648
  * You also need to reflect the choice in SCSS, example:
647
649
  * ```scss
648
650
  * @use "@depict-ai/js-ui" as plp-styling with (
package/ES10/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { add_to_version_info as $8tj43$add_to_version_info, deparallelize_no_drop as $8tj43$deparallelize_no_drop, catchify as $8tj43$catchify, make_random_classname as $8tj43$make_random_classname, ContainedImage as $8tj43$ContainedImage, standard_price_format as $8tj43$standard_price_format, javascript_media_query as $8tj43$javascript_media_query, dlog as $8tj43$dlog, camelCasifyObject as $8tj43$camelCasifyObject, buildThresholdList as $8tj43$buildThresholdList, make_asyncIterable_exiter as $8tj43$make_asyncIterable_exiter, href_change_ipns as $8tj43$href_change_ipns, observer as $8tj43$observer, report as $8tj43$report, base64_encode_unicode as $8tj43$base64_encode_unicode, base64_decode_unicode as $8tj43$base64_decode_unicode, queueMacroTask as $8tj43$queueMacroTask, dwarn as $8tj43$dwarn, slider_fading_factory as $8tj43$slider_fading_factory, Amazing_Slider as $8tj43$Amazing_Slider, slider_snap_css as $8tj43$slider_snap_css, n_col_styling_with_dist as $8tj43$n_col_styling_with_dist, layout_get_visible_recs_without_partial_rows as $8tj43$layout_get_visible_recs_without_partial_rows, layout_get_total_rec_amount_for_row as $8tj43$layout_get_total_rec_amount_for_row, layout_media_query_header as $8tj43$layout_media_query_header, use_href_accessor as $8tj43$use_href_accessor, get_session_id as $8tj43$get_session_id, add_version_query_params as $8tj43$add_version_query_params, base_url as $8tj43$base_url, instant_exec_on_suspect_history_change as $8tj43$instant_exec_on_suspect_history_change, slider_fractional_factory as $8tj43$slider_fractional_factory, useExpandingContainer as $8tj43$useExpandingContainer, hex_to_rgb as $8tj43$hex_to_rgb, relative_luminance_from_rgb as $8tj43$relative_luminance_from_rgb, snakeCasifyObject as $8tj43$snakeCasifyObject, fetch_retry as $8tj43$fetch_retry, make_url_with_query_params as $8tj43$make_url_with_query_params, sort_obj as $8tj43$sort_obj, is_debug as $8tj43$is_debug, ListenableSet as $8tj43$ListenableSet1, insert_surfaces as $8tj43$insert_surfaces } from "@depict-ai/utilishared/ES10";
1
+ import { add_to_version_info as $8tj43$add_to_version_info, deparallelize_no_drop as $8tj43$deparallelize_no_drop, catchify as $8tj43$catchify, make_random_classname as $8tj43$make_random_classname, ContainedImage as $8tj43$ContainedImage, standard_price_format as $8tj43$standard_price_format, javascript_media_query as $8tj43$javascript_media_query, dlog as $8tj43$dlog, camelCasifyObject as $8tj43$camelCasifyObject, buildThresholdList as $8tj43$buildThresholdList, make_asyncIterable_exiter as $8tj43$make_asyncIterable_exiter, href_change_ipns as $8tj43$href_change_ipns, observer as $8tj43$observer, report as $8tj43$report, base64_encode_unicode as $8tj43$base64_encode_unicode, base64_decode_unicode as $8tj43$base64_decode_unicode, ListenableSet as $8tj43$ListenableSet, findMostFrequentItem as $8tj43$findMostFrequentItem, queueMacroTask as $8tj43$queueMacroTask, dwarn as $8tj43$dwarn, slider_fading_factory as $8tj43$slider_fading_factory, Amazing_Slider as $8tj43$Amazing_Slider, slider_snap_css as $8tj43$slider_snap_css, n_col_styling_with_dist as $8tj43$n_col_styling_with_dist, layout_get_visible_recs_without_partial_rows as $8tj43$layout_get_visible_recs_without_partial_rows, layout_get_total_rec_amount_for_row as $8tj43$layout_get_total_rec_amount_for_row, layout_media_query_header as $8tj43$layout_media_query_header, use_href_accessor as $8tj43$use_href_accessor, get_session_id as $8tj43$get_session_id, add_version_query_params as $8tj43$add_version_query_params, base_url as $8tj43$base_url, instant_exec_on_suspect_history_change as $8tj43$instant_exec_on_suspect_history_change, slider_fractional_factory as $8tj43$slider_fractional_factory, useExpandingContainer as $8tj43$useExpandingContainer, hex_to_rgb as $8tj43$hex_to_rgb, relative_luminance_from_rgb as $8tj43$relative_luminance_from_rgb, snakeCasifyObject as $8tj43$snakeCasifyObject, fetch_retry as $8tj43$fetch_retry, make_url_with_query_params as $8tj43$make_url_with_query_params, sort_obj as $8tj43$sort_obj, is_debug as $8tj43$is_debug, insert_surfaces as $8tj43$insert_surfaces } from "@depict-ai/utilishared/ES10";
2
2
  import { createSignal as $8tj43$createSignal, createResource as $8tj43$createResource, createEffect as $8tj43$createEffect, untrack as $8tj43$untrack, createMemo as $8tj43$createMemo, onCleanup as $8tj43$onCleanup, Show as $8tj43$Show, createComputed as $8tj43$createComputed, For as $8tj43$For, getOwner as $8tj43$getOwner, runWithOwner as $8tj43$runWithOwner, on as $8tj43$on, Index as $8tj43$Index, batch as $8tj43$batch, ErrorBoundary as $8tj43$ErrorBoundary, createContext as $8tj43$createContext, useContext as $8tj43$useContext, mergeProps as $8tj43$mergeProps1, createUniqueId as $8tj43$createUniqueId, createRenderEffect as $8tj43$createRenderEffect, createSelector as $8tj43$createSelector, children as $8tj43$children, splitProps as $8tj43$splitProps, createRoot as $8tj43$createRoot, Suspense as $8tj43$Suspense, createReaction as $8tj43$createReaction, mapArray as $8tj43$mapArray } from "solid-js";
3
3
  import { template as $8tj43$template, getNextElement as $8tj43$getNextElement, addEventListener as $8tj43$addEventListener, insert as $8tj43$insert, memo as $8tj43$memo, runHydrationEvents as $8tj43$runHydrationEvents, createComponent as $8tj43$createComponent, getNextMarker as $8tj43$getNextMarker, use as $8tj43$use, effect as $8tj43$effect, classList as $8tj43$classList, setAttribute as $8tj43$setAttribute, delegateEvents as $8tj43$delegateEvents, style as $8tj43$style, className as $8tj43$className, spread as $8tj43$spread, mergeProps as $8tj43$mergeProps, setProperty as $8tj43$setProperty, isServer as $8tj43$isServer, Dynamic as $8tj43$Dynamic } from "solid-js/web";
4
- import { ListenableSet as $8tj43$ListenableSet, catchify as $8tj43$catchify1, use_href_accessor as $8tj43$use_href_accessor1, report as $8tj43$report1 } from "@depict-ai/utilishared/ES10";
4
+ import { ListenableSet as $8tj43$ListenableSet1, catchify as $8tj43$catchify1, use_href_accessor as $8tj43$use_href_accessor1, report as $8tj43$report1 } from "@depict-ai/utilishared/ES10";
5
5
  import $8tj43$babelruntimehelpersdefineProperty from "@babel/runtime/helpers/defineProperty";
6
6
  import $8tj43$babelruntimehelpersclassPrivateFieldSet from "@babel/runtime/helpers/classPrivateFieldSet";
7
7
  import $8tj43$babelruntimehelpersclassPrivateFieldGet from "@babel/runtime/helpers/classPrivateFieldGet";
@@ -10,7 +10,7 @@ import { createStore as $8tj43$createStore, reconcile as $8tj43$reconcile } from
10
10
  /*! Depict.ai search and product listing SDK */
11
11
  import { register_es_version } from "../multi_import_deduplicator.mjs";
12
12
  register_es_version("ui", "ES10");
13
- const $8db9a15135765c11$export$83d89fbfd8236492 = "4.0.0";
13
+ const $8db9a15135765c11$export$83d89fbfd8236492 = "4.0.2";
14
14
  function $a604a8ffa4e4c03f$export$e417c49320921907(dependency, fetcher) {
15
15
  const [promiseOfCurrentFetcherRun, setPromiseOfCurrentFetcherRun] = $8tj43$createSignal();
16
16
  const deparallelizedFetcher = $8tj43$deparallelize_no_drop(async dependencyValue => {
@@ -2451,6 +2451,7 @@ function $56047603f9d212b6$export$e6fffe67d4cdd848(whatToWatch) {
2451
2451
  return size;
2452
2452
  }
2453
2453
  const $56047603f9d212b6$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
2454
+ const $56047603f9d212b6$export$f8945274f08a3105 = /*@__PURE__*/Symbol("listingContextAspectRatios");
2454
2455
  function $56047603f9d212b6$export$6e5611bc7e57e477(props) {
2455
2456
  // Enable reactive props
2456
2457
  const otherOptions = $8tj43$createMemo(() => {
@@ -2515,6 +2516,21 @@ function $56047603f9d212b6$export$6e5611bc7e57e477(props) {
2515
2516
  let timeoutSet = false;
2516
2517
  let gotCleanedUp = false;
2517
2518
  img.classList.add("s-responsive-image");
2519
+ if (listingContext) {
2520
+ let prevValue;
2521
+ const aspectRatios = listingContext[$56047603f9d212b6$export$f8945274f08a3105] || (listingContext[$56047603f9d212b6$export$f8945274f08a3105] = new (0, $8tj43$ListenableSet)());
2522
+ img.addEventListener("load", $8tj43$catchify(() => {
2523
+ // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2
2524
+ const aspectRatio_ = img.naturalWidth / img.naturalHeight;
2525
+ if (prevValue) aspectRatios.delete(prevValue);
2526
+ const newValue = !isNaN(aspectRatio_) ? {
2527
+ aspectRatio_: aspectRatio_
2528
+ } : undefined;
2529
+ if (newValue) aspectRatios.add(newValue);
2530
+ prevValue = newValue;
2531
+ }));
2532
+ $8tj43$onCleanup(() => prevValue && aspectRatios.delete(prevValue));
2533
+ }
2518
2534
  $8tj43$onCleanup(() => gotCleanedUp = true);
2519
2535
  $8tj43$spread(img, $8tj43$mergeProps1(otherOptions), false, true);
2520
2536
  $8tj43$createEffect(() => {
@@ -2582,9 +2598,29 @@ function $4df489344a0f97c7$export$e4b984597b71e989(props) {
2582
2598
  // create a signal that's the same for all items in this listing
2583
2599
  context[$4df489344a0f97c7$export$d7b7ab832c20e2f4] = $8tj43$createSignal();
2584
2600
  const [currentImageSize, setCurrentImageSize] = (context === null || context === void 0 ? void 0 : context[$4df489344a0f97c7$export$d7b7ab832c20e2f4]) || $4df489344a0f97c7$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
2601
+ const aspectRatiosSet = context ? context[(0, $56047603f9d212b6$export$f8945274f08a3105)] || (context[(0, $56047603f9d212b6$export$f8945274f08a3105)] = new (0, $8tj43$ListenableSet)()) : undefined;
2602
+ const [aspectRatios, setAspectRatios] = $8tj43$createSignal(aspectRatiosSet, {
2603
+ equals: false
2604
+ });
2605
+ const aspectRatioToUse = $8tj43$createMemo(() => {
2606
+ const aspectRatiosSet = aspectRatios(); // This signal "changes" to the same set every time the set changes, so we can use it as a dependency here
2607
+ useMostPrevalentAspectRatio: {
2608
+ if (!aspectRatiosSet || !props.autoAdjustAspectRatio) break useMostPrevalentAspectRatio;
2609
+ // Get the aspect ratio that most of the loaded images inside the ListingProvider we are, load
2610
+ const asArray = [...aspectRatiosSet].map(_ref => {
2611
+ let {
2612
+ aspectRatio_: aspectRatio_
2613
+ } = _ref;
2614
+ return aspectRatio_;
2615
+ });
2616
+ const mostPrevalentAspectRatio = $8tj43$findMostFrequentItem(asArray);
2617
+ if (mostPrevalentAspectRatio) return "var(".concat((0, $5eaa00b951637e96$export$8a2234b5b1a5ebd4), ", ").concat(mostPrevalentAspectRatio, ")");
2618
+ }
2619
+ return props.aspectRatio;
2620
+ });
2585
2621
  const container = $8tj43$createComponent((0, $801e8845d3fa3653$export$94026ee33dbabc26), {
2586
2622
  get aspectRatio() {
2587
- return props.aspectRatio;
2623
+ return aspectRatioToUse();
2588
2624
  },
2589
2625
  get ["class"]() {
2590
2626
  return props.class;
@@ -2593,6 +2629,10 @@ function $4df489344a0f97c7$export$e4b984597b71e989(props) {
2593
2629
  const owner = $8tj43$getOwner();
2594
2630
  let createdSizeAccessor = false;
2595
2631
  let wasCleanedUp = false;
2632
+ for (const event of ["add", "delete"]) {
2633
+ aspectRatiosSet === null || aspectRatiosSet === void 0 || aspectRatiosSet.addEventListener(event, () => setAspectRatios(aspectRatiosSet));
2634
+ $8tj43$onCleanup(() => aspectRatiosSet === null || aspectRatiosSet === void 0 ? void 0 : aspectRatiosSet.removeEventListener(event, () => setAspectRatios(aspectRatiosSet)));
2635
+ }
2596
2636
  $8tj43$createEffect(() => {
2597
2637
  if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
2598
2638
  // ensure we always have a size accessor
@@ -3660,7 +3700,8 @@ function $06fcd2a345efd24d$var$RawSearchModalV2(_ref) {
3660
3700
  get src() {
3661
3701
  return props.src_;
3662
3702
  },
3663
- aspectRatio: "var(".concat((0, $5eaa00b951637e96$export$8a2234b5b1a5ebd4), ", 1)")
3703
+ autoAdjustAspectRatio: true,
3704
+ aspectRatio: 1
3664
3705
  }),
3665
3706
  ...instant_results_options_
3666
3707
  }), _el$4, _co$);
@@ -3841,7 +3882,7 @@ const $6a439680ae7e9ba3$var$TabsContext = /*@__PURE__*/$8tj43$createContext();
3841
3882
  const $6a439680ae7e9ba3$var$useTabs = () => $8tj43$useContext($6a439680ae7e9ba3$var$TabsContext);
3842
3883
  function $6a439680ae7e9ba3$export$b2539bed5023c21c(props) {
3843
3884
  return $8tj43$createComponent($6a439680ae7e9ba3$var$TabsContext.Provider, {
3844
- value: new (0, $8tj43$ListenableSet)(),
3885
+ value: new (0, $8tj43$ListenableSet1)(),
3845
3886
  get children() {
3846
3887
  return $8tj43$createComponent($6a439680ae7e9ba3$var$ActualTabs, $8tj43$mergeProps(props, {
3847
3888
  get children() {
@@ -4012,7 +4053,17 @@ async function $d5f1e6a0f9117286$export$79b1565500412d9b(search_modal, modal_fn_
4012
4053
  const actually_close = () => {
4013
4054
  dispose();
4014
4055
  on_dispose === null || on_dispose === void 0 || on_dispose();
4015
- modal_els.forEach(el => el.remove());
4056
+ const {
4057
+ activeElement: activeElement
4058
+ } = document;
4059
+ modal_els.forEach(el => {
4060
+ if (el.contains(activeElement)) {
4061
+ var _blur, _ref;
4062
+ // Fix page jumping to the bottom when closing modal with scape after animation in safari
4063
+ activeElement === null || activeElement === void 0 || (_blur = (_ref = activeElement).blur) === null || _blur === void 0 || _blur.call(_ref);
4064
+ }
4065
+ el.remove();
4066
+ });
4016
4067
  };
4017
4068
  if (animation_started && +new Date() - animation_started > 1000)
4018
4069
  // Animation broke, close it this time
@@ -13295,7 +13346,7 @@ function $d53ebed6f63304e4$export$6d0c9c22f6652669(_ref) {
13295
13346
  number_: num_results,
13296
13347
  i18n_: i18n_
13297
13348
  });
13298
- const queries_without_content_results_ = new (0, $8tj43$ListenableSet1)();
13349
+ const queries_without_content_results_ = new (0, $8tj43$ListenableSet)();
13299
13350
  const [check_query, set_check_query] = $8tj43$createSignal(false);
13300
13351
  const placeholders_enabled = $8tj43$createMemo(() => {
13301
13352
  // don't show placeholders when the user toggles filters
@@ -13397,11 +13448,22 @@ function $937791b86d3d1509$export$44f738469d5570cf(_ref) {
13397
13448
  modalSearchFieldOuterWidth_: modalSearchFieldOuterWidth_
13398
13449
  } = _ref;
13399
13450
  return $8tj43$createRoot(dispose => {
13451
+ const [innerWidthReactive, setInnerWidthReactive] = $8tj43$createSignal(innerWidth);
13452
+ const resizeObserver = new ResizeObserver(records => setInnerWidthReactive(records.at(-1).contentRect.width));
13453
+ const {
13454
+ left: left,
13455
+ top: top,
13456
+ width: width
13457
+ } = actualField_.getBoundingClientRect();
13400
13458
  const fakeField = makeFakeField_();
13401
13459
  const owner = $8tj43$getOwner();
13402
13460
  const inModalFieldWidth = $8tj43$createMemo(
13403
13461
  // Can't have `min(${modalSearchFieldOuterWidth_()}px, var(--field-max-width, 600px))` because the WAAPI doesn't support that, so we need ot calculate it in JS
13404
- () => Math.min(modalSearchFieldOuterWidth_(), parseFloat(getComputedStyle(actualField_).getPropertyValue("--field-max-width") || "600")) + "px");
13462
+ () => Math.min(modalSearchFieldOuterWidth_(), parseFloat(getComputedStyle(actualField_).getPropertyValue("--field-max-width") || "600")));
13463
+ const inModalFieldWidthPx = $8tj43$createMemo(() => inModalFieldWidth() + "px");
13464
+ let disableResizePollingTimeout;
13465
+ resizeObserver.observe(document.documentElement);
13466
+ $8tj43$onCleanup(() => resizeObserver.disconnect());
13405
13467
  actualField_.replaceWith(fakeField);
13406
13468
  // Don't move the wrapped div since that would confuse run_in_root_or_auto_cleanup, but do actually move the field the user clicked around so that all selection stuff etc. is easier
13407
13469
  const addedToBody = wrap_ ? (() => {
@@ -13410,21 +13472,17 @@ function $937791b86d3d1509$export$44f738469d5570cf(_ref) {
13410
13472
  return _el$;
13411
13473
  })() : actualField_;
13412
13474
  document.body.append(addedToBody);
13413
- const {
13414
- left: left,
13415
- top: top,
13416
- width: width
13417
- } = fakeField.getBoundingClientRect();
13418
13475
  const zIndexOfFake = getComputedStyle(fakeField).zIndex;
13419
13476
  Object.assign(addedToBody.style, {
13420
13477
  position: "fixed",
13421
13478
  top: top + "px",
13479
+ left: left + "px",
13422
13480
  width: width + "px",
13423
13481
  ...(zIndexOfFake !== "auto" ? {
13424
13482
  zIndex: +zIndexOfFake + 1
13425
13483
  } : {})
13426
13484
  });
13427
- const pxOffCenter = innerWidth / 2 - (left + width / 2);
13485
+ const pxOffCenter = $8tj43$untrack(innerWidthReactive) / 2 - (left + width / 2);
13428
13486
  const openDuration = pxOffCenter > 100 ? 250 : 125; // faster animations if little left-right movement
13429
13487
  const closeDuration = pxOffCenter > 100 ? 150 : 100;
13430
13488
  setPollAlignment_(true);
@@ -13443,24 +13501,30 @@ function $937791b86d3d1509$export$44f738469d5570cf(_ref) {
13443
13501
  // Wait until the ResizeObserver has delivered a value in case that the modal is small or has much padding so we know that we can't animate our fake field to be wider than that
13444
13502
  addedToBody.animate([{
13445
13503
  left: left + "px",
13446
- transform: "translateX(0%)",
13447
13504
  width: width + "px"
13448
13505
  }, {
13449
- left: "50%",
13450
- transform: "translateX(-50%)",
13451
- width: $8tj43$untrack(inModalFieldWidth)
13506
+ left: "".concat($8tj43$untrack(innerWidthReactive) / 2 - $8tj43$untrack(inModalFieldWidth) / 2, "px"),
13507
+ width: $8tj43$untrack(inModalFieldWidthPx)
13452
13508
  }], {
13453
13509
  duration: openDuration,
13454
13510
  easing: "ease-in"
13455
13511
  }).finished.then(() => {
13456
13512
  setPollAlignment_(false);
13457
- $8tj43$runWithOwner(owner, () => $8tj43$createEffect(() =>
13458
- // When animation has finished, still dynamically set the size of the search field behind in case the user resizes the window
13459
- Object.assign(addedToBody.style, {
13460
- left: "50%",
13461
- transform: "translateX(-50%)",
13462
- width: inModalFieldWidth()
13463
- })));
13513
+ $8tj43$runWithOwner(owner, () => $8tj43$createEffect(() => {
13514
+ // When animation has finished, still dynamically set the size of the search field behind in case the user resizes the window
13515
+ Object.assign(addedToBody.style, {
13516
+ // This is left: 50%, transform: translateX(-50) with extra steps but when using it safari and firefox glitch out like crazy
13517
+ left: "".concat(innerWidthReactive() / 2 - inModalFieldWidth() / 2, "px"),
13518
+ width: inModalFieldWidthPx()
13519
+ });
13520
+ // We might only have changed the left position which align_field doesn't know about, make it poll the position for a while
13521
+ setPollAlignment_(true);
13522
+ if (disableResizePollingTimeout) clearTimeout(disableResizePollingTimeout);
13523
+ disableResizePollingTimeout = setTimeout($8tj43$catchify(() => {
13524
+ setPollAlignment_(false);
13525
+ disableResizePollingTimeout = undefined;
13526
+ }), 1000);
13527
+ }));
13464
13528
  });
13465
13529
  return true;
13466
13530
  }, false);
@@ -13503,13 +13567,11 @@ function $937791b86d3d1509$export$44f738469d5570cf(_ref) {
13503
13567
  transition: "opacity ".concat(closeDuration, "ms ease-out")
13504
13568
  }));
13505
13569
  await Promise.all([addedToBody.animate([{
13506
- width: $8tj43$untrack(inModalFieldWidth),
13507
- left: "50%",
13508
- transform: "translateX(-50%)"
13570
+ width: $8tj43$untrack(inModalFieldWidthPx),
13571
+ left: "".concat($8tj43$untrack(innerWidthReactive) / 2 - $8tj43$untrack(inModalFieldWidth) / 2, "px")
13509
13572
  }, {
13510
13573
  width: width + "px",
13511
- left: left + "px",
13512
- transform: "translateX(0%)"
13574
+ left: left + "px"
13513
13575
  }], {
13514
13576
  duration: closeDuration,
13515
13577
  fill: "forwards",