@depict-ai/ui 4.10.19 → 4.10.21

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.
@@ -7,7 +7,7 @@ import { createStore as $i7OB2$createStore, reconcile as $i7OB2$reconcile } from
7
7
  /*! Depict.ai search and product listing SDK */
8
8
  import { register_es_version } from "../../multi_import_deduplicator.mjs";
9
9
  register_es_version("ui", "latest");
10
- const $ec291e0010116877$export$83d89fbfd8236492 = "4.10.19";
10
+ const $ec291e0010116877$export$83d89fbfd8236492 = "4.10.21";
11
11
  function $dc9262ef6f786812$export$d9f36cf74e24d595(media_query) {
12
12
  const signal = $i7OB2$createSignal(false);
13
13
  $i7OB2$onCleanup($i7OB2$javascript_media_query(media_query, ({
@@ -2020,6 +2020,61 @@ function $1adfe60f3a14a1d7$export$fecbb157621501bd({
2020
2020
  }));
2021
2021
  return outmost_element;
2022
2022
  }
2023
+
2024
+ /**
2025
+ * `HTMLElement.focus()` is a **silent no-op** on an element that is not being rendered
2026
+ * (`display: none`, `visibility: hidden`, a collapsed menu). Nothing throws, focus simply
2027
+ * stays where it was, so a caller that does not check believes it restored focus when it
2028
+ * left it on `<body>` — which puts the keyboard user back at the top of the document.
2029
+ *
2030
+ * That is reachable whenever the element which opened a modal stops being rendered while the
2031
+ * modal is open, and the common way for that to happen is the responsive-duplicate header:
2032
+ * a theme renders the same search trigger twice, once for desktop and once for mobile, and
2033
+ * hides one at the current breakpoint. Open the modal from the desktop trigger, cross the
2034
+ * breakpoint (rotate a tablet, resize a window), close the modal, and the remembered trigger
2035
+ * is still `isConnected` but no longer rendered. Verified against a live merchant storefront
2036
+ * on 4.10.19.
2037
+ *
2038
+ * So: verify that focus landed, and when it did not, look for a rendered twin of the same
2039
+ * control — the other half of the responsive pair — and use that instead.
2040
+ */ /**
2041
+ * An element can only take focus if it is actually being rendered.
2042
+ *
2043
+ * Injectable because it is the one part of this module that needs a layout engine: jsdom
2044
+ * reports no client rects for anything, so the specs pass their own predicate to exercise the
2045
+ * matching rules. The real predicate is only exercised in a browser.
2046
+ */
2047
+ const $07001c226aedc5fb$export$e0652711c614c755 = element => !!element.getClientRects().length;
2048
+ /**
2049
+ * `document.activeElement` is the outermost shadow host when focus is inside a shadow tree,
2050
+ * so ask the element's own root rather than the document — matching how the rest of
2051
+ * modal_opener treats shadow-mounted modals.
2052
+ */
2053
+ const $07001c226aedc5fb$var$has_focus = element => element.getRootNode().activeElement === element;
2054
+ /**
2055
+ * The accessible-name-ish identity we match twins on. Deliberately narrow: an explicit label
2056
+ * or the trimmed text. Two controls that share a tag and this string are the same control
2057
+ * rendered twice, which is exactly the responsive-duplicate case.
2058
+ */
2059
+ const $07001c226aedc5fb$var$identity_of = element => (element.getAttribute("aria-label") || element.getAttribute("title") || element.textContent || "").trim().replace(/\s+/g, " ");
2060
+ function $07001c226aedc5fb$export$5800d9d535a06e96(element, rendered = $07001c226aedc5fb$export$e0652711c614c755) {
2061
+ const identity = $07001c226aedc5fb$var$identity_of(element);
2062
+ if (!identity) return; // nothing to match on — an icon-only button with no label
2063
+ const twins = [...element.ownerDocument.querySelectorAll(element.localName)].filter(candidate => candidate !== element && rendered(candidate) && $07001c226aedc5fb$var$identity_of(candidate) === identity);
2064
+ return twins.length === 1 ? twins[0] : undefined;
2065
+ }
2066
+ function $07001c226aedc5fb$export$51461d633c351649(element, rendered = $07001c226aedc5fb$export$e0652711c614c755) {
2067
+ element.focus({
2068
+ preventScroll: true
2069
+ });
2070
+ if ($07001c226aedc5fb$var$has_focus(element)) return true;
2071
+ const twin = $07001c226aedc5fb$export$5800d9d535a06e96(element, rendered);
2072
+ if (!twin) return false;
2073
+ twin.focus({
2074
+ preventScroll: true
2075
+ });
2076
+ return $07001c226aedc5fb$var$has_focus(twin);
2077
+ }
2023
2078
  async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_opts, parent) {
2024
2079
  const body = parent || document.body || (await (0, $i7OB2$observer).wait_for_element("body"));
2025
2080
  let dispose_and_remove;
@@ -2049,6 +2104,7 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2049
2104
  const modal_els = $i7OB2$createRoot(dispose => {
2050
2105
  let closing_animation;
2051
2106
  let animation_started;
2107
+ let focus_target_after_close;
2052
2108
  dispose_and_remove = () => {
2053
2109
  const actually_close = () => {
2054
2110
  dispose();
@@ -2067,13 +2123,24 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2067
2123
  activeElement?.blur?.();
2068
2124
  el.remove();
2069
2125
  });
2070
- if (should_restore_focus && element_focused_before_open?.isConnected) {
2126
+ const requested_focus_target = focus_target_after_close?.();
2127
+ if (should_restore_focus && (requested_focus_target?.isConnected || element_focused_before_open?.isConnected)) {
2071
2128
  restoring_focus = true;
2072
2129
  try {
2073
2130
  // preventScroll so this can't re-introduce the safari page-jump the blur() above works around
2074
- element_focused_before_open.focus({
2075
- preventScroll: true
2076
- });
2131
+ let focused = false;
2132
+ if (requested_focus_target?.isConnected) {
2133
+ requested_focus_target.focus({
2134
+ preventScroll: true
2135
+ });
2136
+ focused = requested_focus_target.getRootNode().activeElement === requested_focus_target;
2137
+ }
2138
+ if (!focused && element_focused_before_open?.isConnected)
2139
+ // restore_focus_to rather than a bare focus(): the remembered trigger can be
2140
+ // connected but no longer rendered (a responsive-duplicate header whose other
2141
+ // half is showing now), and focus() on an unrendered element silently does
2142
+ // nothing, leaving the keyboard user at the top of the page.
2143
+ $07001c226aedc5fb$export$51461d633c351649(element_focused_before_open);
2077
2144
  } finally {
2078
2145
  // Cleared on a task instead of synchronously in case a browser delivers the focus event async
2079
2146
  setTimeout(() => restoring_focus = false, 0);
@@ -2092,7 +2159,8 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2092
2159
  ...extra_options_for_modal,
2093
2160
  close_modal_: close_modal_,
2094
2161
  open_modal_: open_modal_,
2095
- register_closing_animation_: animation => closing_animation = animation
2162
+ register_closing_animation_: animation => closing_animation = animation,
2163
+ set_focus_target_after_close_: get_target => focus_target_after_close = get_target
2096
2164
  });
2097
2165
  });
2098
2166
  body.append(...modal_els);
@@ -7477,16 +7545,20 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
7477
7545
  * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
7478
7546
  */ /**
7479
7547
  * 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
7480
- */
7481
- #throwing_on_navigation(...args) {
7548
+ */ /**
7549
+ * Called when a go_to_ didn't change location.href, for example when following a link to the page one is already on. href_change_ipns stays silent then, so whoever waits for a href change to react to a navigation has to listen here too
7550
+ */
7551
+ navigation_to_same_href_listeners_ = new Set();
7552
+ #throwing_on_navigation(options, on_throw_) {
7482
7553
  const {
7483
7554
  on_navigation_: on_navigation_
7484
7555
  } = this;
7485
7556
  if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
7486
7557
  // make sure that we don't accidentally catchify if the SDK consumer has fucked up
7487
7558
  try {
7488
- return on_navigation_(...args);
7559
+ return on_navigation_(options);
7489
7560
  } catch (e) {
7561
+ on_throw_?.();
7490
7562
  queueMicrotask(() => {
7491
7563
  throw e;
7492
7564
  });
@@ -7507,6 +7579,28 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
7507
7579
  (0, $i7OB2$instant_exec_on_suspect_history_change).add(handler);
7508
7580
  });
7509
7581
  }
7582
+ /**
7583
+ * Calls navigation_to_same_href_listeners_ if the navigation we're about to request ends on the href we're already on
7584
+ * @returns function to stop watching, call it when the navigation failed
7585
+ */
7586
+ #watch_for_navigation_to_same_href(target_url) {
7587
+ const href_before = location.href;
7588
+ const stop_watching = () => {
7589
+ (0, $i7OB2$instant_exec_on_suspect_history_change).delete(on_history_change);
7590
+ clearTimeout(timeout);
7591
+ };
7592
+ const notify_if_href_unchanged = $i7OB2$catchify1(() => {
7593
+ stop_watching();
7594
+ if (location.href !== href_before) return;
7595
+ this.navigation_to_same_href_listeners_.forEach(listener => $i7OB2$catchify1(listener)());
7596
+ });
7597
+ // The router has acted once it touches history, if the href is still the same then it took us to the page we're on
7598
+ const on_history_change = () => notify_if_href_unchanged();
7599
+ // A router asked to go to the exact href we're on might not touch history at all, so don't wait longer than 500ms for it. For any other target we can't tell a slow navigation from one that goes nowhere, so only stop listening after a while
7600
+ const timeout = target_url.href === href_before ? setTimeout(notify_if_href_unchanged, 500) : setTimeout(stop_watching, 10000);
7601
+ (0, $i7OB2$instant_exec_on_suspect_history_change).add(on_history_change);
7602
+ return stop_watching;
7603
+ }
7510
7604
  navigate_ = {
7511
7605
  /**
7512
7606
  * Call this if you *just* want to replace the state object in history.state
@@ -7546,6 +7640,7 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
7546
7640
  }
7547
7641
  event_?.preventDefault();
7548
7642
  const promise = this.#get_navigation_happened_promise(true);
7643
+ const stop_watching_for_same_href = this.#watch_for_navigation_to_same_href(new_url_);
7549
7644
  if (force_spa_navigation_ && wants_hard_navigation) {
7550
7645
  // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
7551
7646
  const new_state = history.state;
@@ -7559,7 +7654,7 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
7559
7654
  is_replace: is_replace_,
7560
7655
  new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.href),
7561
7656
  scroll: scroll
7562
- });
7657
+ }, stop_watching_for_same_href);
7563
7658
  await promise;
7564
7659
  })
7565
7660
  };
@@ -8738,6 +8833,7 @@ function $081752ca508a876f$export$f7658c347b037c3f(props = {}) {
8738
8833
  var $5285d2814d0fac0c$var$_tmpl$ = ["<div", ' style="', '" class="spacer"></div>'],
8739
8834
  $5285d2814d0fac0c$var$_tmpl$2 = ['<div class="field"><!--$-->', "<!--/-->", "<!--$-->", "<!--/--></div>"],
8740
8835
  $5285d2814d0fac0c$var$_tmpl$3 = ["<button", ' class="submit major" type="button"', ">", "</button>"];
8836
+ const $5285d2814d0fac0c$var$keys_not_opening_modal = new Set(["Tab", "Shift", "Control", "Alt", "AltGraph", "Meta", "CapsLock", "Escape", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "PageUp", "PageDown", "Home", "End", "Insert", "ContextMenu", "NumLock", "ScrollLock", "Pause", "PrintScreen"]);
8741
8837
  function $5285d2814d0fac0c$export$b94867ecbd698f21({
8742
8838
  search_field_value_: [searchFieldValue, setSearchFieldValue],
8743
8839
  input_field_ref_: input_field_ref_,
@@ -8856,11 +8952,17 @@ var $ffb84ffbf4014982$var$_tmpl$ = ["<svg", ' xmlns="http://www.w3.org/2000/svg"
8856
8952
  function $ffb84ffbf4014982$export$8d8893ffd8aca39a() {
8857
8953
  return $i7OB2$ssr($ffb84ffbf4014982$var$_tmpl$, $i7OB2$ssrHydrationKey());
8858
8954
  }
8859
- function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url_param_name_) {
8955
+ function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url_param_name_, router_) {
8860
8956
  const [exit_iterable, exitable_iterable] = $i7OB2$make_asyncIterable_exiter((0, $i7OB2$href_change_ipns));
8957
+ const {
8958
+ navigation_to_same_href_listeners_: navigation_to_same_href_listeners_
8959
+ } = router_;
8861
8960
  let set_initial_values = false;
8862
8961
  let old_pathname;
8863
8962
  let old_param_value;
8963
+ // A card linking to the page one is already on doesn't change the href, close the modal anyway so the click does something
8964
+ navigation_to_same_href_listeners_.add(close_modal);
8965
+ $i7OB2$onCleanup(() => navigation_to_same_href_listeners_.delete(close_modal));
8864
8966
  $i7OB2$onCleanup($i7OB2$catchify1(exit_iterable));
8865
8967
  $i7OB2$catchify1(async () => {
8866
8968
  for await (const href of exitable_iterable) {
@@ -8879,6 +8981,31 @@ function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url
8879
8981
  }
8880
8982
  })();
8881
8983
  }
8984
+ function $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
8985
+ props_search_field_value_: props_search_field_value_,
8986
+ props_submit_query_: props_submit_query_,
8987
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
8988
+ set_focus_target_after_close_: set_focus_target_after_close_,
8989
+ get_search_page_input_element_: get_search_page_input_element_
8990
+ }) {
8991
+ const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $i7OB2$createSignal("") : props_search_field_value_;
8992
+ let submits_in_flight = 0;
8993
+ const submit_query_ = async (new_query = $i7OB2$untrack(search_field_value_[0])) => {
8994
+ submits_in_flight++;
8995
+ try {
8996
+ return await props_submit_query_(new_query, () => set_focus_target_after_close_(get_search_page_input_element_));
8997
+ } finally {
8998
+ submits_in_flight--;
8999
+ }
9000
+ };
9001
+ if (dont_sync_search_field_value_except_on_submit_) $i7OB2$createEffect($i7OB2$on(search_field_value_[0], value => submits_in_flight > 0 && props_search_field_value_[1](value), {
9002
+ defer: true
9003
+ }));
9004
+ return {
9005
+ search_field_value_: search_field_value_,
9006
+ submit_query_: submit_query_
9007
+ };
9008
+ }
8882
9009
  var $42912431795f188e$var$_tmpl$ = ["<div", ' class="discover-more"><button class="major" type="button">', "</button></div>"],
8883
9010
  $42912431795f188e$var$_tmpl$2 = ["<b", ">", "</b>"],
8884
9011
  $42912431795f188e$var$_tmpl$3 = ["<div", ' class="', '"><div class="', '" role="search" aria-label="Search modal with search field, query suggestions and result preview"><!--$-->', '<!--/--><div id="depict-suggestions-and-result-preview" class="padded"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div><!--$-->", "<!--/--></div><!--$-->", "<!--/--></div>"],
@@ -8892,6 +9019,8 @@ function $42912431795f188e$var$RawClassicSearchModal({
8892
9019
  search_query_url_param_name_: search_query_url_param_name_,
8893
9020
  previous_searches_: previous_searches_,
8894
9021
  close_modal_: close_modal_,
9022
+ set_focus_target_after_close_: set_focus_target_after_close_,
9023
+ get_search_page_input_element_: get_search_page_input_element_,
8895
9024
  depict_api_: depict_api_,
8896
9025
  merchant_: merchant_,
8897
9026
  market_: market_,
@@ -8916,15 +9045,16 @@ function $42912431795f188e$var$RawClassicSearchModal({
8916
9045
  // As per feedback from stronger we sometimes want a modal with the search field value disconnected from the one in the rest of the UI, see https://depictaiworkspace.slack.com/archives/C02J16R9XEH/p1679065878487709.
8917
9046
  // This is desired for when the modal is opened from a UI element that visually does not look connected with the search page or current query
8918
9047
  // Basically the UI signals that the button that opens the modal starts a new search.
8919
- const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $i7OB2$createSignal("") : props_search_field_value;
8920
- const propagate_search_field_value_back = dont_sync_search_field_value_except_on_submit_ ? () => props_search_field_value[1]($i7OB2$untrack(search_field_value_[0])) // Set actual search field value to the throwaway internal one before submitting
8921
- : undefined;
8922
- const submit_query_ = (...args) => {
8923
- // submit_query expects to read the current search field value which is why we have to write the current one to the signal before calling it
8924
- // It will write the old one back and then write the new one after submit
8925
- propagate_search_field_value_back?.();
8926
- return props_submit_query(...args);
8927
- };
9048
+ const {
9049
+ search_field_value_: search_field_value_,
9050
+ submit_query_: submit_query_
9051
+ } = $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
9052
+ props_search_field_value_: props_search_field_value,
9053
+ props_submit_query_: props_submit_query,
9054
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
9055
+ set_focus_target_after_close_: set_focus_target_after_close_,
9056
+ get_search_page_input_element_: get_search_page_input_element_
9057
+ });
8928
9058
  const [input_field, set_input_field] = $i7OB2$createSignal();
8929
9059
  const [get_search_field_value_] = search_field_value_;
8930
9060
  // Search field alignment unused in ClassicSearchModal since the search field spans the whole modal
@@ -8977,7 +9107,7 @@ function $42912431795f188e$var$RawClassicSearchModal({
8977
9107
  }
8978
9108
  })));
8979
9109
  if (disable_scrolling_) $aea1edf92433e81e$export$fe334901e8bebd57();
8980
- $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_);
9110
+ $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_, router_);
8981
9111
  window.addEventListener("keydown", close_on_escape_handler);
8982
9112
  $i7OB2$onCleanup($i7OB2$catchify1(() => window.removeEventListener("keydown", close_on_escape_handler)));
8983
9113
  if (closing_animation_) register_closing_animation_(closing_animation_);
@@ -9522,6 +9652,8 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
9522
9652
  search_query_url_param_name_: search_query_url_param_name_,
9523
9653
  previous_searches_: previous_searches_,
9524
9654
  close_modal_: close_modal_,
9655
+ set_focus_target_after_close_: set_focus_target_after_close_,
9656
+ get_search_page_input_element_: get_search_page_input_element_,
9525
9657
  alignmentSignals_: alignmentSignals_,
9526
9658
  depict_api_: depict_api_,
9527
9659
  merchant_: merchant_,
@@ -9552,15 +9684,16 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
9552
9684
  // As per feedback from stronger we sometimes want a modal with the search field value disconnected from the one in the rest of the UI, see https://depictaiworkspace.slack.com/archives/C02J16R9XEH/p1679065878487709.
9553
9685
  // This is desired for when the modal is opened from a UI element that visually does not look connected with the search page or current query
9554
9686
  // Basically the UI signals that the button that opens the modal starts a new search.
9555
- const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $i7OB2$createSignal("") : props_search_field_value;
9556
- const propagate_search_field_value_back = dont_sync_search_field_value_except_on_submit_ ? () => props_search_field_value[1]($i7OB2$untrack(search_field_value_[0])) // Set actual search field value to the throwaway internal one before submitting
9557
- : undefined;
9558
- const submit_query_ = (...args) => {
9559
- // submit_query expects to read the current search field value which is why we have to write the current one to the signal before calling it
9560
- // It will write the old one back and then write the new one after submit
9561
- propagate_search_field_value_back?.();
9562
- return props_submit_query(...args);
9563
- };
9687
+ const {
9688
+ search_field_value_: search_field_value_,
9689
+ submit_query_: submit_query_
9690
+ } = $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
9691
+ props_search_field_value_: props_search_field_value,
9692
+ props_submit_query_: props_submit_query,
9693
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
9694
+ set_focus_target_after_close_: set_focus_target_after_close_,
9695
+ get_search_page_input_element_: get_search_page_input_element_
9696
+ });
9564
9697
  const [input_field, set_input_field] = $i7OB2$createSignal();
9565
9698
  const [searching_for_value_, set_searching_for_value_] = $i7OB2$createSignal();
9566
9699
  const [show_stale_content_results_, set_show_stale_content_results_] = $i7OB2$createSignal(false);
@@ -9667,7 +9800,7 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
9667
9800
  });
9668
9801
  const noResults = $i7OB2$createMemo(prev => (get_modal_search_results_()?.loading === false && !suggestions_response_.loading || !!prev) && totalNumberResults() === 0 && previous_searches_matching_query().length === 0);
9669
9802
  if (disable_scrolling_) $aea1edf92433e81e$export$fe334901e8bebd57();
9670
- $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_);
9803
+ $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_, router_);
9671
9804
  addEventListener("keydown", close_on_escape_handler);
9672
9805
  $i7OB2$onCleanup(() => removeEventListener("keydown", close_on_escape_handler));
9673
9806
  $i7OB2$createEffect($i7OB2$on(get_search_field_value_, () => {
@@ -11388,11 +11521,12 @@ function $21f51c14cb3f586f$export$84bba84a7b837187(read_search_query) {
11388
11521
  async function $bfd908d13d90934c$export$e16630ecb9644a1c({
11389
11522
  on_submit_with_unchanged_value_: on_submit_with_unchanged_value_,
11390
11523
  search_param_name_: search_param_name_,
11391
- set_search_field_value_: set_search_field_value_,
11524
+ search_field_value_: search_field_value_,
11392
11525
  get_search_query_: get_search_query_,
11393
11526
  url_transformer_: url_transformer_,
11394
11527
  router_: router_,
11395
11528
  after_submit_: after_submit_,
11529
+ before_navigate_: before_navigate_,
11396
11530
  get_new_query: get_new_query
11397
11531
  }) {
11398
11532
  const new_search_query = get_new_query();
@@ -11400,21 +11534,89 @@ async function $bfd908d13d90934c$export$e16630ecb9644a1c({
11400
11534
  if (previous_query === new_search_query && new URLSearchParams(location.search).has(search_param_name_)) {
11401
11535
  // don't push a history entry / re-search if someone submits a search again
11402
11536
  // do close the modal though
11537
+ search_field_value_.settle_(new_search_query);
11403
11538
  on_submit_with_unchanged_value_?.();
11404
- return;
11539
+ return false;
11405
11540
  }
11406
- set_search_field_value_(previous_query); // restore the value to the previous query since this one goes to the new history entry
11407
11541
  const target_url = new URL(location.href);
11408
11542
  url_transformer_?.(target_url);
11409
11543
  target_url.searchParams.set(search_param_name_, new_search_query);
11410
- await router_.navigate_.go_to_({
11411
- new_url_: target_url,
11412
- is_replace_: false,
11413
- force_spa_navigation_: true
11414
- });
11415
- set_search_field_value_(new_search_query);
11544
+ const end_submit = search_field_value_.begin_submit_(new_search_query, previous_query);
11545
+ before_navigate_?.();
11546
+ let landed;
11547
+ try {
11548
+ await router_.navigate_.go_to_({
11549
+ new_url_: target_url,
11550
+ is_replace_: false,
11551
+ force_spa_navigation_: true
11552
+ });
11553
+ } finally {
11554
+ landed = end_submit();
11555
+ }
11556
+ if (!landed) return false;
11416
11557
  scrollTo(0, 0);
11417
11558
  after_submit_?.();
11559
+ return true;
11560
+ }
11561
+ function $a578366fad1bde47$export$d13a185c53aa5edf(persisted_, get_search_query_) {
11562
+ const [get_persisted, set_persisted] = persisted_;
11563
+ const [get_submitting, set_submitting] = $i7OB2$createSignal();
11564
+ const get_value = $i7OB2$createMemo(() => get_submitting() ?? get_persisted());
11565
+ const set_value = value => {
11566
+ const new_value = typeof value === "function" ? value($i7OB2$untrack(get_value)) : value;
11567
+ if ($i7OB2$untrack(get_submitting) === undefined) set_persisted(new_value);else set_submitting(new_value);
11568
+ return new_value;
11569
+ };
11570
+ let current_submit;
11571
+ const end_submit = landed => {
11572
+ current_submit.landed_ = landed;
11573
+ current_submit = undefined;
11574
+ $i7OB2$batch(() => {
11575
+ const submitting = $i7OB2$untrack(get_submitting);
11576
+ set_submitting(undefined);
11577
+ if (landed && submitting !== undefined) set_persisted(submitting);
11578
+ });
11579
+ };
11580
+ const abort_on_popstate = what_happened => {
11581
+ if (what_happened === "popstate" && current_submit) end_submit(false);
11582
+ };
11583
+ (0, $i7OB2$instant_exec_on_suspect_history_change).add(abort_on_popstate);
11584
+ $i7OB2$onCleanup(() => (0, $i7OB2$instant_exec_on_suspect_history_change).delete(abort_on_popstate));
11585
+ $i7OB2$createEffect($i7OB2$on(get_search_query_, query => {
11586
+ const token = current_submit;
11587
+ if (!token || query !== token.query_) return;
11588
+ queueMicrotask(() => {
11589
+ if (current_submit === token) end_submit(true);
11590
+ });
11591
+ }, {
11592
+ defer: true
11593
+ }));
11594
+ const begin_submit_ = (submitted_query, query_of_current_history_entry) => {
11595
+ const token = current_submit = {
11596
+ query_: submitted_query,
11597
+ landed_: false
11598
+ };
11599
+ $i7OB2$batch(() => {
11600
+ set_submitting(submitted_query);
11601
+ set_persisted(query_of_current_history_entry);
11602
+ });
11603
+ return () => {
11604
+ if (current_submit === token) end_submit(true);
11605
+ return token.landed_;
11606
+ };
11607
+ };
11608
+ const settle_ = query => {
11609
+ if (current_submit) return;
11610
+ $i7OB2$batch(() => {
11611
+ set_submitting(undefined);
11612
+ set_persisted(query);
11613
+ });
11614
+ };
11615
+ return {
11616
+ value_: [get_value, set_value],
11617
+ begin_submit_: begin_submit_,
11618
+ settle_: settle_
11619
+ };
11418
11620
  }
11419
11621
  function $d68658730065de95$export$181cceed5c91919e(callback, alsoRaF, passiveListener) {
11420
11622
  let aligned_this_microtask = false;
@@ -12050,6 +12252,7 @@ function $7097477c78a89208$export$a54ec244c8863715({
12050
12252
  scroll_restoration_data_: scroll_restoration_data_,
12051
12253
  product_card_template_: product_card_template_,
12052
12254
  modalAlignmentSignalsRef_: modalAlignmentSignalsRef_,
12255
+ inputFieldRef_: inputFieldRef_,
12053
12256
  router_: router_,
12054
12257
  content_results_rows_: content_results_rows_,
12055
12258
  content_layout_options_: content_layout_options_,
@@ -12229,6 +12432,8 @@ function $7097477c78a89208$export$a54ec244c8863715({
12229
12432
  if (!search_field) break add_input_field;
12230
12433
  setModalBodyStyle({});
12231
12434
  modalAlignmentSignalsRef_?.(alignmentSignals_);
12435
+ inputFieldRef_?.(input_element);
12436
+ $i7OB2$onCleanup(() => inputFieldRef_?.(undefined));
12232
12437
  const [pollAlignment, setPollAlignment_] = $i7OB2$createSignal(false);
12233
12438
  const align_position = $i7OB2$catchify1((0, $b6d5529b253681aa$export$b3ad617e9036868))(alignmentSignals_, search_field, (0, $b6d5529b253681aa$export$3f238c96c45e6cc6) | (0, $b6d5529b253681aa$export$7895aadd1956b1c7) | (modalVersionUsed_ === 1 ? (0, $b6d5529b253681aa$export$902f8b4a7dae5d78) : (0, $b6d5529b253681aa$export$6060bc6bee850eb6) | (0, $b6d5529b253681aa$export$5097308c5200105a)), true, pollAlignment);
12234
12439
  div_with_field_class.addEventListener("click", $i7OB2$catchify1(e => {
@@ -12530,14 +12735,16 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
12530
12735
  set_search_content_results_rows((0, $49de9d31aeea1b5e$export$70ceae36059a1036));
12531
12736
  }; // do this every time after we have submitted a new query - otherwise there might already be a saved number of rows in the state
12532
12737
  const on_submit_with_unchanged_value_ = () => this.modal_open = false;
12533
- const [get_search_field_value_, set_search_field_value_] = state_.field_value;
12534
- const configured_submit_query_ = new_query => $bfd908d13d90934c$export$e16630ecb9644a1c({
12738
+ const search_field_value_ = $a578366fad1bde47$export$d13a185c53aa5edf(state_.field_value, get_search_query_);
12739
+ const [get_search_field_value_] = search_field_value_.value_;
12740
+ const configured_submit_query_ = (new_query, before_navigate_) => $bfd908d13d90934c$export$e16630ecb9644a1c({
12535
12741
  on_submit_with_unchanged_value_: on_submit_with_unchanged_value_,
12536
- set_search_field_value_: set_search_field_value_,
12742
+ search_field_value_: search_field_value_,
12537
12743
  get_search_query_: get_search_query_,
12538
12744
  search_param_name_: search_query_url_param_name_,
12539
12745
  after_submit_: after_submit_,
12540
- get_new_query: () => new_query || $i7OB2$untrack(get_search_field_value_),
12746
+ before_navigate_: before_navigate_,
12747
+ get_new_query: () => new_query ?? $i7OB2$untrack(get_search_field_value_),
12541
12748
  url_transformer_: url_transformer,
12542
12749
  router_: this.#router
12543
12750
  });
@@ -12556,6 +12763,7 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
12556
12763
  search_query_url_param_name_: search_query_url_param_name_,
12557
12764
  reset_history_state_: reset_history_state_,
12558
12765
  state_: state_,
12766
+ search_field_value_: search_field_value_.value_,
12559
12767
  router_: this.#router,
12560
12768
  url_transformer_: url_transformer,
12561
12769
  depict_api_: depict_api_,
@@ -12579,7 +12787,8 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
12579
12787
  $i7OB2$onCleanup(() => this.modal_open = false);
12580
12788
  return searchModalComponent(...args);
12581
12789
  }, {
12582
- search_field_value_: state_.field_value,
12790
+ search_field_value_: search_field_value_.value_,
12791
+ get_search_page_input_element_: () => $806c97b931758897$export$dde08b2dca8cc1ce.get(this)?.search_page_input_element_,
12583
12792
  get_search_query_: get_search_query_,
12584
12793
  search_query_url_param_name_: search_query_url_param_name_,
12585
12794
  previous_searches_: previous_searches,
@@ -12727,6 +12936,7 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
12727
12936
  const {
12728
12937
  state_: state_
12729
12938
  } = shared_properties;
12939
+ let registered_input_element;
12730
12940
  const grid_spacing_override = $i7OB2$createMemo(() => {
12731
12941
  const {
12732
12942
  grid_spacing: grid_spacing
@@ -12755,7 +12965,7 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
12755
12965
  min_products_to_fetch_: $806c97b931758897$var$min_products_to_fetch_,
12756
12966
  local_filter_cache_: state_.local_filter_cache,
12757
12967
  content_search_enabled_: () => depict_search.enable_content_search ?? $806c97b931758897$var$content_search_default,
12758
- search_field_value_: state_.field_value,
12968
+ search_field_value_: shared_properties.search_field_value_,
12759
12969
  get_search_query_: shared_properties.get_search_query_,
12760
12970
  clear_filters_on_next_submit_: shared_properties.clear_filters_on_next_submit_,
12761
12971
  open_modal_: (...args) => depict_search.modal_open = args,
@@ -12763,6 +12973,16 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
12763
12973
  modalVersionUsed_: shared_properties.modalVersionUsed_,
12764
12974
  showSliderArrow_: () => props.showSliderArrow_,
12765
12975
  i18n_: shared_properties.i18n_,
12976
+ inputFieldRef_: input_element => {
12977
+ const shared_info_right_now = $806c97b931758897$export$dde08b2dca8cc1ce.get(depict_search);
12978
+ if (!shared_info_right_now) return;
12979
+ if (input_element === undefined && shared_info_right_now.search_page_input_element_ !== registered_input_element) return;
12980
+ registered_input_element = input_element;
12981
+ $806c97b931758897$export$dde08b2dca8cc1ce.set(depict_search, {
12982
+ ...shared_info_right_now,
12983
+ search_page_input_element_: input_element
12984
+ });
12985
+ },
12766
12986
  modalAlignmentSignalsRef_: style => {
12767
12987
  const shared_info_right_now = $806c97b931758897$export$dde08b2dca8cc1ce.get(depict_search);
12768
12988
  if (!shared_info_right_now) return;
@@ -13113,7 +13333,7 @@ function $58b3487626e85ece$export$316f6f283ae64765(props) {
13113
13333
  return shared_properties.BackIcon_;
13114
13334
  },
13115
13335
  get search_field_value_() {
13116
- return shared_properties.state_.field_value;
13336
+ return shared_properties.search_field_value_;
13117
13337
  },
13118
13338
  get submit_query_() {
13119
13339
  return shared_properties.configured_submit_query_;
@@ -13156,7 +13376,7 @@ function $58b3487626e85ece$export$316f6f283ae64765(props) {
13156
13376
  return shared_properties.BackIcon_;
13157
13377
  },
13158
13378
  get search_field_value_() {
13159
- return shared_properties.state_.field_value;
13379
+ return shared_properties.search_field_value_;
13160
13380
  },
13161
13381
  get submit_query_() {
13162
13382
  return shared_properties.configured_submit_query_;