@limetech/lime-elements 38.33.6 → 38.33.7

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.
@@ -2510,10 +2510,10 @@ const Menu = class {
2510
2510
  if (breadcrumbsItems.length === 0) {
2511
2511
  return;
2512
2512
  }
2513
- return (h("limel-breadcrumbs", { style: {
2513
+ return (h("limel-breadcrumbs", { ref: this.setBreadcrumbsElement, style: {
2514
2514
  'border-bottom': 'solid 1px rgb(var(--contrast-500))',
2515
2515
  'flex-shrink': '0',
2516
- }, onSelect: this.handleBreadcrumbsSelect, items: breadcrumbsItems }));
2516
+ }, onSelect: this.handleBreadcrumbsSelect, onKeyDown: this.handleBreadcrumbsKeyDown, items: breadcrumbsItems }));
2517
2517
  };
2518
2518
  this.handleBreadcrumbsSelect = (event) => {
2519
2519
  if (!event.detail.menuItem) {
@@ -2578,8 +2578,8 @@ const Menu = class {
2578
2578
  this.loadingSubItems = false;
2579
2579
  };
2580
2580
  // Key handler for the input search field
2581
- // Will change focus to the first/last item in the dropdown
2582
- // list to enable selection with the keyboard
2581
+ // Will change focus to breadcrumbs (if present) or the first/last item
2582
+ // in the dropdown list to enable selection with the keyboard
2583
2583
  this.handleInputKeyDown = (event) => {
2584
2584
  const isForwardTab = event.key === TAB &&
2585
2585
  !event.altKey &&
@@ -2590,26 +2590,58 @@ const Menu = class {
2590
2590
  if (!isForwardTab && !isUp && !isDown) {
2591
2591
  return;
2592
2592
  }
2593
- if (!this.list) {
2594
- return;
2595
- }
2596
2593
  event.stopPropagation();
2597
2594
  event.preventDefault();
2598
2595
  if (isForwardTab || isDown) {
2599
- const listItems = this.list.shadowRoot.querySelectorAll('.mdc-deprecated-list-item');
2600
- const listElement = listItems[0];
2601
- listElement === null || listElement === void 0 ? void 0 : listElement.focus();
2596
+ if (this.focusBreadcrumbs()) {
2597
+ return;
2598
+ }
2599
+ this.focusFirstListItem();
2602
2600
  return;
2603
2601
  }
2604
2602
  if (isUp) {
2605
- const listItems = this.list.shadowRoot.querySelectorAll('.mdc-deprecated-list-item');
2606
- const listElement = [...listItems].at(-1);
2607
- listElement === null || listElement === void 0 ? void 0 : listElement.focus();
2603
+ // Focus the last list item (wrapping behavior)
2604
+ this.focusLastListItem();
2608
2605
  }
2609
2606
  };
2610
- // Key handler for the menu list
2607
+ // Key handler for the menu list (capture phase)
2608
+ // Handles Up arrow on first item and Down arrow on last item
2609
+ // Must run in capture phase to intercept before MDC Menu wraps focus
2610
+ // Only intercepts when there's a search input or breadcrumbs to navigate to
2611
+ this.handleListKeyDownCapture = (event) => {
2612
+ const isUp = event.key === ARROW_UP;
2613
+ const isDown = event.key === ARROW_DOWN;
2614
+ if (!isUp && !isDown) {
2615
+ return;
2616
+ }
2617
+ // Up on first item: go to breadcrumbs or search input (if they exist)
2618
+ if (isUp && this.isFirstListItemFocused()) {
2619
+ // Try to focus breadcrumbs first
2620
+ if (this.focusBreadcrumbs()) {
2621
+ event.stopPropagation();
2622
+ event.preventDefault();
2623
+ return;
2624
+ }
2625
+ // Then try search input
2626
+ if (this.searchInput) {
2627
+ event.stopPropagation();
2628
+ event.preventDefault();
2629
+ this.searchInput.focus();
2630
+ }
2631
+ // If neither exists, let MDC Menu handle wrap-around
2632
+ return;
2633
+ }
2634
+ // Down on last item: go to search input (if it exists)
2635
+ if (isDown && this.isLastListItemFocused() && this.searchInput) {
2636
+ event.stopPropagation();
2637
+ event.preventDefault();
2638
+ this.searchInput.focus();
2639
+ }
2640
+ // If no search input, let MDC Menu handle wrap-around
2641
+ };
2642
+ // Key handler for the menu list (bubble phase)
2611
2643
  // Will change focus to the search field if using shift+tab
2612
- // And can go forward/back with righ/left arrow keys
2644
+ // And can go forward/back with right/left arrow keys
2613
2645
  this.handleMenuKeyDown = (event) => {
2614
2646
  var _a;
2615
2647
  const isBackwardTab = event.key === TAB &&
@@ -2625,8 +2657,9 @@ const Menu = class {
2625
2657
  event.stopPropagation();
2626
2658
  event.preventDefault();
2627
2659
  (_a = this.searchInput) === null || _a === void 0 ? void 0 : _a.focus();
2660
+ return;
2628
2661
  }
2629
- else if (!this.gridLayout) {
2662
+ if (!this.gridLayout && (isLeft || isRight)) {
2630
2663
  const currentItem = this.getCurrentItem();
2631
2664
  event.stopPropagation();
2632
2665
  event.preventDefault();
@@ -2638,17 +2671,43 @@ const Menu = class {
2638
2671
  }
2639
2672
  }
2640
2673
  };
2674
+ // Key handler for breadcrumbs
2675
+ // Up arrow: focus search input
2676
+ // Down arrow: focus first list item
2677
+ this.handleBreadcrumbsKeyDown = (event) => {
2678
+ var _a;
2679
+ const isUp = event.key === ARROW_UP;
2680
+ const isDown = event.key === ARROW_DOWN;
2681
+ if (!isUp && !isDown) {
2682
+ return;
2683
+ }
2684
+ event.stopPropagation();
2685
+ event.preventDefault();
2686
+ if (isUp) {
2687
+ (_a = this.searchInput) === null || _a === void 0 ? void 0 : _a.focus();
2688
+ return;
2689
+ }
2690
+ if (isDown) {
2691
+ this.focusFirstListItem();
2692
+ }
2693
+ };
2641
2694
  this.clearSearch = () => {
2642
2695
  this.searchValue = '';
2643
2696
  this.searchResults = null;
2644
2697
  this.loadingSubItems = false;
2645
2698
  };
2646
2699
  this.getCurrentItem = () => {
2647
- var _a, _b, _c;
2648
- const activeItem = (_b = (_a = this.list) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('[role="menuitem"][tabindex="0"]');
2649
- const attrIndex = (_c = activeItem === null || activeItem === void 0 ? void 0 : activeItem.attributes) === null || _c === void 0 ? void 0 : _c.getNamedItem('data-index');
2650
- const dataIndex = Number.parseInt((attrIndex === null || attrIndex === void 0 ? void 0 : attrIndex.value) || '0', 10);
2651
- return this.visibleItems[dataIndex];
2700
+ var _a, _b, _c, _d, _e, _f;
2701
+ let menuElement = (_c = (_b = (_a = this.list) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.activeElement) !== null && _c !== void 0 ? _c : null;
2702
+ if (menuElement && menuElement.getAttribute('role') !== 'menuitem') {
2703
+ menuElement = menuElement.closest('[role="menuitem"]');
2704
+ }
2705
+ if (!menuElement) {
2706
+ menuElement = (_e = (_d = this.list) === null || _d === void 0 ? void 0 : _d.shadowRoot) === null || _e === void 0 ? void 0 : _e.querySelector('[role="menuitem"][tabindex="0"]');
2707
+ }
2708
+ const dataIndex = Number.parseInt((_f = menuElement === null || menuElement === void 0 ? void 0 : menuElement.dataset.index) !== null && _f !== void 0 ? _f : '0', 10);
2709
+ const item = this.visibleItems[dataIndex];
2710
+ return (item !== null && item !== void 0 ? item : this.visibleItems[0]);
2652
2711
  };
2653
2712
  this.goForward = (currentItem) => {
2654
2713
  this.handleSelect(currentItem, false);
@@ -2741,7 +2800,13 @@ const Menu = class {
2741
2800
  this.handleSelect(event.detail);
2742
2801
  };
2743
2802
  this.setListElement = (element) => {
2803
+ if (this.list) {
2804
+ this.list.removeEventListener('keydown', this.handleListKeyDownCapture, true);
2805
+ }
2744
2806
  this.list = element;
2807
+ if (this.list) {
2808
+ this.list.addEventListener('keydown', this.handleListKeyDownCapture, true);
2809
+ }
2745
2810
  };
2746
2811
  this.setFocus = () => {
2747
2812
  setTimeout(() => {
@@ -2767,6 +2832,67 @@ const Menu = class {
2767
2832
  this.setSearchElement = (element) => {
2768
2833
  this.searchInput = element;
2769
2834
  };
2835
+ this.setBreadcrumbsElement = (element) => {
2836
+ this.breadcrumbs = element;
2837
+ };
2838
+ /**
2839
+ * Focuses the first focusable element inside breadcrumbs.
2840
+ * Returns true if breadcrumbs exist and were focused,
2841
+ * false otherwise.
2842
+ */
2843
+ this.focusBreadcrumbs = () => {
2844
+ var _a;
2845
+ if (!this.breadcrumbs) {
2846
+ return false;
2847
+ }
2848
+ const focusableElement = (_a = this.breadcrumbs.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('button, a');
2849
+ if (focusableElement) {
2850
+ focusableElement.focus();
2851
+ return true;
2852
+ }
2853
+ return false;
2854
+ };
2855
+ this.focusFirstListItem = () => {
2856
+ const listItems = this.getListItems();
2857
+ const firstItem = listItems === null || listItems === void 0 ? void 0 : listItems[0];
2858
+ firstItem === null || firstItem === void 0 ? void 0 : firstItem.focus();
2859
+ };
2860
+ this.focusLastListItem = () => {
2861
+ const listItems = this.getListItems();
2862
+ const lastItem = listItems === null || listItems === void 0 ? void 0 : listItems.at(-1);
2863
+ lastItem === null || lastItem === void 0 ? void 0 : lastItem.focus();
2864
+ };
2865
+ this.isFirstListItemFocused = () => {
2866
+ var _a;
2867
+ const listItems = this.getListItems();
2868
+ if (!listItems) {
2869
+ return false;
2870
+ }
2871
+ const firstItem = listItems[0];
2872
+ const activeElement = (_a = this.list.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement;
2873
+ return firstItem === activeElement;
2874
+ };
2875
+ this.isLastListItemFocused = () => {
2876
+ var _a;
2877
+ const listItems = this.getListItems();
2878
+ if (!listItems) {
2879
+ return false;
2880
+ }
2881
+ const lastItem = listItems.at(-1);
2882
+ const activeElement = (_a = this.list.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement;
2883
+ return lastItem === activeElement;
2884
+ };
2885
+ this.getListItems = () => {
2886
+ var _a;
2887
+ if (!this.list) {
2888
+ return null;
2889
+ }
2890
+ const items = (_a = this.list.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.mdc-deprecated-list-item');
2891
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
2892
+ return null;
2893
+ }
2894
+ return [...items];
2895
+ };
2770
2896
  this.focusMenuItem = () => {
2771
2897
  var _a;
2772
2898
  if (!this.list) {