@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.
package/latest/index.js CHANGED
@@ -7,7 +7,7 @@ import { createStore as $9HbP8$createStore, reconcile as $9HbP8$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 = $9HbP8$createSignal(false);
13
13
  $9HbP8$onCleanup($9HbP8$javascript_media_query(media_query, ({
@@ -2462,6 +2462,61 @@ function $1adfe60f3a14a1d7$export$fecbb157621501bd({
2462
2462
  return outmost_element;
2463
2463
  }
2464
2464
  $9HbP8$delegateEvents(["click"]);
2465
+
2466
+ /**
2467
+ * `HTMLElement.focus()` is a **silent no-op** on an element that is not being rendered
2468
+ * (`display: none`, `visibility: hidden`, a collapsed menu). Nothing throws, focus simply
2469
+ * stays where it was, so a caller that does not check believes it restored focus when it
2470
+ * left it on `<body>` — which puts the keyboard user back at the top of the document.
2471
+ *
2472
+ * That is reachable whenever the element which opened a modal stops being rendered while the
2473
+ * modal is open, and the common way for that to happen is the responsive-duplicate header:
2474
+ * a theme renders the same search trigger twice, once for desktop and once for mobile, and
2475
+ * hides one at the current breakpoint. Open the modal from the desktop trigger, cross the
2476
+ * breakpoint (rotate a tablet, resize a window), close the modal, and the remembered trigger
2477
+ * is still `isConnected` but no longer rendered. Verified against a live merchant storefront
2478
+ * on 4.10.19.
2479
+ *
2480
+ * So: verify that focus landed, and when it did not, look for a rendered twin of the same
2481
+ * control — the other half of the responsive pair — and use that instead.
2482
+ */ /**
2483
+ * An element can only take focus if it is actually being rendered.
2484
+ *
2485
+ * Injectable because it is the one part of this module that needs a layout engine: jsdom
2486
+ * reports no client rects for anything, so the specs pass their own predicate to exercise the
2487
+ * matching rules. The real predicate is only exercised in a browser.
2488
+ */
2489
+ const $07001c226aedc5fb$export$e0652711c614c755 = element => !!element.getClientRects().length;
2490
+ /**
2491
+ * `document.activeElement` is the outermost shadow host when focus is inside a shadow tree,
2492
+ * so ask the element's own root rather than the document — matching how the rest of
2493
+ * modal_opener treats shadow-mounted modals.
2494
+ */
2495
+ const $07001c226aedc5fb$var$has_focus = element => element.getRootNode().activeElement === element;
2496
+ /**
2497
+ * The accessible-name-ish identity we match twins on. Deliberately narrow: an explicit label
2498
+ * or the trimmed text. Two controls that share a tag and this string are the same control
2499
+ * rendered twice, which is exactly the responsive-duplicate case.
2500
+ */
2501
+ const $07001c226aedc5fb$var$identity_of = element => (element.getAttribute("aria-label") || element.getAttribute("title") || element.textContent || "").trim().replace(/\s+/g, " ");
2502
+ function $07001c226aedc5fb$export$5800d9d535a06e96(element, rendered = $07001c226aedc5fb$export$e0652711c614c755) {
2503
+ const identity = $07001c226aedc5fb$var$identity_of(element);
2504
+ if (!identity) return; // nothing to match on — an icon-only button with no label
2505
+ const twins = [...element.ownerDocument.querySelectorAll(element.localName)].filter(candidate => candidate !== element && rendered(candidate) && $07001c226aedc5fb$var$identity_of(candidate) === identity);
2506
+ return twins.length === 1 ? twins[0] : undefined;
2507
+ }
2508
+ function $07001c226aedc5fb$export$51461d633c351649(element, rendered = $07001c226aedc5fb$export$e0652711c614c755) {
2509
+ element.focus({
2510
+ preventScroll: true
2511
+ });
2512
+ if ($07001c226aedc5fb$var$has_focus(element)) return true;
2513
+ const twin = $07001c226aedc5fb$export$5800d9d535a06e96(element, rendered);
2514
+ if (!twin) return false;
2515
+ twin.focus({
2516
+ preventScroll: true
2517
+ });
2518
+ return $07001c226aedc5fb$var$has_focus(twin);
2519
+ }
2465
2520
  async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_opts, parent) {
2466
2521
  const body = parent || document.body || (await (0, $9HbP8$observer).wait_for_element("body"));
2467
2522
  let dispose_and_remove;
@@ -2491,6 +2546,7 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2491
2546
  const modal_els = $9HbP8$createRoot(dispose => {
2492
2547
  let closing_animation;
2493
2548
  let animation_started;
2549
+ let focus_target_after_close;
2494
2550
  dispose_and_remove = () => {
2495
2551
  const actually_close = () => {
2496
2552
  dispose();
@@ -2509,13 +2565,24 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2509
2565
  activeElement?.blur?.();
2510
2566
  el.remove();
2511
2567
  });
2512
- if (should_restore_focus && element_focused_before_open?.isConnected) {
2568
+ const requested_focus_target = focus_target_after_close?.();
2569
+ if (should_restore_focus && (requested_focus_target?.isConnected || element_focused_before_open?.isConnected)) {
2513
2570
  restoring_focus = true;
2514
2571
  try {
2515
2572
  // preventScroll so this can't re-introduce the safari page-jump the blur() above works around
2516
- element_focused_before_open.focus({
2517
- preventScroll: true
2518
- });
2573
+ let focused = false;
2574
+ if (requested_focus_target?.isConnected) {
2575
+ requested_focus_target.focus({
2576
+ preventScroll: true
2577
+ });
2578
+ focused = requested_focus_target.getRootNode().activeElement === requested_focus_target;
2579
+ }
2580
+ if (!focused && element_focused_before_open?.isConnected)
2581
+ // restore_focus_to rather than a bare focus(): the remembered trigger can be
2582
+ // connected but no longer rendered (a responsive-duplicate header whose other
2583
+ // half is showing now), and focus() on an unrendered element silently does
2584
+ // nothing, leaving the keyboard user at the top of the page.
2585
+ $07001c226aedc5fb$export$51461d633c351649(element_focused_before_open);
2519
2586
  } finally {
2520
2587
  // Cleared on a task instead of synchronously in case a browser delivers the focus event async
2521
2588
  setTimeout(() => restoring_focus = false, 0);
@@ -2534,7 +2601,8 @@ async function $194bd6b8e4c59830$export$79b1565500412d9b(search_modal, modal_fn_
2534
2601
  ...extra_options_for_modal,
2535
2602
  close_modal_: close_modal_,
2536
2603
  open_modal_: open_modal_,
2537
- register_closing_animation_: animation => closing_animation = animation
2604
+ register_closing_animation_: animation => closing_animation = animation,
2605
+ set_focus_target_after_close_: get_target => focus_target_after_close = get_target
2538
2606
  });
2539
2607
  });
2540
2608
  body.append(...modal_els);
@@ -9155,16 +9223,20 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
9155
9223
  * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
9156
9224
  */ /**
9157
9225
  * 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
9158
- */
9159
- #throwing_on_navigation(...args) {
9226
+ */ /**
9227
+ * 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
9228
+ */
9229
+ navigation_to_same_href_listeners_ = new Set();
9230
+ #throwing_on_navigation(options, on_throw_) {
9160
9231
  const {
9161
9232
  on_navigation_: on_navigation_
9162
9233
  } = this;
9163
9234
  if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
9164
9235
  // make sure that we don't accidentally catchify if the SDK consumer has fucked up
9165
9236
  try {
9166
- return on_navigation_(...args);
9237
+ return on_navigation_(options);
9167
9238
  } catch (e) {
9239
+ on_throw_?.();
9168
9240
  queueMicrotask(() => {
9169
9241
  throw e;
9170
9242
  });
@@ -9185,6 +9257,28 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
9185
9257
  (0, $9HbP8$instant_exec_on_suspect_history_change).add(handler);
9186
9258
  });
9187
9259
  }
9260
+ /**
9261
+ * Calls navigation_to_same_href_listeners_ if the navigation we're about to request ends on the href we're already on
9262
+ * @returns function to stop watching, call it when the navigation failed
9263
+ */
9264
+ #watch_for_navigation_to_same_href(target_url) {
9265
+ const href_before = location.href;
9266
+ const stop_watching = () => {
9267
+ (0, $9HbP8$instant_exec_on_suspect_history_change).delete(on_history_change);
9268
+ clearTimeout(timeout);
9269
+ };
9270
+ const notify_if_href_unchanged = $9HbP8$catchify1(() => {
9271
+ stop_watching();
9272
+ if (location.href !== href_before) return;
9273
+ this.navigation_to_same_href_listeners_.forEach(listener => $9HbP8$catchify1(listener)());
9274
+ });
9275
+ // 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
9276
+ const on_history_change = () => notify_if_href_unchanged();
9277
+ // 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
9278
+ const timeout = target_url.href === href_before ? setTimeout(notify_if_href_unchanged, 500) : setTimeout(stop_watching, 10000);
9279
+ (0, $9HbP8$instant_exec_on_suspect_history_change).add(on_history_change);
9280
+ return stop_watching;
9281
+ }
9188
9282
  navigate_ = {
9189
9283
  /**
9190
9284
  * Call this if you *just* want to replace the state object in history.state
@@ -9224,6 +9318,7 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
9224
9318
  }
9225
9319
  event_?.preventDefault();
9226
9320
  const promise = this.#get_navigation_happened_promise(true);
9321
+ const stop_watching_for_same_href = this.#watch_for_navigation_to_same_href(new_url_);
9227
9322
  if (force_spa_navigation_ && wants_hard_navigation) {
9228
9323
  // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
9229
9324
  const new_state = history.state;
@@ -9237,7 +9332,7 @@ class $4fd2ba03703a7d92$export$7e1297a3a19f10d8 {
9237
9332
  is_replace: is_replace_,
9238
9333
  new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.href),
9239
9334
  scroll: scroll
9240
- });
9335
+ }, stop_watching_for_same_href);
9241
9336
  await promise;
9242
9337
  })
9243
9338
  };
@@ -10706,6 +10801,7 @@ var $5285d2814d0fac0c$var$_tmpl$ = /*#__PURE__*/$9HbP8$template(`<button class=b
10706
10801
  $5285d2814d0fac0c$var$_tmpl$3 = /*#__PURE__*/$9HbP8$template(`<div class=spacer>`),
10707
10802
  $5285d2814d0fac0c$var$_tmpl$4 = /*#__PURE__*/$9HbP8$template(`<button class="submit major"type=button>`),
10708
10803
  $5285d2814d0fac0c$var$_tmpl$5 = /*#__PURE__*/$9HbP8$template(`<div><!$><!/><!$><!/><div class=field><!$><!/><input class=query tabindex=0 enterkeyhint=search><!$><!/></div><!$><!/><!$><!/>`);
10804
+ 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"]);
10709
10805
  function $5285d2814d0fac0c$export$b94867ecbd698f21({
10710
10806
  search_field_value_: [searchFieldValue, setSearchFieldValue],
10711
10807
  input_field_ref_: input_field_ref_,
@@ -10883,7 +10979,7 @@ function $5285d2814d0fac0c$export$b94867ecbd698f21({
10883
10979
  get onKeyDown() {
10884
10980
  return $9HbP8$catchify1(e => {
10885
10981
  if (disabled_) {
10886
- if (e.key !== "Tab" && e.key !== "Shift")
10982
+ if (!$5285d2814d0fac0c$var$keys_not_opening_modal.has(e.key) && !/^F\d{1,2}$/.test(e.key))
10887
10983
  // alow tab-selecting the input field and then open the modal when the user start writing but also to move past the field with tab
10888
10984
  input_element.click();
10889
10985
  } else if (e.key === "Enter") {
@@ -10963,11 +11059,17 @@ var $ffb84ffbf4014982$var$_tmpl$ = /*#__PURE__*/$9HbP8$template(`<svg xmlns=http
10963
11059
  function $ffb84ffbf4014982$export$8d8893ffd8aca39a() {
10964
11060
  return $9HbP8$getNextElement($ffb84ffbf4014982$var$_tmpl$);
10965
11061
  }
10966
- function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url_param_name_) {
11062
+ function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url_param_name_, router_) {
10967
11063
  const [exit_iterable, exitable_iterable] = $9HbP8$make_asyncIterable_exiter((0, $9HbP8$href_change_ipns));
11064
+ const {
11065
+ navigation_to_same_href_listeners_: navigation_to_same_href_listeners_
11066
+ } = router_;
10968
11067
  let set_initial_values = false;
10969
11068
  let old_pathname;
10970
11069
  let old_param_value;
11070
+ // A card linking to the page one is already on doesn't change the href, close the modal anyway so the click does something
11071
+ navigation_to_same_href_listeners_.add(close_modal);
11072
+ $9HbP8$onCleanup(() => navigation_to_same_href_listeners_.delete(close_modal));
10971
11073
  $9HbP8$onCleanup($9HbP8$catchify1(exit_iterable));
10972
11074
  $9HbP8$catchify1(async () => {
10973
11075
  for await (const href of exitable_iterable) {
@@ -10986,6 +11088,31 @@ function $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal, search_query_url
10986
11088
  }
10987
11089
  })();
10988
11090
  }
11091
+ function $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
11092
+ props_search_field_value_: props_search_field_value_,
11093
+ props_submit_query_: props_submit_query_,
11094
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
11095
+ set_focus_target_after_close_: set_focus_target_after_close_,
11096
+ get_search_page_input_element_: get_search_page_input_element_
11097
+ }) {
11098
+ const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $9HbP8$createSignal("") : props_search_field_value_;
11099
+ let submits_in_flight = 0;
11100
+ const submit_query_ = async (new_query = $9HbP8$untrack(search_field_value_[0])) => {
11101
+ submits_in_flight++;
11102
+ try {
11103
+ return await props_submit_query_(new_query, () => set_focus_target_after_close_(get_search_page_input_element_));
11104
+ } finally {
11105
+ submits_in_flight--;
11106
+ }
11107
+ };
11108
+ if (dont_sync_search_field_value_except_on_submit_) $9HbP8$createEffect($9HbP8$on(search_field_value_[0], value => submits_in_flight > 0 && props_search_field_value_[1](value), {
11109
+ defer: true
11110
+ }));
11111
+ return {
11112
+ search_field_value_: search_field_value_,
11113
+ submit_query_: submit_query_
11114
+ };
11115
+ }
10989
11116
  var $42912431795f188e$var$_tmpl$ = /*#__PURE__*/$9HbP8$template(`<div class=discover-more><button class=major type=button>`),
10990
11117
  $42912431795f188e$var$_tmpl$2 = /*#__PURE__*/$9HbP8$template(`<b>`),
10991
11118
  $42912431795f188e$var$_tmpl$3 = /*#__PURE__*/$9HbP8$template(`<div class=depict-search-modal><div class=body 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><!$><!/>`),
@@ -10999,6 +11126,8 @@ function $42912431795f188e$var$RawClassicSearchModal({
10999
11126
  search_query_url_param_name_: search_query_url_param_name_,
11000
11127
  previous_searches_: previous_searches_,
11001
11128
  close_modal_: close_modal_,
11129
+ set_focus_target_after_close_: set_focus_target_after_close_,
11130
+ get_search_page_input_element_: get_search_page_input_element_,
11002
11131
  depict_api_: depict_api_,
11003
11132
  merchant_: merchant_,
11004
11133
  market_: market_,
@@ -11023,15 +11152,16 @@ function $42912431795f188e$var$RawClassicSearchModal({
11023
11152
  // 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.
11024
11153
  // 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
11025
11154
  // Basically the UI signals that the button that opens the modal starts a new search.
11026
- const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $9HbP8$createSignal("") : props_search_field_value;
11027
- const propagate_search_field_value_back = dont_sync_search_field_value_except_on_submit_ ? () => props_search_field_value[1]($9HbP8$untrack(search_field_value_[0])) // Set actual search field value to the throwaway internal one before submitting
11028
- : undefined;
11029
- const submit_query_ = (...args) => {
11030
- // 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
11031
- // It will write the old one back and then write the new one after submit
11032
- propagate_search_field_value_back?.();
11033
- return props_submit_query(...args);
11034
- };
11155
+ const {
11156
+ search_field_value_: search_field_value_,
11157
+ submit_query_: submit_query_
11158
+ } = $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
11159
+ props_search_field_value_: props_search_field_value,
11160
+ props_submit_query_: props_submit_query,
11161
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
11162
+ set_focus_target_after_close_: set_focus_target_after_close_,
11163
+ get_search_page_input_element_: get_search_page_input_element_
11164
+ });
11035
11165
  const [input_field, set_input_field] = $9HbP8$createSignal();
11036
11166
  const [get_search_field_value_] = search_field_value_;
11037
11167
  // Search field alignment unused in ClassicSearchModal since the search field spans the whole modal
@@ -11095,7 +11225,7 @@ function $42912431795f188e$var$RawClassicSearchModal({
11095
11225
  return _el$;
11096
11226
  })();
11097
11227
  if (disable_scrolling_) $aea1edf92433e81e$export$fe334901e8bebd57();
11098
- $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_);
11228
+ $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_, router_);
11099
11229
  window.addEventListener("keydown", close_on_escape_handler);
11100
11230
  $9HbP8$onCleanup($9HbP8$catchify1(() => window.removeEventListener("keydown", close_on_escape_handler)));
11101
11231
  if (closing_animation_) register_closing_animation_(closing_animation_);
@@ -11826,6 +11956,8 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
11826
11956
  search_query_url_param_name_: search_query_url_param_name_,
11827
11957
  previous_searches_: previous_searches_,
11828
11958
  close_modal_: close_modal_,
11959
+ set_focus_target_after_close_: set_focus_target_after_close_,
11960
+ get_search_page_input_element_: get_search_page_input_element_,
11829
11961
  alignmentSignals_: alignmentSignals_,
11830
11962
  depict_api_: depict_api_,
11831
11963
  merchant_: merchant_,
@@ -11856,15 +11988,16 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
11856
11988
  // 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.
11857
11989
  // 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
11858
11990
  // Basically the UI signals that the button that opens the modal starts a new search.
11859
- const search_field_value_ = dont_sync_search_field_value_except_on_submit_ ? $9HbP8$createSignal("") : props_search_field_value;
11860
- const propagate_search_field_value_back = dont_sync_search_field_value_except_on_submit_ ? () => props_search_field_value[1]($9HbP8$untrack(search_field_value_[0])) // Set actual search field value to the throwaway internal one before submitting
11861
- : undefined;
11862
- const submit_query_ = (...args) => {
11863
- // 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
11864
- // It will write the old one back and then write the new one after submit
11865
- propagate_search_field_value_back?.();
11866
- return props_submit_query(...args);
11867
- };
11991
+ const {
11992
+ search_field_value_: search_field_value_,
11993
+ submit_query_: submit_query_
11994
+ } = $8b2ecf1919837863$export$9e9e2ae069cf2fe1({
11995
+ props_search_field_value_: props_search_field_value,
11996
+ props_submit_query_: props_submit_query,
11997
+ dont_sync_search_field_value_except_on_submit_: dont_sync_search_field_value_except_on_submit_,
11998
+ set_focus_target_after_close_: set_focus_target_after_close_,
11999
+ get_search_page_input_element_: get_search_page_input_element_
12000
+ });
11868
12001
  const [input_field, set_input_field] = $9HbP8$createSignal();
11869
12002
  const [searching_for_value_, set_searching_for_value_] = $9HbP8$createSignal();
11870
12003
  const [show_stale_content_results_, set_show_stale_content_results_] = $9HbP8$createSignal(false);
@@ -11971,7 +12104,7 @@ function $500a16dd18ee5a71$var$RawSearchModalV2({
11971
12104
  });
11972
12105
  const noResults = $9HbP8$createMemo(prev => (get_modal_search_results_()?.loading === false && !suggestions_response_.loading || !!prev) && totalNumberResults() === 0 && previous_searches_matching_query().length === 0);
11973
12106
  if (disable_scrolling_) $aea1edf92433e81e$export$fe334901e8bebd57();
11974
- $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_);
12107
+ $512b994d501f412b$export$93d9bfd0c9c1a5b8(close_modal_, search_query_url_param_name_, router_);
11975
12108
  addEventListener("keydown", close_on_escape_handler);
11976
12109
  $9HbP8$onCleanup(() => removeEventListener("keydown", close_on_escape_handler));
11977
12110
  $9HbP8$createEffect($9HbP8$on(get_search_field_value_, () => {
@@ -13995,11 +14128,12 @@ function $21f51c14cb3f586f$export$84bba84a7b837187(read_search_query) {
13995
14128
  async function $bfd908d13d90934c$export$e16630ecb9644a1c({
13996
14129
  on_submit_with_unchanged_value_: on_submit_with_unchanged_value_,
13997
14130
  search_param_name_: search_param_name_,
13998
- set_search_field_value_: set_search_field_value_,
14131
+ search_field_value_: search_field_value_,
13999
14132
  get_search_query_: get_search_query_,
14000
14133
  url_transformer_: url_transformer_,
14001
14134
  router_: router_,
14002
14135
  after_submit_: after_submit_,
14136
+ before_navigate_: before_navigate_,
14003
14137
  get_new_query: get_new_query
14004
14138
  }) {
14005
14139
  const new_search_query = get_new_query();
@@ -14007,21 +14141,89 @@ async function $bfd908d13d90934c$export$e16630ecb9644a1c({
14007
14141
  if (previous_query === new_search_query && new URLSearchParams(location.search).has(search_param_name_)) {
14008
14142
  // don't push a history entry / re-search if someone submits a search again
14009
14143
  // do close the modal though
14144
+ search_field_value_.settle_(new_search_query);
14010
14145
  on_submit_with_unchanged_value_?.();
14011
- return;
14146
+ return false;
14012
14147
  }
14013
- set_search_field_value_(previous_query); // restore the value to the previous query since this one goes to the new history entry
14014
14148
  const target_url = new URL(location.href);
14015
14149
  url_transformer_?.(target_url);
14016
14150
  target_url.searchParams.set(search_param_name_, new_search_query);
14017
- await router_.navigate_.go_to_({
14018
- new_url_: target_url,
14019
- is_replace_: false,
14020
- force_spa_navigation_: true
14021
- });
14022
- set_search_field_value_(new_search_query);
14151
+ const end_submit = search_field_value_.begin_submit_(new_search_query, previous_query);
14152
+ before_navigate_?.();
14153
+ let landed;
14154
+ try {
14155
+ await router_.navigate_.go_to_({
14156
+ new_url_: target_url,
14157
+ is_replace_: false,
14158
+ force_spa_navigation_: true
14159
+ });
14160
+ } finally {
14161
+ landed = end_submit();
14162
+ }
14163
+ if (!landed) return false;
14023
14164
  scrollTo(0, 0);
14024
14165
  after_submit_?.();
14166
+ return true;
14167
+ }
14168
+ function $a578366fad1bde47$export$d13a185c53aa5edf(persisted_, get_search_query_) {
14169
+ const [get_persisted, set_persisted] = persisted_;
14170
+ const [get_submitting, set_submitting] = $9HbP8$createSignal();
14171
+ const get_value = $9HbP8$createMemo(() => get_submitting() ?? get_persisted());
14172
+ const set_value = value => {
14173
+ const new_value = typeof value === "function" ? value($9HbP8$untrack(get_value)) : value;
14174
+ if ($9HbP8$untrack(get_submitting) === undefined) set_persisted(new_value);else set_submitting(new_value);
14175
+ return new_value;
14176
+ };
14177
+ let current_submit;
14178
+ const end_submit = landed => {
14179
+ current_submit.landed_ = landed;
14180
+ current_submit = undefined;
14181
+ $9HbP8$batch(() => {
14182
+ const submitting = $9HbP8$untrack(get_submitting);
14183
+ set_submitting(undefined);
14184
+ if (landed && submitting !== undefined) set_persisted(submitting);
14185
+ });
14186
+ };
14187
+ const abort_on_popstate = what_happened => {
14188
+ if (what_happened === "popstate" && current_submit) end_submit(false);
14189
+ };
14190
+ (0, $9HbP8$instant_exec_on_suspect_history_change).add(abort_on_popstate);
14191
+ $9HbP8$onCleanup(() => (0, $9HbP8$instant_exec_on_suspect_history_change).delete(abort_on_popstate));
14192
+ $9HbP8$createEffect($9HbP8$on(get_search_query_, query => {
14193
+ const token = current_submit;
14194
+ if (!token || query !== token.query_) return;
14195
+ queueMicrotask(() => {
14196
+ if (current_submit === token) end_submit(true);
14197
+ });
14198
+ }, {
14199
+ defer: true
14200
+ }));
14201
+ const begin_submit_ = (submitted_query, query_of_current_history_entry) => {
14202
+ const token = current_submit = {
14203
+ query_: submitted_query,
14204
+ landed_: false
14205
+ };
14206
+ $9HbP8$batch(() => {
14207
+ set_submitting(submitted_query);
14208
+ set_persisted(query_of_current_history_entry);
14209
+ });
14210
+ return () => {
14211
+ if (current_submit === token) end_submit(true);
14212
+ return token.landed_;
14213
+ };
14214
+ };
14215
+ const settle_ = query => {
14216
+ if (current_submit) return;
14217
+ $9HbP8$batch(() => {
14218
+ set_submitting(undefined);
14219
+ set_persisted(query);
14220
+ });
14221
+ };
14222
+ return {
14223
+ value_: [get_value, set_value],
14224
+ begin_submit_: begin_submit_,
14225
+ settle_: settle_
14226
+ };
14025
14227
  }
14026
14228
  function $d68658730065de95$export$181cceed5c91919e(callback, alsoRaF, passiveListener) {
14027
14229
  let aligned_this_microtask = false;
@@ -14725,6 +14927,7 @@ function $7097477c78a89208$export$a54ec244c8863715({
14725
14927
  scroll_restoration_data_: scroll_restoration_data_,
14726
14928
  product_card_template_: product_card_template_,
14727
14929
  modalAlignmentSignalsRef_: modalAlignmentSignalsRef_,
14930
+ inputFieldRef_: inputFieldRef_,
14728
14931
  router_: router_,
14729
14932
  content_results_rows_: content_results_rows_,
14730
14933
  content_layout_options_: content_layout_options_,
@@ -14913,6 +15116,8 @@ function $7097477c78a89208$export$a54ec244c8863715({
14913
15116
  if (!search_field) break add_input_field;
14914
15117
  setModalBodyStyle({});
14915
15118
  modalAlignmentSignalsRef_?.(alignmentSignals_);
15119
+ inputFieldRef_?.(input_element);
15120
+ $9HbP8$onCleanup(() => inputFieldRef_?.(undefined));
14916
15121
  const [pollAlignment, setPollAlignment_] = $9HbP8$createSignal(false);
14917
15122
  const align_position = $9HbP8$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);
14918
15123
  div_with_field_class.addEventListener("click", $9HbP8$catchify1(e => {
@@ -15255,14 +15460,16 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
15255
15460
  set_search_content_results_rows((0, $49de9d31aeea1b5e$export$70ceae36059a1036));
15256
15461
  }; // do this every time after we have submitted a new query - otherwise there might already be a saved number of rows in the state
15257
15462
  const on_submit_with_unchanged_value_ = () => this.modal_open = false;
15258
- const [get_search_field_value_, set_search_field_value_] = state_.field_value;
15259
- const configured_submit_query_ = new_query => $bfd908d13d90934c$export$e16630ecb9644a1c({
15463
+ const search_field_value_ = $a578366fad1bde47$export$d13a185c53aa5edf(state_.field_value, get_search_query_);
15464
+ const [get_search_field_value_] = search_field_value_.value_;
15465
+ const configured_submit_query_ = (new_query, before_navigate_) => $bfd908d13d90934c$export$e16630ecb9644a1c({
15260
15466
  on_submit_with_unchanged_value_: on_submit_with_unchanged_value_,
15261
- set_search_field_value_: set_search_field_value_,
15467
+ search_field_value_: search_field_value_,
15262
15468
  get_search_query_: get_search_query_,
15263
15469
  search_param_name_: search_query_url_param_name_,
15264
15470
  after_submit_: after_submit_,
15265
- get_new_query: () => new_query || $9HbP8$untrack(get_search_field_value_),
15471
+ before_navigate_: before_navigate_,
15472
+ get_new_query: () => new_query ?? $9HbP8$untrack(get_search_field_value_),
15266
15473
  url_transformer_: url_transformer,
15267
15474
  router_: this.#router
15268
15475
  });
@@ -15281,6 +15488,7 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
15281
15488
  search_query_url_param_name_: search_query_url_param_name_,
15282
15489
  reset_history_state_: reset_history_state_,
15283
15490
  state_: state_,
15491
+ search_field_value_: search_field_value_.value_,
15284
15492
  router_: this.#router,
15285
15493
  url_transformer_: url_transformer,
15286
15494
  depict_api_: depict_api_,
@@ -15304,7 +15512,8 @@ class $806c97b931758897$export$ac6237957a15b3f0 {
15304
15512
  $9HbP8$onCleanup(() => this.modal_open = false);
15305
15513
  return searchModalComponent(...args);
15306
15514
  }, {
15307
- search_field_value_: state_.field_value,
15515
+ search_field_value_: search_field_value_.value_,
15516
+ get_search_page_input_element_: () => $806c97b931758897$export$dde08b2dca8cc1ce.get(this)?.search_page_input_element_,
15308
15517
  get_search_query_: get_search_query_,
15309
15518
  search_query_url_param_name_: search_query_url_param_name_,
15310
15519
  previous_searches_: previous_searches,
@@ -15452,6 +15661,7 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
15452
15661
  const {
15453
15662
  state_: state_
15454
15663
  } = shared_properties;
15664
+ let registered_input_element;
15455
15665
  const grid_spacing_override = $9HbP8$createMemo(() => {
15456
15666
  const {
15457
15667
  grid_spacing: grid_spacing
@@ -15480,7 +15690,7 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
15480
15690
  min_products_to_fetch_: $806c97b931758897$var$min_products_to_fetch_,
15481
15691
  local_filter_cache_: state_.local_filter_cache,
15482
15692
  content_search_enabled_: () => depict_search.enable_content_search ?? $806c97b931758897$var$content_search_default,
15483
- search_field_value_: state_.field_value,
15693
+ search_field_value_: shared_properties.search_field_value_,
15484
15694
  get_search_query_: shared_properties.get_search_query_,
15485
15695
  clear_filters_on_next_submit_: shared_properties.clear_filters_on_next_submit_,
15486
15696
  open_modal_: (...args) => depict_search.modal_open = args,
@@ -15488,6 +15698,16 @@ function $806c97b931758897$export$f2dc7e4e4aa11abb(props) {
15488
15698
  modalVersionUsed_: shared_properties.modalVersionUsed_,
15489
15699
  showSliderArrow_: () => props.showSliderArrow_,
15490
15700
  i18n_: shared_properties.i18n_,
15701
+ inputFieldRef_: input_element => {
15702
+ const shared_info_right_now = $806c97b931758897$export$dde08b2dca8cc1ce.get(depict_search);
15703
+ if (!shared_info_right_now) return;
15704
+ if (input_element === undefined && shared_info_right_now.search_page_input_element_ !== registered_input_element) return;
15705
+ registered_input_element = input_element;
15706
+ $806c97b931758897$export$dde08b2dca8cc1ce.set(depict_search, {
15707
+ ...shared_info_right_now,
15708
+ search_page_input_element_: input_element
15709
+ });
15710
+ },
15491
15711
  modalAlignmentSignalsRef_: style => {
15492
15712
  const shared_info_right_now = $806c97b931758897$export$dde08b2dca8cc1ce.get(depict_search);
15493
15713
  if (!shared_info_right_now) return;
@@ -15838,7 +16058,7 @@ function $58b3487626e85ece$export$316f6f283ae64765(props) {
15838
16058
  return shared_properties.BackIcon_;
15839
16059
  },
15840
16060
  get search_field_value_() {
15841
- return shared_properties.state_.field_value;
16061
+ return shared_properties.search_field_value_;
15842
16062
  },
15843
16063
  get submit_query_() {
15844
16064
  return shared_properties.configured_submit_query_;
@@ -15881,7 +16101,7 @@ function $58b3487626e85ece$export$316f6f283ae64765(props) {
15881
16101
  return shared_properties.BackIcon_;
15882
16102
  },
15883
16103
  get search_field_value_() {
15884
- return shared_properties.state_.field_value;
16104
+ return shared_properties.search_field_value_;
15885
16105
  },
15886
16106
  get submit_query_() {
15887
16107
  return shared_properties.configured_submit_query_;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depict-ai/ui",
3
- "version": "4.10.19",
3
+ "version": "4.10.21",
4
4
  "description": "Base package containing the actual UI of Depict UI along with translations, with a not-simplified API. We recommend using @depict-ai/js-ui or @depict-ai/react-ui instead.",
5
5
  "packageManager": "yarn@3.2.2",
6
6
  "sass": "styles.scss",
@@ -236,9 +236,9 @@
236
236
  "@babel/plugin-transform-typescript": "^7.22.9",
237
237
  "@babel/runtime": "^7.22.6",
238
238
  "@babel/runtime-corejs3": "^7.22.6",
239
- "@depict-ai/plp-styling": "^4.6.11",
240
- "@depict-ai/types": "^5.6.9",
241
- "@depict-ai/utilishared": "^2.6.9",
239
+ "@depict-ai/plp-styling": "^4.6.13",
240
+ "@depict-ai/types": "^5.6.11",
241
+ "@depict-ai/utilishared": "^2.6.11",
242
242
  "solid-js": "^1.9.10"
243
243
  },
244
244
  "type": "module",