@depict-ai/ui 4.10.14 → 4.10.16

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
@@ -115,7 +115,7 @@ $parcel$export(module.exports, "BreadCrumbs", () => $335c02c1241a9ca8$export$5b7
115
115
  $parcel$export(module.exports, "QuickLinks", () => $335c02c1241a9ca8$export$de035477d6fef996);
116
116
  $parcel$export(module.exports, "CategoryPage", () => $c10e33c4681f8c9b$export$e2bf8ce7779e827e);
117
117
  /*! Depict.ai search and product listing SDK */
118
- const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.10.14";
118
+ const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.10.16";
119
119
  function $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query) {
120
120
  const signal = $52FdA$solidjs.createSignal(false);
121
121
  $52FdA$solidjs.onCleanup($52FdA$depictaiutilishared.javascript_media_query(media_query, _ref => {
@@ -2821,6 +2821,14 @@ function $a904ccf883f60231$export$f21ab0717a89c77f(props) {
2821
2821
  return _el$;
2822
2822
  })();
2823
2823
  }
2824
+
2825
+ /**
2826
+ * Whether a click came from the keyboard (Enter/Space) rather than a pointer. Browsers report `detail === 0` for
2827
+ * keyboard-activated clicks and `>= 1` for real pointer clicks, so we use it to only move focus on keyboard opens.
2828
+ */
2829
+ function $5f28fa844ecd384c$export$c5c485c196a19ec1(event) {
2830
+ return event.detail === 0;
2831
+ }
2824
2832
  var $b0477e4d832f090e$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<button type=button class=expand-filter><!$><!/><span>`);
2825
2833
  function $b0477e4d832f090e$export$ca21a16d65b3dd8(_ref) {
2826
2834
  let {
@@ -2837,17 +2845,14 @@ function $b0477e4d832f090e$export$ca21a16d65b3dd8(_ref) {
2837
2845
  $52FdA$solidjsweb.addEventListener(_el$, "click", $52FdA$depictaiutilishared.catchify(event => {
2838
2846
  const container = expanding_container_element_;
2839
2847
  const will_expand = !get_show_extras();
2840
- // A click from Enter/Space on the button reports `detail === 0`; a real pointer click reports >= 1.
2841
- // Only hijack focus for keyboard activation - mouse users can see the revealed options and don't need it
2842
- // (and would otherwise get the viewport scrolled and an unexpected focus ring).
2843
- const keyboard_activated = event.detail === 0;
2848
+ // Only move focus for keyboard activation; mouse users see the revealed options and don't need a focus jump.
2849
+ const keyboard_activated = $5f28fa844ecd384c$export$c5c485c196a19ec1(event);
2844
2850
  const had_focus_inside = !!container && container.contains(document.activeElement);
2845
2851
  set_show_extras(will_expand);
2846
2852
  if (will_expand) {
2847
2853
  if (!keyboard_activated) return;
2848
- // The container's `expand()` (run from the consumer's effect after this handler) clears `inert`/`visibility`;
2849
- // focus the first revealed option on the next frame so Tab continues through the newly shown options.
2850
- // `preventScroll` so moving focus never yanks the viewport down to the first checkbox.
2854
+ // `expand()` (consumer's effect, runs after this) clears `inert`/`visibility`; focus the first revealed
2855
+ // option next frame so Tab continues through them. `preventScroll` so it doesn't yank the viewport down.
2851
2856
  requestAnimationFrame($52FdA$depictaiutilishared.catchify(() => {
2852
2857
  var _container$querySelec;
2853
2858
  return container === null || container === void 0 ? void 0 : (_container$querySelec = container.querySelector("input:not(:disabled)")) === null || _container$querySelec === void 0 ? void 0 : _container$querySelec.focus({
@@ -2857,7 +2862,9 @@ function $b0477e4d832f090e$export$ca21a16d65b3dd8(_ref) {
2857
2862
  } else if (had_focus_inside)
2858
2863
  // Keep focus on the toggle when collapsing, otherwise making the container `inert` dumps focus to <body>
2859
2864
  // (Safari doesn't focus buttons on mouse click, so focus can still be inside the container here).
2860
- button.focus();
2865
+ button.focus({
2866
+ preventScroll: true
2867
+ });
2861
2868
  }), true);
2862
2869
  var _ref$ = button;
2863
2870
  typeof _ref$ === "function" ? $52FdA$solidjsweb.use(_ref$, _el$) : button = _el$;
@@ -6415,10 +6422,10 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
6415
6422
  available_sortings_: available_sortings_,
6416
6423
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
6417
6424
  };
6418
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
6419
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
6420
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
6421
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
6425
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
6426
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
6427
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
6428
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
6422
6429
  let user_opened_panel = false;
6423
6430
  let filter_toggle_button;
6424
6431
  let sort_toggle_button;
@@ -6429,7 +6436,20 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
6429
6436
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
6430
6437
  // listener it registers - referenced forever.
6431
6438
  await (0, $52FdA$depictaiutilishared.observer).wait_for_element(panel, 4000);
6432
- if (panel.isConnected) panel.focus();
6439
+ if (panel.isConnected) {
6440
+ var _panel$querySelector;
6441
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
6442
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
6443
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
6444
+ // by the input/button/etc. selectors, so it must be listed explicitly.
6445
+ const focus_target = (_panel$querySelector = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])")) !== null && _panel$querySelector !== void 0 ? _panel$querySelector : panel;
6446
+ focus_target.focus({
6447
+ preventScroll: true
6448
+ });
6449
+ focus_target.scrollIntoView({
6450
+ block: "nearest"
6451
+ });
6452
+ }
6433
6453
  })();
6434
6454
  const register_desktop_panel = (el, toggle_button, should_focus) => {
6435
6455
  current_panel = el;
@@ -6447,7 +6467,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
6447
6467
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
6448
6468
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
6449
6469
  hide_button_: hide_filters,
6450
- on_user_open_: () => user_opened_panel = true,
6470
+ on_user_open_: keyboard_activated => {
6471
+ if (keyboard_activated) user_opened_panel = true;
6472
+ },
6451
6473
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
6452
6474
  });
6453
6475
  };
@@ -6463,7 +6485,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
6463
6485
  available_sortings_: available_sortings_,
6464
6486
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
6465
6487
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
6466
- on_user_open_: () => user_opened_panel = true,
6488
+ on_user_open_: keyboard_activated => {
6489
+ if (keyboard_activated) user_opened_panel = true;
6490
+ },
6467
6491
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
6468
6492
  });
6469
6493
  };
@@ -6490,7 +6514,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
6490
6514
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
6491
6515
  current_panel = undefined;
6492
6516
  current_panel_toggle_button = undefined;
6493
- if (focus_was_in_panel) button_to_restore === null || button_to_restore === void 0 || button_to_restore.focus();
6517
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
6518
+ preventScroll: true
6519
+ });
6494
6520
  };
6495
6521
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
6496
6522
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -6632,12 +6658,13 @@ function $f70cc6dfcadf0fd5$var$OpenFiltersButton(_ref3) {
6632
6658
  return _el$15;
6633
6659
  }
6634
6660
  }), _el$21, _co$5);
6635
- $52FdA$solidjsweb.addEventListener(_el$16, "click", $52FdA$depictaiutilishared.catchify(() => $52FdA$solidjs.batch(() => {
6661
+ $52FdA$solidjsweb.addEventListener(_el$16, "click", $52FdA$depictaiutilishared.catchify(event => $52FdA$solidjs.batch(() => {
6636
6662
  if (search_filters_open_[0]()) {
6637
6663
  search_filters_open_[1](false);
6638
6664
  return;
6639
6665
  }
6640
- on_user_open_ === null || on_user_open_ === void 0 || on_user_open_();
6666
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6667
+ on_user_open_ === null || on_user_open_ === void 0 || on_user_open_($5f28fa844ecd384c$export$c5c485c196a19ec1(event));
6641
6668
  search_filters_open_[1](true);
6642
6669
  search_sorting_open_[1](false);
6643
6670
  })), true);
@@ -6707,12 +6734,13 @@ function $f70cc6dfcadf0fd5$var$OpenSortingButton(_ref4) {
6707
6734
  _el$23 = _el$22.firstChild,
6708
6735
  _el$24 = _el$23.nextSibling,
6709
6736
  [_el$25, _co$6] = $52FdA$solidjsweb.getNextMarker(_el$24.nextSibling);
6710
- $52FdA$solidjsweb.addEventListener(_el$22, "click", $52FdA$depictaiutilishared.catchify(() => $52FdA$solidjs.batch(() => {
6737
+ $52FdA$solidjsweb.addEventListener(_el$22, "click", $52FdA$depictaiutilishared.catchify(event => $52FdA$solidjs.batch(() => {
6711
6738
  if (search_sorting_open_[0]()) {
6712
6739
  search_sorting_open_[1](false);
6713
6740
  return;
6714
6741
  }
6715
- on_user_open_ === null || on_user_open_ === void 0 || on_user_open_();
6742
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6743
+ on_user_open_ === null || on_user_open_ === void 0 || on_user_open_($5f28fa844ecd384c$export$c5c485c196a19ec1(event));
6716
6744
  search_filters_open_[1](false);
6717
6745
  search_sorting_open_[1](true);
6718
6746
  })), true);
package/ES10/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import { GetListingRequest } from "@depict-ai/types/api/GetListingRequest";
11
11
  import { BaseSearchRequestV3 } from "@depict-ai/types/api/BaseSearchRequestV3";
12
12
  import { FeaturedInDisplay } from "@depict-ai/types/api/FeaturedInResponseV3";
13
13
  import { SearchFilter as _SearchFilter3 } from "@depict-ai/types/api/SearchRequestV2";
14
- export const version = "4.10.14";
14
+ export const version = "4.10.16";
15
15
  /**
16
16
  * Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
17
17
  */
package/ES10/index.js CHANGED
@@ -10,7 +10,7 @@ import $8tj43$babelruntimehelpersclassPrivateFieldGet from "@babel/runtime/helpe
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.10.14";
13
+ const $8db9a15135765c11$export$83d89fbfd8236492 = "4.10.16";
14
14
  function $00a5b94f0c11efbb$export$d9f36cf74e24d595(media_query) {
15
15
  const signal = $8tj43$createSignal(false);
16
16
  $8tj43$onCleanup($8tj43$javascript_media_query(media_query, _ref => {
@@ -2716,6 +2716,14 @@ function $ff3225aef892a467$export$f21ab0717a89c77f(props) {
2716
2716
  return _el$;
2717
2717
  })();
2718
2718
  }
2719
+
2720
+ /**
2721
+ * Whether a click came from the keyboard (Enter/Space) rather than a pointer. Browsers report `detail === 0` for
2722
+ * keyboard-activated clicks and `>= 1` for real pointer clicks, so we use it to only move focus on keyboard opens.
2723
+ */
2724
+ function $5cfec0b5cd753ec8$export$c5c485c196a19ec1(event) {
2725
+ return event.detail === 0;
2726
+ }
2719
2727
  var $3e850b2f2cca761f$var$_tmpl$ = /*#__PURE__*/$8tj43$template(`<button type=button class=expand-filter><!$><!/><span>`);
2720
2728
  function $3e850b2f2cca761f$export$ca21a16d65b3dd8(_ref) {
2721
2729
  let {
@@ -2732,17 +2740,14 @@ function $3e850b2f2cca761f$export$ca21a16d65b3dd8(_ref) {
2732
2740
  $8tj43$addEventListener(_el$, "click", $8tj43$catchify1(event => {
2733
2741
  const container = expanding_container_element_;
2734
2742
  const will_expand = !get_show_extras();
2735
- // A click from Enter/Space on the button reports `detail === 0`; a real pointer click reports >= 1.
2736
- // Only hijack focus for keyboard activation - mouse users can see the revealed options and don't need it
2737
- // (and would otherwise get the viewport scrolled and an unexpected focus ring).
2738
- const keyboard_activated = event.detail === 0;
2743
+ // Only move focus for keyboard activation; mouse users see the revealed options and don't need a focus jump.
2744
+ const keyboard_activated = $5cfec0b5cd753ec8$export$c5c485c196a19ec1(event);
2739
2745
  const had_focus_inside = !!container && container.contains(document.activeElement);
2740
2746
  set_show_extras(will_expand);
2741
2747
  if (will_expand) {
2742
2748
  if (!keyboard_activated) return;
2743
- // The container's `expand()` (run from the consumer's effect after this handler) clears `inert`/`visibility`;
2744
- // focus the first revealed option on the next frame so Tab continues through the newly shown options.
2745
- // `preventScroll` so moving focus never yanks the viewport down to the first checkbox.
2749
+ // `expand()` (consumer's effect, runs after this) clears `inert`/`visibility`; focus the first revealed
2750
+ // option next frame so Tab continues through them. `preventScroll` so it doesn't yank the viewport down.
2746
2751
  requestAnimationFrame($8tj43$catchify1(() => {
2747
2752
  var _container$querySelec;
2748
2753
  return container === null || container === void 0 ? void 0 : (_container$querySelec = container.querySelector("input:not(:disabled)")) === null || _container$querySelec === void 0 ? void 0 : _container$querySelec.focus({
@@ -2752,7 +2757,9 @@ function $3e850b2f2cca761f$export$ca21a16d65b3dd8(_ref) {
2752
2757
  } else if (had_focus_inside)
2753
2758
  // Keep focus on the toggle when collapsing, otherwise making the container `inert` dumps focus to <body>
2754
2759
  // (Safari doesn't focus buttons on mouse click, so focus can still be inside the container here).
2755
- button.focus();
2760
+ button.focus({
2761
+ preventScroll: true
2762
+ });
2756
2763
  }), true);
2757
2764
  var _ref$ = button;
2758
2765
  typeof _ref$ === "function" ? $8tj43$use(_ref$, _el$) : button = _el$;
@@ -6310,10 +6317,10 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
6310
6317
  available_sortings_: available_sortings_,
6311
6318
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
6312
6319
  };
6313
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
6314
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
6315
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
6316
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
6320
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
6321
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
6322
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
6323
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
6317
6324
  let user_opened_panel = false;
6318
6325
  let filter_toggle_button;
6319
6326
  let sort_toggle_button;
@@ -6324,7 +6331,20 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
6324
6331
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
6325
6332
  // listener it registers - referenced forever.
6326
6333
  await (0, $8tj43$observer).wait_for_element(panel, 4000);
6327
- if (panel.isConnected) panel.focus();
6334
+ if (panel.isConnected) {
6335
+ var _panel$querySelector;
6336
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
6337
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
6338
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
6339
+ // by the input/button/etc. selectors, so it must be listed explicitly.
6340
+ const focus_target = (_panel$querySelector = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])")) !== null && _panel$querySelector !== void 0 ? _panel$querySelector : panel;
6341
+ focus_target.focus({
6342
+ preventScroll: true
6343
+ });
6344
+ focus_target.scrollIntoView({
6345
+ block: "nearest"
6346
+ });
6347
+ }
6328
6348
  })();
6329
6349
  const register_desktop_panel = (el, toggle_button, should_focus) => {
6330
6350
  current_panel = el;
@@ -6342,7 +6362,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
6342
6362
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
6343
6363
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
6344
6364
  hide_button_: hide_filters,
6345
- on_user_open_: () => user_opened_panel = true,
6365
+ on_user_open_: keyboard_activated => {
6366
+ if (keyboard_activated) user_opened_panel = true;
6367
+ },
6346
6368
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
6347
6369
  });
6348
6370
  };
@@ -6358,7 +6380,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
6358
6380
  available_sortings_: available_sortings_,
6359
6381
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
6360
6382
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
6361
- on_user_open_: () => user_opened_panel = true,
6383
+ on_user_open_: keyboard_activated => {
6384
+ if (keyboard_activated) user_opened_panel = true;
6385
+ },
6362
6386
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
6363
6387
  });
6364
6388
  };
@@ -6385,7 +6409,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
6385
6409
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
6386
6410
  current_panel = undefined;
6387
6411
  current_panel_toggle_button = undefined;
6388
- if (focus_was_in_panel) button_to_restore === null || button_to_restore === void 0 || button_to_restore.focus();
6412
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
6413
+ preventScroll: true
6414
+ });
6389
6415
  };
6390
6416
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
6391
6417
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -6527,12 +6553,13 @@ function $7396052a1484264f$var$OpenFiltersButton(_ref3) {
6527
6553
  return _el$15;
6528
6554
  }
6529
6555
  }), _el$21, _co$5);
6530
- $8tj43$addEventListener(_el$16, "click", $8tj43$catchify1(() => $8tj43$batch(() => {
6556
+ $8tj43$addEventListener(_el$16, "click", $8tj43$catchify1(event => $8tj43$batch(() => {
6531
6557
  if (search_filters_open_[0]()) {
6532
6558
  search_filters_open_[1](false);
6533
6559
  return;
6534
6560
  }
6535
- on_user_open_ === null || on_user_open_ === void 0 || on_user_open_();
6561
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6562
+ on_user_open_ === null || on_user_open_ === void 0 || on_user_open_($5cfec0b5cd753ec8$export$c5c485c196a19ec1(event));
6536
6563
  search_filters_open_[1](true);
6537
6564
  search_sorting_open_[1](false);
6538
6565
  })), true);
@@ -6602,12 +6629,13 @@ function $7396052a1484264f$var$OpenSortingButton(_ref4) {
6602
6629
  _el$23 = _el$22.firstChild,
6603
6630
  _el$24 = _el$23.nextSibling,
6604
6631
  [_el$25, _co$6] = $8tj43$getNextMarker(_el$24.nextSibling);
6605
- $8tj43$addEventListener(_el$22, "click", $8tj43$catchify1(() => $8tj43$batch(() => {
6632
+ $8tj43$addEventListener(_el$22, "click", $8tj43$catchify1(event => $8tj43$batch(() => {
6606
6633
  if (search_sorting_open_[0]()) {
6607
6634
  search_sorting_open_[1](false);
6608
6635
  return;
6609
6636
  }
6610
- on_user_open_ === null || on_user_open_ === void 0 || on_user_open_();
6637
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6638
+ on_user_open_ === null || on_user_open_ === void 0 || on_user_open_($5cfec0b5cd753ec8$export$c5c485c196a19ec1(event));
6611
6639
  search_filters_open_[1](false);
6612
6640
  search_sorting_open_[1](true);
6613
6641
  })), true);
package/latest/index.cjs CHANGED
@@ -109,7 +109,7 @@ $parcel$export(module.exports, "BreadCrumbs", () => $1f4925833f07df29$export$5b7
109
109
  $parcel$export(module.exports, "QuickLinks", () => $1f4925833f07df29$export$de035477d6fef996);
110
110
  $parcel$export(module.exports, "CategoryPage", () => $14f289047713d67a$export$e2bf8ce7779e827e);
111
111
  /*! Depict.ai search and product listing SDK */
112
- const $b757f75811f3261f$export$83d89fbfd8236492 = "4.10.14";
112
+ const $b757f75811f3261f$export$83d89fbfd8236492 = "4.10.16";
113
113
  function $b54e6192d0caa293$export$d9f36cf74e24d595(media_query) {
114
114
  const signal = $gVhhF$solidjs.createSignal(false);
115
115
  $gVhhF$solidjs.onCleanup($gVhhF$depictaiutilishared.javascript_media_query(media_query, ({
@@ -2698,6 +2698,14 @@ function $cc43b6428000c4bf$export$f21ab0717a89c77f(props) {
2698
2698
  return _el$;
2699
2699
  })();
2700
2700
  }
2701
+
2702
+ /**
2703
+ * Whether a click came from the keyboard (Enter/Space) rather than a pointer. Browsers report `detail === 0` for
2704
+ * keyboard-activated clicks and `>= 1` for real pointer clicks, so we use it to only move focus on keyboard opens.
2705
+ */
2706
+ function $fb96fea58c4a45dd$export$c5c485c196a19ec1(event) {
2707
+ return event.detail === 0;
2708
+ }
2701
2709
  var $0fe1e7efdf4200d6$var$_tmpl$ = /*#__PURE__*/$gVhhF$solidjsweb.template(`<button type=button class=expand-filter><!$><!/><span>`);
2702
2710
  function $0fe1e7efdf4200d6$export$ca21a16d65b3dd8({
2703
2711
  show_extras_: [get_show_extras, set_show_extras],
@@ -2713,24 +2721,23 @@ function $0fe1e7efdf4200d6$export$ca21a16d65b3dd8({
2713
2721
  $gVhhF$solidjsweb.addEventListener(_el$, "click", $gVhhF$depictaiutilishared.catchify(event => {
2714
2722
  const container = expanding_container_element_;
2715
2723
  const will_expand = !get_show_extras();
2716
- // A click from Enter/Space on the button reports `detail === 0`; a real pointer click reports >= 1.
2717
- // Only hijack focus for keyboard activation - mouse users can see the revealed options and don't need it
2718
- // (and would otherwise get the viewport scrolled and an unexpected focus ring).
2719
- const keyboard_activated = event.detail === 0;
2724
+ // Only move focus for keyboard activation; mouse users see the revealed options and don't need a focus jump.
2725
+ const keyboard_activated = $fb96fea58c4a45dd$export$c5c485c196a19ec1(event);
2720
2726
  const had_focus_inside = !!container && container.contains(document.activeElement);
2721
2727
  set_show_extras(will_expand);
2722
2728
  if (will_expand) {
2723
2729
  if (!keyboard_activated) return;
2724
- // The container's `expand()` (run from the consumer's effect after this handler) clears `inert`/`visibility`;
2725
- // focus the first revealed option on the next frame so Tab continues through the newly shown options.
2726
- // `preventScroll` so moving focus never yanks the viewport down to the first checkbox.
2730
+ // `expand()` (consumer's effect, runs after this) clears `inert`/`visibility`; focus the first revealed
2731
+ // option next frame so Tab continues through them. `preventScroll` so it doesn't yank the viewport down.
2727
2732
  requestAnimationFrame($gVhhF$depictaiutilishared.catchify(() => container?.querySelector("input:not(:disabled)")?.focus({
2728
2733
  preventScroll: true
2729
2734
  })));
2730
2735
  } else if (had_focus_inside)
2731
2736
  // Keep focus on the toggle when collapsing, otherwise making the container `inert` dumps focus to <body>
2732
2737
  // (Safari doesn't focus buttons on mouse click, so focus can still be inside the container here).
2733
- button.focus();
2738
+ button.focus({
2739
+ preventScroll: true
2740
+ });
2734
2741
  }), true);
2735
2742
  var _ref$ = button;
2736
2743
  typeof _ref$ === "function" ? $gVhhF$solidjsweb.use(_ref$, _el$) : button = _el$;
@@ -6059,10 +6066,10 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
6059
6066
  available_sortings_: available_sortings_,
6060
6067
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
6061
6068
  };
6062
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
6063
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
6064
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
6065
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
6069
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
6070
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
6071
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
6072
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
6066
6073
  let user_opened_panel = false;
6067
6074
  let filter_toggle_button;
6068
6075
  let sort_toggle_button;
@@ -6073,7 +6080,19 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
6073
6080
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
6074
6081
  // listener it registers - referenced forever.
6075
6082
  await (0, $gVhhF$depictaiutilishared.observer).wait_for_element(panel, 4000);
6076
- if (panel.isConnected) panel.focus();
6083
+ if (panel.isConnected) {
6084
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
6085
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
6086
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
6087
+ // by the input/button/etc. selectors, so it must be listed explicitly.
6088
+ const focus_target = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])") ?? panel;
6089
+ focus_target.focus({
6090
+ preventScroll: true
6091
+ });
6092
+ focus_target.scrollIntoView({
6093
+ block: "nearest"
6094
+ });
6095
+ }
6077
6096
  })();
6078
6097
  const register_desktop_panel = (el, toggle_button, should_focus) => {
6079
6098
  current_panel = el;
@@ -6088,7 +6107,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
6088
6107
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
6089
6108
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
6090
6109
  hide_button_: hide_filters,
6091
- on_user_open_: () => user_opened_panel = true,
6110
+ on_user_open_: keyboard_activated => {
6111
+ if (keyboard_activated) user_opened_panel = true;
6112
+ },
6092
6113
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
6093
6114
  });
6094
6115
  const make_open_sorting_button = (adhere_to_width = false, is_tabbable = false) => $gVhhF$solidjsweb.createComponent($f8f64d05c525825b$var$OpenSortingButton, {
@@ -6100,7 +6121,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
6100
6121
  available_sortings_: available_sortings_,
6101
6122
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
6102
6123
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
6103
- on_user_open_: () => user_opened_panel = true,
6124
+ on_user_open_: keyboard_activated => {
6125
+ if (keyboard_activated) user_opened_panel = true;
6126
+ },
6104
6127
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
6105
6128
  });
6106
6129
  let open_modal_;
@@ -6126,7 +6149,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
6126
6149
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
6127
6150
  current_panel = undefined;
6128
6151
  current_panel_toggle_button = undefined;
6129
- if (focus_was_in_panel) button_to_restore?.focus();
6152
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
6153
+ preventScroll: true
6154
+ });
6130
6155
  };
6131
6156
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
6132
6157
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -6264,12 +6289,13 @@ function $f8f64d05c525825b$var$OpenFiltersButton({
6264
6289
  return _el$15;
6265
6290
  }
6266
6291
  }), _el$21, _co$5);
6267
- $gVhhF$solidjsweb.addEventListener(_el$16, "click", $gVhhF$depictaiutilishared.catchify(() => $gVhhF$solidjs.batch(() => {
6292
+ $gVhhF$solidjsweb.addEventListener(_el$16, "click", $gVhhF$depictaiutilishared.catchify(event => $gVhhF$solidjs.batch(() => {
6268
6293
  if (search_filters_open_[0]()) {
6269
6294
  search_filters_open_[1](false);
6270
6295
  return;
6271
6296
  }
6272
- on_user_open_?.();
6297
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6298
+ on_user_open_?.($fb96fea58c4a45dd$export$c5c485c196a19ec1(event));
6273
6299
  search_filters_open_[1](true);
6274
6300
  search_sorting_open_[1](false);
6275
6301
  })), true);
@@ -6338,12 +6364,13 @@ function $f8f64d05c525825b$var$OpenSortingButton({
6338
6364
  _el$23 = _el$22.firstChild,
6339
6365
  _el$24 = _el$23.nextSibling,
6340
6366
  [_el$25, _co$6] = $gVhhF$solidjsweb.getNextMarker(_el$24.nextSibling);
6341
- $gVhhF$solidjsweb.addEventListener(_el$22, "click", $gVhhF$depictaiutilishared.catchify(() => $gVhhF$solidjs.batch(() => {
6367
+ $gVhhF$solidjsweb.addEventListener(_el$22, "click", $gVhhF$depictaiutilishared.catchify(event => $gVhhF$solidjs.batch(() => {
6342
6368
  if (search_sorting_open_[0]()) {
6343
6369
  search_sorting_open_[1](false);
6344
6370
  return;
6345
6371
  }
6346
- on_user_open_?.();
6372
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6373
+ on_user_open_?.($fb96fea58c4a45dd$export$c5c485c196a19ec1(event));
6347
6374
  search_filters_open_[1](false);
6348
6375
  search_sorting_open_[1](true);
6349
6376
  })), true);
package/latest/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import { GetListingRequest } from "@depict-ai/types/api/GetListingRequest";
11
11
  import { BaseSearchRequestV3 } from "@depict-ai/types/api/BaseSearchRequestV3";
12
12
  import { FeaturedInDisplay } from "@depict-ai/types/api/FeaturedInResponseV3";
13
13
  import { SearchFilter as _SearchFilter3 } from "@depict-ai/types/api/SearchRequestV2";
14
- export const version = "4.10.14";
14
+ export const version = "4.10.16";
15
15
  /**
16
16
  * Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
17
17
  */
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.14";
10
+ const $ec291e0010116877$export$83d89fbfd8236492 = "4.10.16";
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, ({
@@ -2596,6 +2596,14 @@ function $f8a56ba74eedd0c6$export$f21ab0717a89c77f(props) {
2596
2596
  return _el$;
2597
2597
  })();
2598
2598
  }
2599
+
2600
+ /**
2601
+ * Whether a click came from the keyboard (Enter/Space) rather than a pointer. Browsers report `detail === 0` for
2602
+ * keyboard-activated clicks and `>= 1` for real pointer clicks, so we use it to only move focus on keyboard opens.
2603
+ */
2604
+ function $5108d4f5c200e4e5$export$c5c485c196a19ec1(event) {
2605
+ return event.detail === 0;
2606
+ }
2599
2607
  var $67b173f9db427028$var$_tmpl$ = /*#__PURE__*/$9HbP8$template(`<button type=button class=expand-filter><!$><!/><span>`);
2600
2608
  function $67b173f9db427028$export$ca21a16d65b3dd8({
2601
2609
  show_extras_: [get_show_extras, set_show_extras],
@@ -2611,24 +2619,23 @@ function $67b173f9db427028$export$ca21a16d65b3dd8({
2611
2619
  $9HbP8$addEventListener(_el$, "click", $9HbP8$catchify1(event => {
2612
2620
  const container = expanding_container_element_;
2613
2621
  const will_expand = !get_show_extras();
2614
- // A click from Enter/Space on the button reports `detail === 0`; a real pointer click reports >= 1.
2615
- // Only hijack focus for keyboard activation - mouse users can see the revealed options and don't need it
2616
- // (and would otherwise get the viewport scrolled and an unexpected focus ring).
2617
- const keyboard_activated = event.detail === 0;
2622
+ // Only move focus for keyboard activation; mouse users see the revealed options and don't need a focus jump.
2623
+ const keyboard_activated = $5108d4f5c200e4e5$export$c5c485c196a19ec1(event);
2618
2624
  const had_focus_inside = !!container && container.contains(document.activeElement);
2619
2625
  set_show_extras(will_expand);
2620
2626
  if (will_expand) {
2621
2627
  if (!keyboard_activated) return;
2622
- // The container's `expand()` (run from the consumer's effect after this handler) clears `inert`/`visibility`;
2623
- // focus the first revealed option on the next frame so Tab continues through the newly shown options.
2624
- // `preventScroll` so moving focus never yanks the viewport down to the first checkbox.
2628
+ // `expand()` (consumer's effect, runs after this) clears `inert`/`visibility`; focus the first revealed
2629
+ // option next frame so Tab continues through them. `preventScroll` so it doesn't yank the viewport down.
2625
2630
  requestAnimationFrame($9HbP8$catchify1(() => container?.querySelector("input:not(:disabled)")?.focus({
2626
2631
  preventScroll: true
2627
2632
  })));
2628
2633
  } else if (had_focus_inside)
2629
2634
  // Keep focus on the toggle when collapsing, otherwise making the container `inert` dumps focus to <body>
2630
2635
  // (Safari doesn't focus buttons on mouse click, so focus can still be inside the container here).
2631
- button.focus();
2636
+ button.focus({
2637
+ preventScroll: true
2638
+ });
2632
2639
  }), true);
2633
2640
  var _ref$ = button;
2634
2641
  typeof _ref$ === "function" ? $9HbP8$use(_ref$, _el$) : button = _el$;
@@ -5957,10 +5964,10 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
5957
5964
  available_sortings_: available_sortings_,
5958
5965
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
5959
5966
  };
5960
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
5961
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
5962
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
5963
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
5967
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
5968
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
5969
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
5970
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
5964
5971
  let user_opened_panel = false;
5965
5972
  let filter_toggle_button;
5966
5973
  let sort_toggle_button;
@@ -5971,7 +5978,19 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
5971
5978
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
5972
5979
  // listener it registers - referenced forever.
5973
5980
  await (0, $9HbP8$observer).wait_for_element(panel, 4000);
5974
- if (panel.isConnected) panel.focus();
5981
+ if (panel.isConnected) {
5982
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
5983
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
5984
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
5985
+ // by the input/button/etc. selectors, so it must be listed explicitly.
5986
+ const focus_target = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])") ?? panel;
5987
+ focus_target.focus({
5988
+ preventScroll: true
5989
+ });
5990
+ focus_target.scrollIntoView({
5991
+ block: "nearest"
5992
+ });
5993
+ }
5975
5994
  })();
5976
5995
  const register_desktop_panel = (el, toggle_button, should_focus) => {
5977
5996
  current_panel = el;
@@ -5986,7 +6005,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
5986
6005
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
5987
6006
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
5988
6007
  hide_button_: hide_filters,
5989
- on_user_open_: () => user_opened_panel = true,
6008
+ on_user_open_: keyboard_activated => {
6009
+ if (keyboard_activated) user_opened_panel = true;
6010
+ },
5990
6011
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
5991
6012
  });
5992
6013
  const make_open_sorting_button = (adhere_to_width = false, is_tabbable = false) => $9HbP8$createComponent($cdea4cf8c5c071ef$var$OpenSortingButton, {
@@ -5998,7 +6019,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
5998
6019
  available_sortings_: available_sortings_,
5999
6020
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
6000
6021
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
6001
- on_user_open_: () => user_opened_panel = true,
6022
+ on_user_open_: keyboard_activated => {
6023
+ if (keyboard_activated) user_opened_panel = true;
6024
+ },
6002
6025
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
6003
6026
  });
6004
6027
  let open_modal_;
@@ -6024,7 +6047,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
6024
6047
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
6025
6048
  current_panel = undefined;
6026
6049
  current_panel_toggle_button = undefined;
6027
- if (focus_was_in_panel) button_to_restore?.focus();
6050
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
6051
+ preventScroll: true
6052
+ });
6028
6053
  };
6029
6054
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
6030
6055
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -6162,12 +6187,13 @@ function $cdea4cf8c5c071ef$var$OpenFiltersButton({
6162
6187
  return _el$15;
6163
6188
  }
6164
6189
  }), _el$21, _co$5);
6165
- $9HbP8$addEventListener(_el$16, "click", $9HbP8$catchify1(() => $9HbP8$batch(() => {
6190
+ $9HbP8$addEventListener(_el$16, "click", $9HbP8$catchify1(event => $9HbP8$batch(() => {
6166
6191
  if (search_filters_open_[0]()) {
6167
6192
  search_filters_open_[1](false);
6168
6193
  return;
6169
6194
  }
6170
- on_user_open_?.();
6195
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6196
+ on_user_open_?.($5108d4f5c200e4e5$export$c5c485c196a19ec1(event));
6171
6197
  search_filters_open_[1](true);
6172
6198
  search_sorting_open_[1](false);
6173
6199
  })), true);
@@ -6236,12 +6262,13 @@ function $cdea4cf8c5c071ef$var$OpenSortingButton({
6236
6262
  _el$23 = _el$22.firstChild,
6237
6263
  _el$24 = _el$23.nextSibling,
6238
6264
  [_el$25, _co$6] = $9HbP8$getNextMarker(_el$24.nextSibling);
6239
- $9HbP8$addEventListener(_el$22, "click", $9HbP8$catchify1(() => $9HbP8$batch(() => {
6265
+ $9HbP8$addEventListener(_el$22, "click", $9HbP8$catchify1(event => $9HbP8$batch(() => {
6240
6266
  if (search_sorting_open_[0]()) {
6241
6267
  search_sorting_open_[1](false);
6242
6268
  return;
6243
6269
  }
6244
- on_user_open_?.();
6270
+ // Only keyboard opens move focus into the panel; mouse opens leave the viewport put.
6271
+ on_user_open_?.($5108d4f5c200e4e5$export$c5c485c196a19ec1(event));
6245
6272
  search_filters_open_[1](false);
6246
6273
  search_sorting_open_[1](true);
6247
6274
  })), true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depict-ai/ui",
3
- "version": "4.10.14",
3
+ "version": "4.10.16",
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",
@@ -234,11 +234,11 @@
234
234
  },
235
235
  "dependencies": {
236
236
  "@babel/plugin-transform-typescript": "^7.22.9",
237
- "@babel/runtime": "latest",
237
+ "@babel/runtime": "^7.22.6",
238
238
  "@babel/runtime-corejs3": "^7.22.6",
239
- "@depict-ai/plp-styling": "^4.6.6",
240
- "@depict-ai/types": "^5.6.4",
241
- "@depict-ai/utilishared": "^2.6.4",
239
+ "@depict-ai/plp-styling": "^4.6.8",
240
+ "@depict-ai/types": "^5.6.6",
241
+ "@depict-ai/utilishared": "^2.6.6",
242
242
  "solid-js": "^1.9.10"
243
243
  },
244
244
  "type": "module",
@@ -115,7 +115,7 @@ $parcel$export(module.exports, "BreadCrumbs", () => $335c02c1241a9ca8$export$5b7
115
115
  $parcel$export(module.exports, "QuickLinks", () => $335c02c1241a9ca8$export$de035477d6fef996);
116
116
  $parcel$export(module.exports, "CategoryPage", () => $c10e33c4681f8c9b$export$e2bf8ce7779e827e);
117
117
  /*! Depict.ai search and product listing SDK */
118
- const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.10.14";
118
+ const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.10.16";
119
119
  function $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query) {
120
120
  const signal = $3hooq$solidjs.createSignal(false);
121
121
  $3hooq$solidjs.onCleanup($3hooq$depictaiutilishared.javascript_media_query(media_query, _ref => {
@@ -5087,10 +5087,10 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
5087
5087
  available_sortings_: available_sortings_,
5088
5088
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
5089
5089
  };
5090
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
5091
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
5092
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
5093
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
5090
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
5091
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
5092
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
5093
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
5094
5094
  let user_opened_panel = false;
5095
5095
  let filter_toggle_button;
5096
5096
  let sort_toggle_button;
@@ -5101,7 +5101,20 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
5101
5101
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
5102
5102
  // listener it registers - referenced forever.
5103
5103
  await (0, $3hooq$depictaiutilishared.observer).wait_for_element(panel, 4000);
5104
- if (panel.isConnected) panel.focus();
5104
+ if (panel.isConnected) {
5105
+ var _panel$querySelector;
5106
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
5107
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
5108
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
5109
+ // by the input/button/etc. selectors, so it must be listed explicitly.
5110
+ const focus_target = (_panel$querySelector = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])")) !== null && _panel$querySelector !== void 0 ? _panel$querySelector : panel;
5111
+ focus_target.focus({
5112
+ preventScroll: true
5113
+ });
5114
+ focus_target.scrollIntoView({
5115
+ block: "nearest"
5116
+ });
5117
+ }
5105
5118
  })();
5106
5119
  const register_desktop_panel = (el, toggle_button, should_focus) => {
5107
5120
  current_panel = el;
@@ -5119,7 +5132,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
5119
5132
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
5120
5133
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
5121
5134
  hide_button_: hide_filters,
5122
- on_user_open_: () => user_opened_panel = true,
5135
+ on_user_open_: keyboard_activated => {
5136
+ if (keyboard_activated) user_opened_panel = true;
5137
+ },
5123
5138
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
5124
5139
  });
5125
5140
  };
@@ -5135,7 +5150,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
5135
5150
  available_sortings_: available_sortings_,
5136
5151
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
5137
5152
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
5138
- on_user_open_: () => user_opened_panel = true,
5153
+ on_user_open_: keyboard_activated => {
5154
+ if (keyboard_activated) user_opened_panel = true;
5155
+ },
5139
5156
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
5140
5157
  });
5141
5158
  };
@@ -5162,7 +5179,9 @@ function $f70cc6dfcadf0fd5$export$d7841e452f2e59a8(_ref) {
5162
5179
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
5163
5180
  current_panel = undefined;
5164
5181
  current_panel_toggle_button = undefined;
5165
- if (focus_was_in_panel) button_to_restore === null || button_to_restore === void 0 || button_to_restore.focus();
5182
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
5183
+ preventScroll: true
5184
+ });
5166
5185
  };
5167
5186
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
5168
5187
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -11,7 +11,7 @@ import { GetListingRequest } from "@depict-ai/types/api/GetListingRequest";
11
11
  import { BaseSearchRequestV3 } from "@depict-ai/types/api/BaseSearchRequestV3";
12
12
  import { FeaturedInDisplay } from "@depict-ai/types/api/FeaturedInResponseV3";
13
13
  import { SearchFilter as _SearchFilter3 } from "@depict-ai/types/api/SearchRequestV2";
14
- export const version = "4.10.14";
14
+ export const version = "4.10.16";
15
15
  /**
16
16
  * Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
17
17
  */
@@ -10,7 +10,7 @@ import $b8hua$babelruntimehelpersclassPrivateFieldGet from "@babel/runtime/helpe
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.10.14";
13
+ const $8db9a15135765c11$export$83d89fbfd8236492 = "4.10.16";
14
14
  function $00a5b94f0c11efbb$export$d9f36cf74e24d595(media_query) {
15
15
  const signal = $b8hua$createSignal(false);
16
16
  $b8hua$onCleanup($b8hua$javascript_media_query(media_query, _ref => {
@@ -4982,10 +4982,10 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
4982
4982
  available_sortings_: available_sortings_,
4983
4983
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
4984
4984
  };
4985
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
4986
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
4987
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
4988
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
4985
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
4986
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
4987
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
4988
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
4989
4989
  let user_opened_panel = false;
4990
4990
  let filter_toggle_button;
4991
4991
  let sort_toggle_button;
@@ -4996,7 +4996,20 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
4996
4996
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
4997
4997
  // listener it registers - referenced forever.
4998
4998
  await (0, $b8hua$observer).wait_for_element(panel, 4000);
4999
- if (panel.isConnected) panel.focus();
4999
+ if (panel.isConnected) {
5000
+ var _panel$querySelector;
5001
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
5002
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
5003
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
5004
+ // by the input/button/etc. selectors, so it must be listed explicitly.
5005
+ const focus_target = (_panel$querySelector = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])")) !== null && _panel$querySelector !== void 0 ? _panel$querySelector : panel;
5006
+ focus_target.focus({
5007
+ preventScroll: true
5008
+ });
5009
+ focus_target.scrollIntoView({
5010
+ block: "nearest"
5011
+ });
5012
+ }
5000
5013
  })();
5001
5014
  const register_desktop_panel = (el, toggle_button, should_focus) => {
5002
5015
  current_panel = el;
@@ -5014,7 +5027,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
5014
5027
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
5015
5028
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
5016
5029
  hide_button_: hide_filters,
5017
- on_user_open_: () => user_opened_panel = true,
5030
+ on_user_open_: keyboard_activated => {
5031
+ if (keyboard_activated) user_opened_panel = true;
5032
+ },
5018
5033
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
5019
5034
  });
5020
5035
  };
@@ -5030,7 +5045,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
5030
5045
  available_sortings_: available_sortings_,
5031
5046
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
5032
5047
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
5033
- on_user_open_: () => user_opened_panel = true,
5048
+ on_user_open_: keyboard_activated => {
5049
+ if (keyboard_activated) user_opened_panel = true;
5050
+ },
5034
5051
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
5035
5052
  });
5036
5053
  };
@@ -5057,7 +5074,9 @@ function $7396052a1484264f$export$d7841e452f2e59a8(_ref) {
5057
5074
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
5058
5075
  current_panel = undefined;
5059
5076
  current_panel_toggle_button = undefined;
5060
- if (focus_was_in_panel) button_to_restore === null || button_to_restore === void 0 || button_to_restore.focus();
5077
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
5078
+ preventScroll: true
5079
+ });
5061
5080
  };
5062
5081
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
5063
5082
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -109,7 +109,7 @@ $parcel$export(module.exports, "BreadCrumbs", () => $1f4925833f07df29$export$5b7
109
109
  $parcel$export(module.exports, "QuickLinks", () => $1f4925833f07df29$export$de035477d6fef996);
110
110
  $parcel$export(module.exports, "CategoryPage", () => $14f289047713d67a$export$e2bf8ce7779e827e);
111
111
  /*! Depict.ai search and product listing SDK */
112
- const $b757f75811f3261f$export$83d89fbfd8236492 = "4.10.14";
112
+ const $b757f75811f3261f$export$83d89fbfd8236492 = "4.10.16";
113
113
  function $b54e6192d0caa293$export$d9f36cf74e24d595(media_query) {
114
114
  const signal = $5vyXB$solidjs.createSignal(false);
115
115
  $5vyXB$solidjs.onCleanup($5vyXB$depictaiutilishared.javascript_media_query(media_query, ({
@@ -4783,10 +4783,10 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
4783
4783
  available_sortings_: available_sortings_,
4784
4784
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
4785
4785
  };
4786
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
4787
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
4788
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
4789
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
4786
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
4787
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
4788
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
4789
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
4790
4790
  let user_opened_panel = false;
4791
4791
  let filter_toggle_button;
4792
4792
  let sort_toggle_button;
@@ -4797,7 +4797,19 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
4797
4797
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
4798
4798
  // listener it registers - referenced forever.
4799
4799
  await (0, $5vyXB$depictaiutilishared.observer).wait_for_element(panel, 4000);
4800
- if (panel.isConnected) panel.focus();
4800
+ if (panel.isConnected) {
4801
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
4802
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
4803
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
4804
+ // by the input/button/etc. selectors, so it must be listed explicitly.
4805
+ const focus_target = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])") ?? panel;
4806
+ focus_target.focus({
4807
+ preventScroll: true
4808
+ });
4809
+ focus_target.scrollIntoView({
4810
+ block: "nearest"
4811
+ });
4812
+ }
4801
4813
  })();
4802
4814
  const register_desktop_panel = (el, toggle_button, should_focus) => {
4803
4815
  current_panel = el;
@@ -4812,7 +4824,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
4812
4824
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
4813
4825
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
4814
4826
  hide_button_: hide_filters,
4815
- on_user_open_: () => user_opened_panel = true,
4827
+ on_user_open_: keyboard_activated => {
4828
+ if (keyboard_activated) user_opened_panel = true;
4829
+ },
4816
4830
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
4817
4831
  });
4818
4832
  const make_open_sorting_button = (adhere_to_width = false, is_tabbable = false) => $5vyXB$solidjsweb.createComponent($f8f64d05c525825b$var$OpenSortingButton, {
@@ -4824,7 +4838,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
4824
4838
  available_sortings_: available_sortings_,
4825
4839
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
4826
4840
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
4827
- on_user_open_: () => user_opened_panel = true,
4841
+ on_user_open_: keyboard_activated => {
4842
+ if (keyboard_activated) user_opened_panel = true;
4843
+ },
4828
4844
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
4829
4845
  });
4830
4846
  let open_modal_;
@@ -4850,7 +4866,9 @@ function $f8f64d05c525825b$export$d7841e452f2e59a8({
4850
4866
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
4851
4867
  current_panel = undefined;
4852
4868
  current_panel_toggle_button = undefined;
4853
- if (focus_was_in_panel) button_to_restore?.focus();
4869
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
4870
+ preventScroll: true
4871
+ });
4854
4872
  };
4855
4873
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
4856
4874
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids
@@ -11,7 +11,7 @@ import { GetListingRequest } from "@depict-ai/types/api/GetListingRequest";
11
11
  import { BaseSearchRequestV3 } from "@depict-ai/types/api/BaseSearchRequestV3";
12
12
  import { FeaturedInDisplay } from "@depict-ai/types/api/FeaturedInResponseV3";
13
13
  import { SearchFilter as _SearchFilter3 } from "@depict-ai/types/api/SearchRequestV2";
14
- export const version = "4.10.14";
14
+ export const version = "4.10.16";
15
15
  /**
16
16
  * Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
17
17
  */
@@ -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.14";
10
+ const $ec291e0010116877$export$83d89fbfd8236492 = "4.10.16";
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, ({
@@ -4681,10 +4681,10 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
4681
4681
  available_sortings_: available_sortings_,
4682
4682
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_
4683
4683
  };
4684
- // Keyboard accessibility for the desktop panels (rendered after the product grid in the DOM): when the user
4685
- // opens a panel we move focus into it, and restore focus to the toggle button on close. Intent is tracked with
4686
- // a plain flag set in the buttons' click handlers - `filters_open`/`sorting_open` also change programmatically
4687
- // (undo toast, history-state restore, SDK consumers), and those must not steal focus.
4684
+ // Keyboard a11y for desktop panels (DOM order: after the grid). Keyboard opens move focus into the panel and
4685
+ // restore it to the toggle on close; mouse opens skip the focus move (already visible, and it'd jump the viewport).
4686
+ // `user_opened_panel` is set only on keyboard activation - `filters_open`/`sorting_open` also change
4687
+ // programmatically (undo toast, history restore, SDK consumers), which must not steal focus.
4688
4688
  let user_opened_panel = false;
4689
4689
  let filter_toggle_button;
4690
4690
  let sort_toggle_button;
@@ -4695,7 +4695,19 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
4695
4695
  // insertion), the timeout lets this promise resolve instead of keeping `panel` - and the observer
4696
4696
  // listener it registers - referenced forever.
4697
4697
  await (0, $i7OB2$observer).wait_for_element(panel, 4000);
4698
- if (panel.isConnected) panel.focus();
4698
+ if (panel.isConnected) {
4699
+ // Focus the first interactive control (often a group's <summary>), not the <section>: the section has no
4700
+ // visible focus ring and is flex-stretched to full grid height (scrolling it mis-aligns). The first
4701
+ // control keeps focus visible and lets Tab walk through the panel. `summary` is focusable but not matched
4702
+ // by the input/button/etc. selectors, so it must be listed explicitly.
4703
+ const focus_target = panel.querySelector("summary, input:not([type='hidden']):not(:disabled), button:not(:disabled), a[href], select:not(:disabled), [tabindex]:not([tabindex='-1'])") ?? panel;
4704
+ focus_target.focus({
4705
+ preventScroll: true
4706
+ });
4707
+ focus_target.scrollIntoView({
4708
+ block: "nearest"
4709
+ });
4710
+ }
4699
4711
  })();
4700
4712
  const register_desktop_panel = (el, toggle_button, should_focus) => {
4701
4713
  current_panel = el;
@@ -4710,7 +4722,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
4710
4722
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
4711
4723
  filter_button_width_: adhere_to_width ? filter_button_width_ : undefined,
4712
4724
  hide_button_: hide_filters,
4713
- on_user_open_: () => user_opened_panel = true,
4725
+ on_user_open_: keyboard_activated => {
4726
+ if (keyboard_activated) user_opened_panel = true;
4727
+ },
4714
4728
  button_ref_: is_tabbable ? el => filter_toggle_button = el : undefined
4715
4729
  });
4716
4730
  const make_open_sorting_button = (adhere_to_width = false, is_tabbable = false) => $i7OB2$createComponent($cdea4cf8c5c071ef$var$OpenSortingButton, {
@@ -4722,7 +4736,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
4722
4736
  available_sortings_: available_sortings_,
4723
4737
  sort_button_width_: adhere_to_width ? sort_button_width_ : undefined,
4724
4738
  meta_of_currently_selected_sorting_: meta_of_currently_selected_sorting_,
4725
- on_user_open_: () => user_opened_panel = true,
4739
+ on_user_open_: keyboard_activated => {
4740
+ if (keyboard_activated) user_opened_panel = true;
4741
+ },
4726
4742
  button_ref_: is_tabbable ? el => sort_toggle_button = el : undefined
4727
4743
  });
4728
4744
  let open_modal_;
@@ -4748,7 +4764,9 @@ function $cdea4cf8c5c071ef$export$d7841e452f2e59a8({
4748
4764
  const focus_was_in_panel = !!current_panel && current_panel.contains(document.activeElement);
4749
4765
  current_panel = undefined;
4750
4766
  current_panel_toggle_button = undefined;
4751
- if (focus_was_in_panel) button_to_restore?.focus();
4767
+ if (focus_was_in_panel && button_to_restore) button_to_restore.focus({
4768
+ preventScroll: true
4769
+ });
4752
4770
  };
4753
4771
  // `<section>` + `aria-label` so the panel announces itself ("Filters"/"Sort") when we move focus to it; the bare
4754
4772
  // tabindex=-1 container would otherwise give screen readers nothing to read on focus. A semantic <section> avoids